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