1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     ut_Float24.h
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Revision: 24277 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NW_UT_FLOAT24_H_
17 #define NW_UT_FLOAT24_H_
18 
19 #include <nw/ut/ut_Inlines.h>
20 #include <nw/math/math_Types.h>
21 
22 namespace nw {
23 namespace ut {
24 
25 //--------------------------------------------------------------------------
26 //! @brief        32bit 浮動小数用のユーティリティです。
27 //
28 // 32bit 浮動小数のビットフォーマットは次の通りです。
29 // | sign | exponent | fraction |
30 // sign     : 符号 1 bit.
31 // exponent : 指数部 8 bit. bias 127.
32 // fraction : 仮数部 23 bit.
33 //---------------------------------------------------------------------------
34 class Float32
35 {
36 public:
37     //--------------------------------------------------------------------------
38     //! @brief        f32 から 32bit 浮動小数のビット表現に変換します。
39     //!
40     //! @param[in]    value   32bit float の値です。
41     //!
42     //! @return       32bit 浮動小数のビット表現を返します。
43     //--------------------------------------------------------------------------
Float32ToBits32(f32 value)44     static u32 Float32ToBits32(f32 value)
45     {
46         return *reinterpret_cast<u32*>(&value);
47     }
48 
49     //--------------------------------------------------------------------------
50     //! @brief        32bit 浮動小数のビット表現から f32 に変換します。
51     //!
52     //! @param[in]    value   32bit 浮動小数のビット表現です。
53     //!
54     //! @return       f32 の値です。
55     //--------------------------------------------------------------------------
Bits32ToFloat32(u32 value)56     static f32 Bits32ToFloat32(u32 value)
57     {
58         return *reinterpret_cast<f32*>(&value);
59     }
60 };
61 
62 //--------------------------------------------------------------------------
63 //! @brief        24bit 浮動小数用のユーティリティです。
64 //
65 // 24bit 浮動小数のビットフォーマットは次の通りです。
66 // | sign | exponent | fraction |
67 // sign     : 符号 1 bit.
68 // exponent : 指数部 7 bit. bias 63.
69 // fraction : 仮数部 16 bit.
70 //---------------------------------------------------------------------------
71 class Float24
72 {
73 public:
74     //--------------------------------------------------------------------------
75     //! @brief        デフォルトコンストラクタです。
76     //--------------------------------------------------------------------------
Float24()77     Float24() : m_Float32( 0.0f ) {}
78 
79     //--------------------------------------------------------------------------
80     //! @brief        コンストラクタです。
81     //!
82     //! @param[in]    bits24   24bit 浮動小数のビットを表現した整数値です。
83     //--------------------------------------------------------------------------
Float24(u32 bits24)84     /* implicit */ Float24( u32 bits24 )
85     {
86         m_Float32 = Bits24ToFloat32( bits24 );
87     }
88 
89     //--------------------------------------------------------------------------
90     //! @brief        コンストラクタです。
91     //!
92     //! @param[in]    value   32bit 浮動小数の値から 24bit float を生成します。
93     //--------------------------------------------------------------------------
Float24(f32 value)94     /* implicit */ Float24( f32 value ) : m_Float32( value ) {}
95 
GetFloat32Value()96     f32     GetFloat32Value() const { return m_Float32; }
GetFloat24Value()97     u32     GetFloat24Value() const { return Float32ToBits24( m_Float32 ); }
98 
99     Float24& operator =(f32 value) { this->m_Float32 = value; return *this; }
100     Float24& operator =(u32 bits24) { this->m_Float32 = Bits24ToFloat32( bits24 ); return *this; }
101 
f32()102     operator f32() const { return m_Float32; }
103 
104     f32 operator +(f32 right) const { return this->m_Float32 + right; }
105     f32 operator -(f32 right) const { return this->m_Float32 - right; }
106     f32 operator *(f32 right) const { return this->m_Float32 * right; }
107     f32 operator /(f32 right) const { return this->m_Float32 / right; }
108 
109     Float24& operator +=(f32 rhs) { this->m_Float32 += rhs; return *this; }
110     Float24& operator -=(f32 rhs) { this->m_Float32 -= rhs; return *this; }
111     Float24& operator *=(f32 rhs) { this->m_Float32 *= rhs; return *this; }
112     Float24& operator /=(f32 rhs) { this->m_Float32 /= rhs; return *this; }
113 
114     bool operator ==(f32 rhs) const { return (rhs == this->m_Float32); }
115     bool operator !=(f32 rhs) const { return !(*this == rhs); }
116 
117     //--------------------------------------------------------------------------
118     //! @brief        24bit float から 32bit float に変換します。
119     //!
120     //! @param[in]    bits24   24bit 浮動小数のビットを表現した整数値です。
121     //!
122     //! @return       f32 に変換した値を返します。
123     //--------------------------------------------------------------------------
Bits24ToFloat32(u32 bits24)124     static f32 Bits24ToFloat32(u32 bits24)
125     {
126         u32 sign = bits24 & SIGN24;
127         int exp = (int)((bits24 & EXP_MASK24) >> FRACTION_WIDTH24);
128         u32 fraction = bits24 & FRACTION_MASK24;
129 
130         u32 bits32 = 0;
131         bits32 |= (sign != 0) ? SIGN32 : 0;
132 
133         if ((bits24 & ~SIGN24) == 0)
134         {
135             exp = 0;
136         }
137         else
138         {
139             exp = exp - EXP_BIAS24 + EXP_BIAS32;
140         }
141 
142         fraction = fraction << (FRACTION_WIDTH32 - FRACTION_WIDTH24);
143 
144         // ビット拡張なので、exp がオーバーフローすることは無い。
145         bits32 |= fraction & FRACTION_MASK32;
146         bits32 |= ((u32)exp & 0xFF) << FRACTION_WIDTH32;
147 
148         return *reinterpret_cast<f32*>(&bits32);
149     }
150 
151     //--------------------------------------------------------------------------
152     //! @brief        f32 から 24bit float に変換します。
153     //!
154     //! @param[in]    value   32bit float の値です。
155     //!
156     //! @return       24bit 浮動小数のビット表現を返します。
157     //--------------------------------------------------------------------------
Float32ToBits24(f32 value)158     static u32 Float32ToBits24(f32 value)
159     {
160         u32 bits32 = *reinterpret_cast<u32*>(&value);
161 
162         u32 sign = bits32 & SIGN32;
163         int exp = (int)((bits32 & EXP_MASK32) >> FRACTION_WIDTH32);
164         u32 fraction = bits32 & FRACTION_MASK32;
165 
166         u32 bits24 = 0;
167         bits24 |= (sign != 0) ? SIGN24 : 0;
168 
169         if ((bits32 & ~SIGN32) == 0)
170         {
171             exp = 0;
172         }
173         else
174         {
175             exp = exp - EXP_BIAS32 + EXP_BIAS24;
176         }
177 
178         fraction = fraction >> (FRACTION_WIDTH32 - FRACTION_WIDTH24);
179 
180         if (exp < 0)
181         {
182             // +0 もしくは -0 なのでそのまま。
183         }
184         else if (exp > 127)
185         {
186             // 無限大の処理
187             // TODO: IEEE float の無限大の表現がGPU上で有効なのかどうかを要確認。
188             bits24 = (u32)0x7F << FRACTION_WIDTH24;
189         }
190         else
191         {
192             bits24 |= fraction & FRACTION_MASK24;
193             bits24 |= ((u32)exp & 0x7F) << FRACTION_WIDTH24;
194         }
195 
196         return bits24;
197     }
198 
199 private:
200     f32 m_Float32;
201 
202     enum
203     {
204         SIGN32 = 0x80000000,
205         SIGN24 = 0x00800000,
206 
207         EXP_BIAS32 = 127,
208         EXP_BIAS24 = 63,
209         EXP_MASK32 = 0x7F800000,
210         EXP_MASK24 = 0x007F0000,
211 
212         FRACTION_WIDTH32 = 23,
213         FRACTION_MASK32  = 0x007FFFFF,
214         FRACTION_WIDTH24 = 16,
215         FRACTION_MASK24  = 0x0000FFFF
216     };
217 };
218 
219 //--------------------------------------------------------------------------
220 //! @brief        31bit 浮動小数用のユーティリティです。
221 //
222 // 31bit 浮動小数のビットフォーマットは次の通りです。
223 // | sign | exponent | fraction |
224 // sign     : 符号 1 bit.
225 // exponent : 指数部 7 bit. bias 63.
226 // fraction : 仮数部 23 bit.
227 //---------------------------------------------------------------------------
228 class Float31
229 {
230 public:
231     //--------------------------------------------------------------------------
232     //! @brief        デフォルトコンストラクタです。
233     //--------------------------------------------------------------------------
Float31()234     Float31() : m_Float32( 0.0f ) {}
235 
236     //--------------------------------------------------------------------------
237     //! @brief        コンストラクタです。
238     //!
239     //! @param[in]    bits31   31bit 浮動小数のビットを表現した整数値です。
240     //--------------------------------------------------------------------------
Float31(u32 bits31)241     /* implicit */ Float31( u32 bits31 )
242     {
243         m_Float32 = Bits31ToFloat32( bits31 );
244     }
245 
246     //--------------------------------------------------------------------------
247     //! @brief        コンストラクタです。
248     //!
249     //! @param[in]    value   32bit 浮動小数の値から 31bit float を生成します。
250     //--------------------------------------------------------------------------
Float31(f32 value)251     /* implicit */ Float31( f32 value ) : m_Float32( value ) {}
252 
GetFloat32Value()253     f32     GetFloat32Value() const { return m_Float32; }
GetFloat31Value()254     u32     GetFloat31Value() const { return Float32ToBits31( m_Float32 ); }
255 
256     Float31& operator =(f32 value) { this->m_Float32 = value; return *this; }
257     Float31& operator =(u32 bits31) { this->m_Float32 = Bits31ToFloat32( bits31 ); return *this; }
258 
f32()259     operator f32() const { return m_Float32; }
260 
261     f32 operator +(f32 right) const { return this->m_Float32 + right; }
262     f32 operator -(f32 right) const { return this->m_Float32 - right; }
263     f32 operator *(f32 right) const { return this->m_Float32 * right; }
264     f32 operator /(f32 right) const { return this->m_Float32 / right; }
265 
266     Float31& operator +=(f32 rhs) { this->m_Float32 += rhs; return *this; }
267     Float31& operator -=(f32 rhs) { this->m_Float32 -= rhs; return *this; }
268     Float31& operator *=(f32 rhs) { this->m_Float32 *= rhs; return *this; }
269     Float31& operator /=(f32 rhs) { this->m_Float32 /= rhs; return *this; }
270 
271     bool operator ==(f32 rhs) const { return (rhs == this->m_Float32); }
272     bool operator !=(f32 rhs) const { return !(*this == rhs); }
273 
274     //--------------------------------------------------------------------------
275     //! @brief        31bit float から 32bit float に変換します。
276     //!
277     //! @param[in]    bits31   31bit 浮動小数のビットを表現した整数値です。
278     //!
279     //! @return       f32 に変換した値を返します。
280     //--------------------------------------------------------------------------
Bits31ToFloat32(u32 bits31)281     static f32 Bits31ToFloat32(u32 bits31)
282     {
283         u32 sign = bits31 & SIGN31;
284         int exp = (int)((bits31 & EXP_MASK31) >> FRACTION_WIDTH31);
285         u32 fraction = bits31 & FRACTION_MASK31;
286 
287         u32 bits32 = 0;
288         bits32 |= (sign != 0) ? SIGN32 : 0;
289 
290         if ((bits31 & ~SIGN31) == 0)
291         {
292             exp = 0;
293         }
294         else
295         {
296             exp = exp - EXP_BIAS31 + EXP_BIAS32;
297         }
298 
299         // ビット拡張なので、exp がオーバーフローすることは無い。
300         bits32 |= fraction & FRACTION_MASK32;
301         bits32 |= ((u32)exp & 0xFF) << FRACTION_WIDTH32;
302 
303         return *reinterpret_cast<f32*>(&bits32);
304     }
305 
306     //--------------------------------------------------------------------------
307     //! @brief        f32 から 31bit float に変換します。
308     //!
309     //! @param[in]    value   32bit float の値です。
310     //!
311     //! @return       31bit 浮動小数のビット表現を返します。
312     //--------------------------------------------------------------------------
Float32ToBits31(f32 value)313     static u32 Float32ToBits31(f32 value)
314     {
315         u32 bits32 = *reinterpret_cast<u32*>(&value);
316 
317         u32 sign = bits32 & SIGN32;
318         int exp = (int)((bits32 & EXP_MASK32) >> FRACTION_WIDTH32);
319         u32 fraction = bits32 & FRACTION_MASK32;
320 
321         u32 bits31 = 0;
322         bits31 |= (sign != 0) ? SIGN31 : 0;
323 
324         if ((bits32 & ~SIGN32) == 0)
325         {
326             exp = 0;
327         }
328         else
329         {
330             exp = exp - EXP_BIAS32 + EXP_BIAS31;
331         }
332 
333         if (exp < 0)
334         {
335             // +0 もしくは -0 なのでそのまま。
336         }
337         else if (exp > 127)
338         {
339             // 無限大の処理
340             // TODO: IEEE float の無限大の表現がGPU上で有効なのかどうかを要確認。
341             bits31 = (u32)0x7F << FRACTION_WIDTH31;
342         }
343         else
344         {
345             bits31 |= fraction & FRACTION_MASK31;
346             bits31 |= ((u32)exp & 0x7F) << FRACTION_WIDTH31;
347         }
348 
349         return bits31;
350     }
351 
352 private:
353     f32 m_Float32;
354 
355     enum
356     {
357         SIGN32 = 0x80000000,
358         SIGN31 = 0x40000000,
359 
360         EXP_BIAS32 = 127,
361         EXP_BIAS31 = 63,
362         EXP_MASK32 = 0x7F800000,
363         EXP_MASK31 = 0x3F800000,
364 
365         FRACTION_WIDTH32 = 23,
366         FRACTION_MASK32  = 0x007FFFFF,
367         FRACTION_WIDTH31 = 23,
368         FRACTION_MASK31  = 0x007FFFFF
369     };
370 };
371 
372 
373 //--------------------------------------------------------------------------
374 //! @brief        20bit 浮動小数用のユーティリティです。
375 //
376 // 20bit 浮動小数のビットフォーマットは次の通りです。
377 // | sign | exponent | fraction |
378 // sign     : 符号 1 bit.
379 // exponent : 指数部 7 bit. bias 63.
380 // fraction : 仮数部 12 bit.
381 //---------------------------------------------------------------------------
382 class Float20
383 {
384 public:
385     //--------------------------------------------------------------------------
386     //! @brief        デフォルトコンストラクタです。
387     //--------------------------------------------------------------------------
Float20()388     Float20() : m_Float32( 0.0f ) {}
389 
390     //--------------------------------------------------------------------------
391     //! @brief        コンストラクタです。
392     //!
393     //! @param[in]    bits20   20bit 浮動小数のビットを表現した整数値です。
394     //--------------------------------------------------------------------------
Float20(u32 bits20)395     /* implicit */ Float20( u32 bits20 )
396     {
397         m_Float32 = Bits20ToFloat32( bits20 );
398     }
399 
400     //--------------------------------------------------------------------------
401     //! @brief        コンストラクタです。
402     //!
403     //! @param[in]    value   32bit 浮動小数の値から 20bit float を生成します。
404     //--------------------------------------------------------------------------
Float20(f32 value)405     /* implicit */ Float20( f32 value ) : m_Float32( value ) {}
406 
GetFloat32Value()407     f32     GetFloat32Value() const { return m_Float32; }
GetFloat20Value()408     u32     GetFloat20Value() const { return Float32ToBits20( m_Float32 ); }
409 
410     Float20& operator =(f32 value) { this->m_Float32 = value; return *this; }
411     Float20& operator =(u32 bits20) { this->m_Float32 = Bits20ToFloat32( bits20 ); return *this; }
412 
f32()413     operator f32() const { return m_Float32; }
414 
415     f32 operator +(f32 right) const { return this->m_Float32 + right; }
416     f32 operator -(f32 right) const { return this->m_Float32 - right; }
417     f32 operator *(f32 right) const { return this->m_Float32 * right; }
418     f32 operator /(f32 right) const { return this->m_Float32 / right; }
419 
420     Float20& operator +=(f32 rhs) { this->m_Float32 += rhs; return *this; }
421     Float20& operator -=(f32 rhs) { this->m_Float32 -= rhs; return *this; }
422     Float20& operator *=(f32 rhs) { this->m_Float32 *= rhs; return *this; }
423     Float20& operator /=(f32 rhs) { this->m_Float32 /= rhs; return *this; }
424 
425     bool operator ==(f32 rhs) const { return (rhs == this->m_Float32); }
426     bool operator !=(f32 rhs) const { return !(*this == rhs); }
427 
428     //--------------------------------------------------------------------------
429     //! @brief        20bit float から 32bit float に変換します。
430     //!
431     //! @param[in]    bits20   20bit 浮動小数のビットを表現した整数値です。
432     //!
433     //! @return       f32 に変換した値を返します。
434     //--------------------------------------------------------------------------
Bits20ToFloat32(u32 bits20)435     static f32 Bits20ToFloat32(u32 bits20)
436     {
437         u32 sign = bits20 & SIGN20;
438         int exp = (int)((bits20 & EXP_MASK20) >> FRACTION_WIDTH20);
439         u32 fraction = bits20 & FRACTION_MASK20;
440 
441         u32 bits32 = 0;
442         bits32 |= (sign != 0) ? SIGN32 : 0;
443 
444         if ((bits20 & ~SIGN20) == 0)
445         {
446             exp = 0;
447         }
448         else
449         {
450             exp = exp - EXP_BIAS20 + EXP_BIAS32;
451         }
452 
453         fraction = fraction << (FRACTION_WIDTH32 - FRACTION_WIDTH20);
454 
455         // ビット拡張なので、exp がオーバーフローすることは無い。
456         bits32 |= fraction & FRACTION_MASK32;
457         bits32 |= ((u32)exp & 0xFF) << FRACTION_WIDTH32;
458 
459         return *reinterpret_cast<f32*>(&bits32);
460     }
461 
462     //--------------------------------------------------------------------------
463     //! @brief        f32 から 20bit float に変換します。
464     //!
465     //! @param[in]    value   32bit float の値です。
466     //!
467     //! @return       20bit 浮動小数のビット表現を返します。
468     //--------------------------------------------------------------------------
Float32ToBits20(f32 value)469     static u32 Float32ToBits20(f32 value)
470     {
471         u32 bits32 = *reinterpret_cast<u32*>(&value);
472 
473         u32 sign = bits32 & SIGN32;
474         int exp = (int)((bits32 & EXP_MASK32) >> FRACTION_WIDTH32);
475         u32 fraction = bits32 & FRACTION_MASK32;
476 
477         u32 bits20 = 0;
478         bits20 |= (sign != 0) ? SIGN20 : 0;
479 
480         if ((bits32 & ~SIGN32) == 0)
481         {
482             exp = 0;
483         }
484         else
485         {
486             exp = exp - EXP_BIAS32 + EXP_BIAS20;
487         }
488 
489         fraction = fraction >> (FRACTION_WIDTH32 - FRACTION_WIDTH20);
490 
491         if (exp < 0)
492         {
493             // +0 もしくは -0 なのでそのまま。
494         }
495         else if (exp > 127)
496         {
497             // 無限大の処理
498             // TODO: IEEE float の無限大の表現がGPU上で有効なのかどうかを要確認。
499             bits20 = (u32)0x7F << FRACTION_WIDTH20;
500         }
501         else
502         {
503             bits20 |= fraction & FRACTION_MASK20;
504             bits20 |= ((u32)exp & 0x7F) << FRACTION_WIDTH20;
505         }
506 
507         return bits20;
508     }
509 
510 private:
511     f32 m_Float32;
512 
513     enum
514     {
515         SIGN32 = 0x80000000,
516         SIGN20 = 0x00080000,
517 
518         EXP_BIAS32 = 127,
519         EXP_BIAS20 = 63,
520         EXP_MASK32 = 0x7F800000,
521         EXP_MASK20 = 0x0007F000,
522 
523         FRACTION_WIDTH32 = 23,
524         FRACTION_MASK32  = 0x007FFFFF,
525         FRACTION_WIDTH20 = 12,
526         FRACTION_MASK20  = 0x00000FFF
527     };
528 };
529 
530 
531 //--------------------------------------------------------------------------
532 //! @brief        16bit 浮動小数用のユーティリティです。
533 //
534 // 16bit 浮動小数のビットフォーマットは次の通りです。
535 // | sign | exponent | fraction |
536 // sign     : 符号 1 bit.
537 // exponent : 指数部 5 bit. bias 15.
538 // fraction : 仮数部 10 bit.
539 //---------------------------------------------------------------------------
540 class Float16
541 {
542 public:
543     //--------------------------------------------------------------------------
544     //! @brief        デフォルトコンストラクタです。
545     //--------------------------------------------------------------------------
Float16()546     Float16() : m_Float32( 0.0f ) {}
547 
548     //--------------------------------------------------------------------------
549     //! @brief        コンストラクタです。
550     //!
551     //! @param[in]    bits16   16bit 浮動小数のビットを表現した整数値です。
552     //--------------------------------------------------------------------------
Float16(u32 bits16)553     /* implicit */ Float16( u32 bits16 )
554     {
555         m_Float32 = Bits16ToFloat32( bits16 );
556     }
557 
558     //--------------------------------------------------------------------------
559     //! @brief        コンストラクタです。
560     //!
561     //! @param[in]    value   32bit 浮動小数の値から 16bit float を生成します。
562     //--------------------------------------------------------------------------
Float16(f32 value)563     /* implicit */ Float16( f32 value ) : m_Float32( value ) {}
564 
GetFloat32Value()565     f32     GetFloat32Value() const { return m_Float32; }
GetFloat16Value()566     u16     GetFloat16Value() const { return Float32ToBits16( m_Float32 ); }
567 
568     Float16& operator =(f32 value) { this->m_Float32 = value; return *this; }
569     Float16& operator =(u32 bits16) { this->m_Float32 = Bits16ToFloat32( bits16 ); return *this; }
570 
f32()571     operator f32() const { return m_Float32; }
u16()572     operator u16() const { return GetFloat16Value(); }
573 
574     f32 operator +(f32 right) const { return this->m_Float32 + right; }
575     f32 operator -(f32 right) const { return this->m_Float32 - right; }
576     f32 operator *(f32 right) const { return this->m_Float32 * right; }
577     f32 operator /(f32 right) const { return this->m_Float32 / right; }
578 
579     Float16& operator +=(f32 rhs) { this->m_Float32 += rhs; return *this; }
580     Float16& operator -=(f32 rhs) { this->m_Float32 -= rhs; return *this; }
581     Float16& operator *=(f32 rhs) { this->m_Float32 *= rhs; return *this; }
582     Float16& operator /=(f32 rhs) { this->m_Float32 /= rhs; return *this; }
583 
584     bool operator ==(f32 rhs) const { return (rhs == this->m_Float32); }
585     bool operator !=(f32 rhs) const { return !(*this == rhs); }
586 
587     //--------------------------------------------------------------------------
588     //! @brief        16bit float から 32bit float に変換します。
589     //!
590     //! @param[in]    bits16   16bit 浮動小数のビットを表現した整数値です。
591     //!
592     //! @return       f32 に変換した値を返します。
593     //--------------------------------------------------------------------------
Bits16ToFloat32(u32 bits16)594     static f32 Bits16ToFloat32(u32 bits16)
595     {
596         u32 sign = bits16 & SIGN16;
597         int exp = (int)((bits16 & EXP_MASK16) >> FRACTION_WIDTH16);
598         u32 fraction = bits16 & FRACTION_MASK16;
599 
600         u32 bits32 = 0;
601         bits32 |= (sign != 0) ? SIGN32 : 0;
602 
603         if ((bits16 & ~SIGN16) == 0)
604         {
605             exp = 0;
606         }
607         else
608         {
609             exp = exp - EXP_BIAS16 + EXP_BIAS32;
610         }
611 
612         fraction = fraction << (FRACTION_WIDTH32 - FRACTION_WIDTH16);
613 
614         // ビット拡張なので、exp がオーバーフローすることは無い。
615         bits32 |= fraction & FRACTION_MASK32;
616         bits32 |= ((u32)exp & 0xFF) << FRACTION_WIDTH32;
617 
618         return *reinterpret_cast<f32*>(&bits32);
619     }
620 
621     //--------------------------------------------------------------------------
622     //! @brief        f32 から 16bit float に変換します。
623     //!
624     //! @param[in]    value   32bit float の値です。
625     //!
626     //! @return       16bit 浮動小数のビット表現を返します。
627     //--------------------------------------------------------------------------
Float32ToBits16(f32 value)628     static u16 Float32ToBits16(f32 value)
629     {
630         u32 bits32 = *reinterpret_cast<u32*>(&value);
631 
632         u32 sign = bits32 & SIGN32;
633         int exp = (int)((bits32 & EXP_MASK32) >> FRACTION_WIDTH32);
634         u32 fraction = bits32 & FRACTION_MASK32;
635 
636         u32 bits16 = 0;
637         bits16 |= (sign != 0) ? SIGN16 : 0;
638 
639         if ((bits32 & ~SIGN32) == 0)
640         {
641             exp = 0;
642         }
643         else
644         {
645             exp = exp - EXP_BIAS32 + EXP_BIAS16;
646         }
647 
648         fraction = fraction >> (FRACTION_WIDTH32 - FRACTION_WIDTH16);
649 
650         if (exp < 0)
651         {
652             // +0 もしくは -0 なのでそのまま。
653         }
654         else if (exp > 31)
655         {
656             // 無限大の処理
657             // TODO: IEEE float の無限大の表現がGPU上で有効なのかどうかを要確認。
658             bits16 = (u32)0x1F << FRACTION_WIDTH16;
659         }
660         else
661         {
662             bits16 |= fraction & FRACTION_MASK16;
663             bits16 |= ((u32)exp & 0x1F) << FRACTION_WIDTH16;
664         }
665 
666         return static_cast<u16>(bits16);
667     }
668 
669 private:
670     f32 m_Float32;
671 
672     enum
673     {
674         SIGN32 = 0x80000000,
675         SIGN16 = 0x00008000,
676 
677         EXP_BIAS32 = 127,
678         EXP_BIAS16 = 15,
679         EXP_MASK32 = 0x7F800000,
680         EXP_MASK16 = 0x00007C00,
681 
682         FRACTION_WIDTH32 = 23,
683         FRACTION_MASK32  = 0x007FFFFF,
684         FRACTION_WIDTH16 = 10,
685         FRACTION_MASK16  = 0x000003FF
686     };
687 };
688 
689 //--------------------------------------------------------------------------
690 //! @brief        13bit 固定小数用のユーティリティです。
691 //
692 // 13bit 固定小数のビットフォーマットは次の通りです。
693 // | int | decimal | (2の補数)
694 // int      : 整数部 2 bit.
695 // decimal  : 小数部 11 bit.
696 //---------------------------------------------------------------------------
697 class Fixed13
698 {
699 public:
700     //--------------------------------------------------------------------------
701     //! @brief        デフォルトコンストラクタです。
702     //--------------------------------------------------------------------------
Fixed13()703     Fixed13() : m_Float32( 0.0f ) {}
704 
705     //--------------------------------------------------------------------------
706     //! @brief        コンストラクタです。
707     //!
708     //! @param[in]    fixed13   13bit 固定小数のビットを表現した整数値です。
709     //--------------------------------------------------------------------------
Fixed13(u32 fixed13)710     explicit Fixed13( u32 fixed13 )
711     {
712         m_Float32 = Fixed13ToFloat32( fixed13 );
713     }
714 
715     //--------------------------------------------------------------------------
716     //! @brief        コンストラクタです。
717     //!
718     //! @param[in]    fvalue   32bit 浮動小数の値です。
719     //--------------------------------------------------------------------------
Fixed13(f32 fvalue)720     explicit Fixed13( f32 fvalue )
721     {
722         m_Float32 = fvalue;
723     }
724 
725 
GetFloat32Value()726     f32     GetFloat32Value() const { return m_Float32; }
GetFixed13Value()727     u16     GetFixed13Value() const { return Float32ToFixed13( m_Float32 ); }
728 
729     //--------------------------------------------------------------------------
730     //! @brief        13bit fixed から 32bit float に変換します。
731     //!
732     //! @param[in]    fixed13   13bit 固定小数のビットを表現した整数値です。
733     //!
734     //! @return       f32 に変換した値を返します。
735     //--------------------------------------------------------------------------
Fixed13ToFloat32(u32 fixed13)736     static f32 Fixed13ToFloat32(u32 fixed13)
737     {
738         f32 float32 = static_cast<f32>(fixed13);
739 
740         if (fixed13 & (0x1 << (TOTAL_WIDTH - 1)))
741         {
742             float32 -= (0x1 << TOTAL_WIDTH);
743         }
744 
745         return float32 / (0x1 << DECIMAL_WIDTH);
746     }
747 
748     //--------------------------------------------------------------------------
749     //! @brief        f32 から 13bit fixed に変換します。
750     //!
751     //! @param[in]    value   32bit float の値です。
752     //!
753     //! @return       16bit 浮動小数のビット表現を返します。
754     //--------------------------------------------------------------------------
Float32ToFixed13(f32 value)755     static u16 Float32ToFixed13(f32 value)
756     {
757         f32 fixed = value;
758         fixed += ((0x1 << INT_WIDTH) / 2);
759         fixed *= (0x1 << DECIMAL_WIDTH);
760 
761         if (fixed < 0)
762         {
763             fixed = 0.0f;
764         }
765         else if (fixed >= (0x1 << TOTAL_WIDTH))
766         {
767             fixed = (0x1 << TOTAL_WIDTH) - 1;
768         }
769 
770         fixed -= 0x1 << (TOTAL_WIDTH - 1);
771 
772         return static_cast<u16>(static_cast<s16>(fixed) & MASK);
773     }
774 
775 private:
776     f32 m_Float32;
777 
778     enum
779     {
780         INT_WIDTH = 2,
781         DECIMAL_WIDTH = 11,
782         TOTAL_WIDTH = 13,
783         MASK = (0x1 << TOTAL_WIDTH) - 1
784     };
785 };
786 
787 //--------------------------------------------------------------------------
788 //! @brief        13bit 固定小数用のユーティリティです。
789 //
790 // 13bit 固定小数のビットフォーマットは次の通りです。
791 // | sign | int | decimal | (2の補数)
792 // int      : 整数部 5 bit.
793 // decimal  : 小数部 8 bit.
794 //---------------------------------------------------------------------------
795 class FixedS13Fraction8
796 {
797 public:
798     //--------------------------------------------------------------------------
799     //! @brief        デフォルトコンストラクタです。
800     //--------------------------------------------------------------------------
FixedS13Fraction8()801     FixedS13Fraction8() : m_Float32( 0.0f ) {}
802 
803     //--------------------------------------------------------------------------
804     //! @brief        コンストラクタです。
805     //!
806     //! @param[in]    fixed13   13bit 固定小数のビットを表現した整数値です。
807     //--------------------------------------------------------------------------
FixedS13Fraction8(u32 fixed13)808     explicit FixedS13Fraction8( u32 fixed13 )
809     {
810         m_Float32 = Fixed13ToFloat32( fixed13 );
811     }
812 
813     //--------------------------------------------------------------------------
814     //! @brief        コンストラクタです。
815     //!
816     //! @param[in]    fvalue   32bit 浮動小数の値です。
817     //--------------------------------------------------------------------------
FixedS13Fraction8(f32 fvalue)818     explicit FixedS13Fraction8( f32 fvalue )
819     {
820         m_Float32 = fvalue;
821     }
822 
823 
GetFloat32Value()824     f32     GetFloat32Value() const { return m_Float32; }
GetFixed13Value()825     u16     GetFixed13Value() const { return Float32ToFixed13( m_Float32 ); }
826 
827     //--------------------------------------------------------------------------
828     //! @brief        13bit fixed から 32bit float に変換します。
829     //!
830     //! @param[in]    fixed13   13bit 固定小数のビットを表現した整数値です。
831     //!
832     //! @return       f32 に変換した値を返します。
833     //--------------------------------------------------------------------------
Fixed13ToFloat32(u32 fixed13)834     static f32 Fixed13ToFloat32(u32 fixed13)
835     {
836         f32 float32 = static_cast<f32>(fixed13);
837 
838         if (fixed13 & (0x1 << (TOTAL_WIDTH - 1)))
839         {
840             float32 -= (0x1 << TOTAL_WIDTH);
841         }
842 
843         return float32 / (0x1 << DECIMAL_WIDTH);
844     }
845 
846     //--------------------------------------------------------------------------
847     //! @brief        f32 から 13bit fixed に変換します。
848     //!
849     //! @param[in]    value   32bit float の値です。
850     //!
851     //! @return       13bit 固定小数のビット表現を返します。
852     //--------------------------------------------------------------------------
Float32ToFixed13(f32 value)853     static u16 Float32ToFixed13(f32 value)
854     {
855         f32 fixed = value;
856         fixed += ((0x1 << INT_WIDTH) / 2);
857         fixed *= (0x1 << DECIMAL_WIDTH);
858 
859         if (fixed < 0)
860         {
861             fixed = 0.0f;
862         }
863         else if (fixed >= (0x1 << TOTAL_WIDTH))
864         {
865             fixed = (0x1 << TOTAL_WIDTH) - 1;
866         }
867 
868         fixed -= 0x1 << (TOTAL_WIDTH - 1);
869 
870         return static_cast<u16>(static_cast<s16>(fixed) & MASK);
871     }
872 
873 private:
874     f32 m_Float32;
875 
876     enum
877     {
878         INT_WIDTH = 5,
879         DECIMAL_WIDTH = 8,
880         TOTAL_WIDTH = 13,
881         MASK = (0x1 << TOTAL_WIDTH) - 1
882     };
883 };
884 
885 //--------------------------------------------------------------------------
886 //! @brief        11bit 固定小数用のユーティリティです。
887 //
888 // 11bit 固定小数のビットフォーマットは次の通りです。
889 // decimal  : 小数部 11 bit.
890 //---------------------------------------------------------------------------
891 class Fixed11
892 {
893 public:
894     //--------------------------------------------------------------------------
895     //! @brief        デフォルトコンストラクタです。
896     //--------------------------------------------------------------------------
Fixed11()897     Fixed11() : m_Float32( 0.0f ) {}
898 
899     //--------------------------------------------------------------------------
900     //! @brief        コンストラクタです。
901     //!
902     //! @param[in]    fixed11   11bit 固定小数のビットを表現した整数値です。
903     //--------------------------------------------------------------------------
Fixed11(u32 fixed11)904     explicit Fixed11( u32 fixed11 )
905     {
906         m_Float32 = Fixed11ToFloat32( fixed11 );
907     }
908 
909     //--------------------------------------------------------------------------
910     //! @brief        コンストラクタです。
911     //!
912     //! @param[in]    fvalue   32bit 浮動小数の値です。
913     //--------------------------------------------------------------------------
Fixed11(f32 fvalue)914     explicit Fixed11( f32 fvalue )
915     {
916         m_Float32 = fvalue;
917     }
918 
919 
GetFloat32Value()920     f32     GetFloat32Value() const { return m_Float32; }
GetFixed11Value()921     u16     GetFixed11Value() const { return Float32ToFixed11( m_Float32 ); }
922 
923     //--------------------------------------------------------------------------
924     //! @brief        11bit fixed から 32bit float に変換します。
925     //!
926     //! @param[in]    fixed11   11bit 固定小数のビットを表現した整数値です。
927     //!
928     //! @return       f32 に変換した値を返します。
929     //--------------------------------------------------------------------------
Fixed11ToFloat32(u32 fixed11)930     static f32 Fixed11ToFloat32(u32 fixed11)
931     {
932         f32 float32 = static_cast<f32>(fixed11);
933         return float32 / MASK;
934     }
935 
936     //--------------------------------------------------------------------------
937     //! @brief        f32 から 11bit fixed に変換します。
938     //!
939     //! @param[in]    value   32bit float の値です。
940     //!
941     //! @return       11bit 固定小数のビット表現を返します。
942     //--------------------------------------------------------------------------
Float32ToFixed11(f32 value)943     static u16 Float32ToFixed11(f32 value)
944     {
945         u32 fixed;
946         u32 v_ = *(u32*)&value;
947 
948         if (value <= 0 || (v_ & 0x7f800000) == 0x7f800000)
949         {
950             fixed = 0;
951         }
952         else
953         {
954             value *= 1 << (DECIMAL_WIDTH - 0);
955             if (value >= (1 << DECIMAL_WIDTH))
956             {
957                 fixed = (1 << DECIMAL_WIDTH) - 1;
958             }
959             else
960             {
961                 fixed = (unsigned)(value);
962             }
963         }
964 
965         return static_cast<u16>(static_cast<s16>(fixed) & MASK);
966     }
967 
968 private:
969     f32 m_Float32;
970 
971     enum
972     {
973         INT_WIDTH = 2,
974         DECIMAL_WIDTH = 11,
975         TOTAL_WIDTH = 11,
976         MASK = (0x1 << TOTAL_WIDTH) - 1
977     };
978 };
979 
980 //--------------------------------------------------------------------------
981 //! @brief        24bit 固定小数用のユーティリティです。
982 //
983 // 24bit 固定小数のビットフォーマットは次の通りです。
984 // decimal  : 小数部 24 bit.
985 //---------------------------------------------------------------------------
986 class FixedU24
987 {
988 public:
989     //--------------------------------------------------------------------------
990     //! @brief        デフォルトコンストラクタです。
991     //--------------------------------------------------------------------------
FixedU24()992     FixedU24() : m_Float32( 0.0f ) {}
993 
994     //--------------------------------------------------------------------------
995     //! @brief        コンストラクタです。
996     //!
997     //! @param[in]    fixedU24 24bit 固定小数のビットを表現した整数値です。
998     //--------------------------------------------------------------------------
FixedU24(u32 fixedU24)999     explicit FixedU24( u32 fixedU24 )
1000     {
1001         m_Float32 = FixedU24ToFloat32( fixedU24 );
1002     }
1003 
1004     //--------------------------------------------------------------------------
1005     //! @brief        コンストラクタです。
1006     //!
1007     //! @param[in]    fvalue   32bit 浮動小数の値です。
1008     //--------------------------------------------------------------------------
FixedU24(f32 fvalue)1009     explicit FixedU24( f32 fvalue )
1010     {
1011         m_Float32 = fvalue;
1012     }
1013 
1014 
GetFloat32Value()1015     f32     GetFloat32Value() const { return m_Float32; }
GetFixedU24Value()1016     u32     GetFixedU24Value() const { return Float32ToFixedU24( m_Float32 ); }
1017 
1018     //--------------------------------------------------------------------------
1019     //! @brief        24bit fixed から 32bit float に変換します。
1020     //!
1021     //! @param[in]    fixedU24   24bit 固定小数のビットを表現した整数値です。
1022     //!
1023     //! @return       f32 に変換した値を返します。
1024     //--------------------------------------------------------------------------
FixedU24ToFloat32(u32 fixedU24)1025     static f32 FixedU24ToFloat32(u32 fixedU24)
1026     {
1027         f32 float32 = static_cast<f32>(fixedU24);
1028         return float32 / MASK;
1029     }
1030 
1031     //--------------------------------------------------------------------------
1032     //! @brief        f32 から 24bit fixed に変換します。
1033     //!
1034     //! @param[in]    value   32bit float の値です。
1035     //!
1036     //! @return       24bit 固定小数小数のビット表現を返します。
1037     //--------------------------------------------------------------------------
Float32ToFixedU24(f32 value)1038     static u32 Float32ToFixedU24(f32 value)
1039     {
1040         u32 fixed;
1041         u32 v_ = *(u32*)&value;
1042 
1043         if (value <= 0 || (v_ & 0x7f800000) == 0x7f800000)
1044         {
1045             fixed = 0;
1046         }
1047         else
1048         {
1049             value *= 1 << (DECIMAL_WIDTH - 0);
1050             if (value >= (1 << DECIMAL_WIDTH))
1051             {
1052                 fixed = (1 << DECIMAL_WIDTH) - 1;
1053             }
1054             else
1055             {
1056                 fixed = (unsigned)(value);
1057             }
1058         }
1059 
1060         return static_cast<u32>(static_cast<s32>(fixed) & MASK);
1061     }
1062 
1063 private:
1064     f32 m_Float32;
1065 
1066     enum
1067     {
1068         INT_WIDTH = 2,
1069         DECIMAL_WIDTH = 24,
1070         TOTAL_WIDTH = 24,
1071         MASK = (0x1 << TOTAL_WIDTH) - 1
1072     };
1073 };
1074 
1075 } /* namespace ut */
1076 } /* namespace nw */
1077 
1078 #endif //  NW_UT_FLOAT24_H_
1079