1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: util_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: 25398 $ 14 *---------------------------------------------------------------------------*/ 15 16 #ifndef NN_UTIL_UTIL_FLOAT24_H_ 17 #define NN_UTIL_UTIL_FLOAT24_H_ 18 19 #include <nn/math.h> 20 21 #ifdef __cplusplus 22 23 namespace nn { 24 namespace util { 25 26 //-------------------------------------------------------------------------- 27 //! @brief 32bit 浮動小数用のユーティリティです。 28 // 29 // 32bit 浮動小数のビットフォーマットは次の通りです。 30 // | sign | exponent | fraction | 31 // sign : 符号 1 bit. 32 // exponent : 指数部 8 bit. bias 127. 33 // fraction : 仮数部 23 bit. 34 //--------------------------------------------------------------------------- 35 class Float32 36 { 37 public: 38 //-------------------------------------------------------------------------- 39 //! @brief f32 から 32bit 浮動小数のビット表現に変換します。 40 //! 41 //! @param[in] value 32bit float の値です。 42 //! 43 //! @return 32bit 浮動小数のビット表現を返します。 44 //-------------------------------------------------------------------------- Float32ToBits32(f32 value)45 static u32 Float32ToBits32(f32 value) 46 { 47 return *reinterpret_cast<u32*>(&value); 48 } 49 50 //-------------------------------------------------------------------------- 51 //! @brief 32bit 浮動小数のビット表現から f32 に変換します。 52 //! 53 //! @param[in] value 32bit 浮動小数のビット表現です。 54 //! 55 //! @return f32 の値です。 56 //-------------------------------------------------------------------------- Bits32ToFloat32(u32 value)57 static f32 Bits32ToFloat32(u32 value) 58 { 59 return *reinterpret_cast<f32*>(&value); 60 } 61 }; 62 63 //-------------------------------------------------------------------------- 64 //! @brief 24bit 浮動小数用のユーティリティです。 65 // 66 // 24bit 浮動小数のビットフォーマットは次の通りです。 67 // | sign | exponent | fraction | 68 // sign : 符号 1 bit. 69 // exponent : 指数部 7 bit. bias 63. 70 // fraction : 仮数部 16 bit. 71 //--------------------------------------------------------------------------- 72 class Float24 73 { 74 public: 75 //-------------------------------------------------------------------------- 76 //! @brief デフォルトコンストラクタです。 77 //-------------------------------------------------------------------------- Float24()78 Float24() : m_Float32( 0.0f ) {} 79 80 //-------------------------------------------------------------------------- 81 //! @brief コンストラクタです。 82 //! 83 //! @param[in] bits24 24bit 浮動小数のビットを表現した整数値です。 84 //-------------------------------------------------------------------------- Float24(u32 bits24)85 /* implicit */ Float24( u32 bits24 ) 86 { 87 m_Float32 = Bits24ToFloat32( bits24 ); 88 } 89 90 //-------------------------------------------------------------------------- 91 //! @brief コンストラクタです。 92 //! 93 //! @param[in] value 32bit 浮動小数の値から 24bit float を生成します。 94 //-------------------------------------------------------------------------- Float24(f32 value)95 /* implicit */ Float24( f32 value ) : m_Float32( value ) {} 96 GetFloat32Value()97 f32 GetFloat32Value() const { return m_Float32; } GetFloat24Value()98 u32 GetFloat24Value() const { return Float32ToBits24( m_Float32 ); } 99 100 Float24& operator =(f32 value) { this->m_Float32 = value; return *this; } 101 Float24& operator =(u32 bits24) { this->m_Float32 = Bits24ToFloat32( bits24 ); return *this; } 102 f32()103 operator f32() const { return m_Float32; } 104 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 f32 operator /(f32 right) const { return this->m_Float32 / right; } 109 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 Float24& operator /=(f32 rhs) { this->m_Float32 /= rhs; return *this; } 114 115 bool operator ==(f32 rhs) const { return (rhs == this->m_Float32); } 116 bool operator !=(f32 rhs) const { return !(*this == rhs); } 117 118 //-------------------------------------------------------------------------- 119 //! @brief 24bit float から 32bit float に変換します。 120 //! 121 //! @param[in] bits24 24bit 浮動小数のビットを表現した整数値です。 122 //! 123 //! @return f32 に変換した値を返します。 124 //-------------------------------------------------------------------------- Bits24ToFloat32(u32 bits24)125 static f32 Bits24ToFloat32(u32 bits24) 126 { 127 u32 sign = bits24 & SIGN24; 128 int exp = (int)((bits24 & EXP_MASK24) >> FRACTION_WIDTH24); 129 u32 fraction = bits24 & FRACTION_MASK24; 130 131 u32 bits32 = 0; 132 bits32 |= (sign != 0) ? SIGN32 : 0; 133 134 if ((bits24 & ~SIGN24) == 0) 135 { 136 exp = 0; 137 } 138 else 139 { 140 exp = exp - EXP_BIAS24 + EXP_BIAS32; 141 } 142 143 fraction = fraction << (FRACTION_WIDTH32 - FRACTION_WIDTH24); 144 145 // ビット拡張なので、exp がオーバーフローすることは無い。 146 bits32 |= fraction & FRACTION_MASK32; 147 bits32 |= ((u32)exp & 0xFF) << FRACTION_WIDTH32; 148 149 return *reinterpret_cast<f32*>(&bits32); 150 } 151 152 //-------------------------------------------------------------------------- 153 //! @brief f32 から 24bit float に変換します。 154 //! 155 //! @param[in] value 32bit float の値です。 156 //! 157 //! @return 24bit 浮動小数のビット表現を返します。 158 //-------------------------------------------------------------------------- Float32ToBits24(f32 value)159 static u32 Float32ToBits24(f32 value) 160 { 161 u32 bits32 = *reinterpret_cast<u32*>(&value); 162 163 u32 sign = bits32 & SIGN32; 164 int exp = (int)((bits32 & EXP_MASK32) >> FRACTION_WIDTH32); 165 u32 fraction = bits32 & FRACTION_MASK32; 166 167 u32 bits24 = 0; 168 bits24 |= (sign != 0) ? SIGN24 : 0; 169 170 if ((bits32 & ~SIGN32) == 0) 171 { 172 exp = 0; 173 } 174 else 175 { 176 exp = exp - EXP_BIAS32 + EXP_BIAS24; 177 } 178 179 fraction = fraction >> (FRACTION_WIDTH32 - FRACTION_WIDTH24); 180 181 if (exp < 0) 182 { 183 // +0 もしくは -0 なのでそのまま。 184 } 185 else if (exp > 127) 186 { 187 // 無限大の処理 188 // TODO: IEEE float の無限大の表現がGPU上で有効なのかどうかを要確認。 189 bits24 = (u32)0x7F << FRACTION_WIDTH24; 190 } 191 else 192 { 193 bits24 |= fraction & FRACTION_MASK24; 194 bits24 |= ((u32)exp & 0x7F) << FRACTION_WIDTH24; 195 } 196 197 return bits24; 198 } 199 200 private: 201 f32 m_Float32; 202 203 enum 204 { 205 SIGN32 = 0x80000000, 206 SIGN24 = 0x00800000, 207 208 EXP_BIAS32 = 127, 209 EXP_BIAS24 = 63, 210 EXP_MASK32 = 0x7F800000, 211 EXP_MASK24 = 0x007F0000, 212 213 FRACTION_WIDTH32 = 23, 214 FRACTION_MASK32 = 0x007FFFFF, 215 FRACTION_WIDTH24 = 16, 216 FRACTION_MASK24 = 0x0000FFFF 217 }; 218 }; 219 220 //-------------------------------------------------------------------------- 221 //! @brief 31bit 浮動小数用のユーティリティです。 222 // 223 // 31bit 浮動小数のビットフォーマットは次の通りです。 224 // | sign | exponent | fraction | 225 // sign : 符号 1 bit. 226 // exponent : 指数部 7 bit. bias 63. 227 // fraction : 仮数部 23 bit. 228 //--------------------------------------------------------------------------- 229 class Float31 230 { 231 public: 232 //-------------------------------------------------------------------------- 233 //! @brief デフォルトコンストラクタです。 234 //-------------------------------------------------------------------------- Float31()235 Float31() : m_Float32( 0.0f ) {} 236 237 //-------------------------------------------------------------------------- 238 //! @brief コンストラクタです。 239 //! 240 //! @param[in] bits31 31bit 浮動小数のビットを表現した整数値です。 241 //-------------------------------------------------------------------------- Float31(u32 bits31)242 /* implicit */ Float31( u32 bits31 ) 243 { 244 m_Float32 = Bits31ToFloat32( bits31 ); 245 } 246 247 //-------------------------------------------------------------------------- 248 //! @brief コンストラクタです。 249 //! 250 //! @param[in] value 32bit 浮動小数の値から 31bit float を生成します。 251 //-------------------------------------------------------------------------- Float31(f32 value)252 /* implicit */ Float31( f32 value ) : m_Float32( value ) {} 253 GetFloat32Value()254 f32 GetFloat32Value() const { return m_Float32; } GetFloat31Value()255 u32 GetFloat31Value() const { return Float32ToBits31( m_Float32 ); } 256 257 Float31& operator =(f32 value) { this->m_Float32 = value; return *this; } 258 Float31& operator =(u32 bits31) { this->m_Float32 = Bits31ToFloat32( bits31 ); return *this; } 259 f32()260 operator f32() const { return m_Float32; } 261 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 f32 operator /(f32 right) const { return this->m_Float32 / right; } 266 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 Float31& operator /=(f32 rhs) { this->m_Float32 /= rhs; return *this; } 271 272 bool operator ==(f32 rhs) const { return (rhs == this->m_Float32); } 273 bool operator !=(f32 rhs) const { return !(*this == rhs); } 274 275 //-------------------------------------------------------------------------- 276 //! @brief 31bit float から 32bit float に変換します。 277 //! 278 //! @param[in] bits31 31bit 浮動小数のビットを表現した整数値です。 279 //! 280 //! @return f32 に変換した値を返します。 281 //-------------------------------------------------------------------------- Bits31ToFloat32(u32 bits31)282 static f32 Bits31ToFloat32(u32 bits31) 283 { 284 u32 sign = bits31 & SIGN31; 285 int exp = (int)((bits31 & EXP_MASK31) >> FRACTION_WIDTH31); 286 u32 fraction = bits31 & FRACTION_MASK31; 287 288 u32 bits32 = 0; 289 bits32 |= (sign != 0) ? SIGN32 : 0; 290 291 if ((bits31 & ~SIGN31) == 0) 292 { 293 exp = 0; 294 } 295 else 296 { 297 exp = exp - EXP_BIAS31 + EXP_BIAS32; 298 } 299 300 // ビット拡張なので、exp がオーバーフローすることは無い。 301 bits32 |= fraction & FRACTION_MASK32; 302 bits32 |= ((u32)exp & 0xFF) << FRACTION_WIDTH32; 303 304 return *reinterpret_cast<f32*>(&bits32); 305 } 306 307 //-------------------------------------------------------------------------- 308 //! @brief f32 から 31bit float に変換します。 309 //! 310 //! @param[in] value 32bit float の値です。 311 //! 312 //! @return 31bit 浮動小数のビット表現を返します。 313 //-------------------------------------------------------------------------- Float32ToBits31(f32 value)314 static u32 Float32ToBits31(f32 value) 315 { 316 u32 bits32 = *reinterpret_cast<u32*>(&value); 317 318 u32 sign = bits32 & SIGN32; 319 int exp = (int)((bits32 & EXP_MASK32) >> FRACTION_WIDTH32); 320 u32 fraction = bits32 & FRACTION_MASK32; 321 322 u32 bits31 = 0; 323 bits31 |= (sign != 0) ? SIGN31 : 0; 324 325 if ((bits32 & ~SIGN32) == 0) 326 { 327 exp = 0; 328 } 329 else 330 { 331 exp = exp - EXP_BIAS32 + EXP_BIAS31; 332 } 333 334 if (exp < 0) 335 { 336 // +0 もしくは -0 なのでそのまま。 337 } 338 else if (exp > 127) 339 { 340 // 無限大の処理 341 // TODO: IEEE float の無限大の表現がGPU上で有効なのかどうかを要確認。 342 bits31 = (u32)0x7F << FRACTION_WIDTH31; 343 } 344 else 345 { 346 bits31 |= fraction & FRACTION_MASK31; 347 bits31 |= ((u32)exp & 0x7F) << FRACTION_WIDTH31; 348 } 349 350 return bits31; 351 } 352 353 private: 354 f32 m_Float32; 355 356 enum 357 { 358 SIGN32 = 0x80000000, 359 SIGN31 = 0x40000000, 360 361 EXP_BIAS32 = 127, 362 EXP_BIAS31 = 63, 363 EXP_MASK32 = 0x7F800000, 364 EXP_MASK31 = 0x3F800000, 365 366 FRACTION_WIDTH32 = 23, 367 FRACTION_MASK32 = 0x007FFFFF, 368 FRACTION_WIDTH31 = 23, 369 FRACTION_MASK31 = 0x007FFFFF 370 }; 371 }; 372 373 374 //-------------------------------------------------------------------------- 375 //! @brief 20bit 浮動小数用のユーティリティです。 376 // 377 // 20bit 浮動小数のビットフォーマットは次の通りです。 378 // | sign | exponent | fraction | 379 // sign : 符号 1 bit. 380 // exponent : 指数部 7 bit. bias 63. 381 // fraction : 仮数部 12 bit. 382 //--------------------------------------------------------------------------- 383 class Float20 384 { 385 public: 386 //-------------------------------------------------------------------------- 387 //! @brief デフォルトコンストラクタです。 388 //-------------------------------------------------------------------------- Float20()389 Float20() : m_Float32( 0.0f ) {} 390 391 //-------------------------------------------------------------------------- 392 //! @brief コンストラクタです。 393 //! 394 //! @param[in] bits20 20bit 浮動小数のビットを表現した整数値です。 395 //-------------------------------------------------------------------------- Float20(u32 bits20)396 /* implicit */ Float20( u32 bits20 ) 397 { 398 m_Float32 = Bits20ToFloat32( bits20 ); 399 } 400 401 //-------------------------------------------------------------------------- 402 //! @brief コンストラクタです。 403 //! 404 //! @param[in] value 32bit 浮動小数の値から 20bit float を生成します。 405 //-------------------------------------------------------------------------- Float20(f32 value)406 /* implicit */ Float20( f32 value ) : m_Float32( value ) {} 407 GetFloat32Value()408 f32 GetFloat32Value() const { return m_Float32; } GetFloat20Value()409 u32 GetFloat20Value() const { return Float32ToBits20( m_Float32 ); } 410 411 Float20& operator =(f32 value) { this->m_Float32 = value; return *this; } 412 Float20& operator =(u32 bits20) { this->m_Float32 = Bits20ToFloat32( bits20 ); return *this; } 413 f32()414 operator f32() const { return m_Float32; } 415 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 f32 operator /(f32 right) const { return this->m_Float32 / right; } 420 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 Float20& operator /=(f32 rhs) { this->m_Float32 /= rhs; return *this; } 425 426 bool operator ==(f32 rhs) const { return (rhs == this->m_Float32); } 427 bool operator !=(f32 rhs) const { return !(*this == rhs); } 428 429 //-------------------------------------------------------------------------- 430 //! @brief 20bit float から 32bit float に変換します。 431 //! 432 //! @param[in] bits20 20bit 浮動小数のビットを表現した整数値です。 433 //! 434 //! @return f32 に変換した値を返します。 435 //-------------------------------------------------------------------------- Bits20ToFloat32(u32 bits20)436 static f32 Bits20ToFloat32(u32 bits20) 437 { 438 u32 sign = bits20 & SIGN20; 439 int exp = (int)((bits20 & EXP_MASK20) >> FRACTION_WIDTH20); 440 u32 fraction = bits20 & FRACTION_MASK20; 441 442 u32 bits32 = 0; 443 bits32 |= (sign != 0) ? SIGN32 : 0; 444 445 if ((bits20 & ~SIGN20) == 0) 446 { 447 exp = 0; 448 } 449 else 450 { 451 exp = exp - EXP_BIAS20 + EXP_BIAS32; 452 } 453 454 fraction = fraction << (FRACTION_WIDTH32 - FRACTION_WIDTH20); 455 456 // ビット拡張なので、exp がオーバーフローすることは無い。 457 bits32 |= fraction & FRACTION_MASK32; 458 bits32 |= ((u32)exp & 0xFF) << FRACTION_WIDTH32; 459 460 return *reinterpret_cast<f32*>(&bits32); 461 } 462 463 //-------------------------------------------------------------------------- 464 //! @brief f32 から 20bit float に変換します。 465 //! 466 //! @param[in] value 32bit float の値です。 467 //! 468 //! @return 20bit 浮動小数のビット表現を返します。 469 //-------------------------------------------------------------------------- Float32ToBits20(f32 value)470 static u32 Float32ToBits20(f32 value) 471 { 472 u32 bits32 = *reinterpret_cast<u32*>(&value); 473 474 u32 sign = bits32 & SIGN32; 475 int exp = (int)((bits32 & EXP_MASK32) >> FRACTION_WIDTH32); 476 u32 fraction = bits32 & FRACTION_MASK32; 477 478 u32 bits20 = 0; 479 bits20 |= (sign != 0) ? SIGN20 : 0; 480 481 if ((bits32 & ~SIGN32) == 0) 482 { 483 exp = 0; 484 } 485 else 486 { 487 exp = exp - EXP_BIAS32 + EXP_BIAS20; 488 } 489 490 fraction = fraction >> (FRACTION_WIDTH32 - FRACTION_WIDTH20); 491 492 if (exp < 0) 493 { 494 // +0 もしくは -0 なのでそのまま。 495 } 496 else if (exp > 127) 497 { 498 // 無限大の処理 499 // TODO: IEEE float の無限大の表現がGPU上で有効なのかどうかを要確認。 500 bits20 = (u32)0x7F << FRACTION_WIDTH20; 501 } 502 else 503 { 504 bits20 |= fraction & FRACTION_MASK20; 505 bits20 |= ((u32)exp & 0x7F) << FRACTION_WIDTH20; 506 } 507 508 return bits20; 509 } 510 511 private: 512 f32 m_Float32; 513 514 enum 515 { 516 SIGN32 = 0x80000000, 517 SIGN20 = 0x00080000, 518 519 EXP_BIAS32 = 127, 520 EXP_BIAS20 = 63, 521 EXP_MASK32 = 0x7F800000, 522 EXP_MASK20 = 0x0007F000, 523 524 FRACTION_WIDTH32 = 23, 525 FRACTION_MASK32 = 0x007FFFFF, 526 FRACTION_WIDTH20 = 12, 527 FRACTION_MASK20 = 0x00000FFF 528 }; 529 }; 530 531 532 //-------------------------------------------------------------------------- 533 //! @brief 16bit 浮動小数用のユーティリティです。 534 // 535 // 16bit 浮動小数のビットフォーマットは次の通りです。 536 // | sign | exponent | fraction | 537 // sign : 符号 1 bit. 538 // exponent : 指数部 5 bit. bias 15. 539 // fraction : 仮数部 10 bit. 540 //--------------------------------------------------------------------------- 541 class Float16 542 { 543 public: 544 //-------------------------------------------------------------------------- 545 //! @brief デフォルトコンストラクタです。 546 //-------------------------------------------------------------------------- Float16()547 Float16() : m_Float32( 0.0f ) {} 548 549 //-------------------------------------------------------------------------- 550 //! @brief コンストラクタです。 551 //! 552 //! @param[in] bits16 16bit 浮動小数のビットを表現した整数値です。 553 //-------------------------------------------------------------------------- Float16(u32 bits16)554 /* implicit */ Float16( u32 bits16 ) 555 { 556 m_Float32 = Bits16ToFloat32( bits16 ); 557 } 558 559 //-------------------------------------------------------------------------- 560 //! @brief コンストラクタです。 561 //! 562 //! @param[in] value 32bit 浮動小数の値から 16bit float を生成します。 563 //-------------------------------------------------------------------------- Float16(f32 value)564 /* implicit */ Float16( f32 value ) : m_Float32( value ) {} 565 GetFloat32Value()566 f32 GetFloat32Value() const { return m_Float32; } GetFloat16Value()567 u16 GetFloat16Value() const { return Float32ToBits16( m_Float32 ); } 568 569 Float16& operator =(f32 value) { this->m_Float32 = value; return *this; } 570 Float16& operator =(u32 bits16) { this->m_Float32 = Bits16ToFloat32( bits16 ); return *this; } 571 f32()572 operator f32() const { return m_Float32; } u16()573 operator u16() const { return GetFloat16Value(); } 574 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 f32 operator /(f32 right) const { return this->m_Float32 / right; } 579 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 Float16& operator /=(f32 rhs) { this->m_Float32 /= rhs; return *this; } 584 585 bool operator ==(f32 rhs) const { return (rhs == this->m_Float32); } 586 bool operator !=(f32 rhs) const { return !(*this == rhs); } 587 588 //-------------------------------------------------------------------------- 589 //! @brief 16bit float から 32bit float に変換します。 590 //! 591 //! @param[in] bits16 16bit 浮動小数のビットを表現した整数値です。 592 //! 593 //! @return f32 に変換した値を返します。 594 //-------------------------------------------------------------------------- Bits16ToFloat32(u32 bits16)595 static f32 Bits16ToFloat32(u32 bits16) 596 { 597 u32 sign = bits16 & SIGN16; 598 int exp = (int)((bits16 & EXP_MASK16) >> FRACTION_WIDTH16); 599 u32 fraction = bits16 & FRACTION_MASK16; 600 601 u32 bits32 = 0; 602 bits32 |= (sign != 0) ? SIGN32 : 0; 603 604 if ((bits16 & ~SIGN16) == 0) 605 { 606 exp = 0; 607 } 608 else 609 { 610 exp = exp - EXP_BIAS16 + EXP_BIAS32; 611 } 612 613 fraction = fraction << (FRACTION_WIDTH32 - FRACTION_WIDTH16); 614 615 // ビット拡張なので、exp がオーバーフローすることは無い。 616 bits32 |= fraction & FRACTION_MASK32; 617 bits32 |= ((u32)exp & 0xFF) << FRACTION_WIDTH32; 618 619 return *reinterpret_cast<f32*>(&bits32); 620 } 621 622 //-------------------------------------------------------------------------- 623 //! @brief f32 から 16bit float に変換します。 624 //! 625 //! @param[in] value 32bit float の値です。 626 //! 627 //! @return 16bit 浮動小数のビット表現を返します。 628 //-------------------------------------------------------------------------- Float32ToBits16(f32 value)629 static u16 Float32ToBits16(f32 value) 630 { 631 u32 bits32 = *reinterpret_cast<u32*>(&value); 632 633 u32 sign = bits32 & SIGN32; 634 int exp = (int)((bits32 & EXP_MASK32) >> FRACTION_WIDTH32); 635 u32 fraction = bits32 & FRACTION_MASK32; 636 637 u32 bits16 = 0; 638 bits16 |= (sign != 0) ? SIGN16 : 0; 639 640 if ((bits32 & ~SIGN32) == 0) 641 { 642 exp = 0; 643 } 644 else 645 { 646 exp = exp - EXP_BIAS32 + EXP_BIAS16; 647 } 648 649 fraction = fraction >> (FRACTION_WIDTH32 - FRACTION_WIDTH16); 650 651 if (exp < 0) 652 { 653 // +0 もしくは -0 なのでそのまま。 654 } 655 else if (exp > 31) 656 { 657 // 無限大の処理 658 // TODO: IEEE float の無限大の表現がGPU上で有効なのかどうかを要確認。 659 bits16 = (u32)0x1F << FRACTION_WIDTH16; 660 } 661 else 662 { 663 bits16 |= fraction & FRACTION_MASK16; 664 bits16 |= ((u32)exp & 0x1F) << FRACTION_WIDTH16; 665 } 666 667 return static_cast<u16>(bits16); 668 } 669 670 private: 671 f32 m_Float32; 672 673 enum 674 { 675 SIGN32 = 0x80000000, 676 SIGN16 = 0x00008000, 677 678 EXP_BIAS32 = 127, 679 EXP_BIAS16 = 15, 680 EXP_MASK32 = 0x7F800000, 681 EXP_MASK16 = 0x00007C00, 682 683 FRACTION_WIDTH32 = 23, 684 FRACTION_MASK32 = 0x007FFFFF, 685 FRACTION_WIDTH16 = 10, 686 FRACTION_MASK16 = 0x000003FF 687 }; 688 }; 689 690 //-------------------------------------------------------------------------- 691 //! @brief 13bit 固定小数用のユーティリティです。 692 // 693 // 13bit 固定小数のビットフォーマットは次の通りです。 694 // | int | decimal | (2の補数) 695 // int : 整数部 2 bit. 696 // decimal : 小数部 11 bit. 697 //--------------------------------------------------------------------------- 698 class Fixed13 699 { 700 public: 701 //-------------------------------------------------------------------------- 702 //! @brief デフォルトコンストラクタです。 703 //-------------------------------------------------------------------------- Fixed13()704 Fixed13() : m_Float32( 0.0f ) {} 705 706 //-------------------------------------------------------------------------- 707 //! @brief コンストラクタです。 708 //! 709 //! @param[in] fixed13 13bit 固定小数のビットを表現した整数値です。 710 //-------------------------------------------------------------------------- Fixed13(u32 fixed13)711 explicit Fixed13( u32 fixed13 ) 712 { 713 m_Float32 = Fixed13ToFloat32( fixed13 ); 714 } 715 716 //-------------------------------------------------------------------------- 717 //! @brief コンストラクタです。 718 //! 719 //! @param[in] fvalue 32bit 浮動小数の値です。 720 //-------------------------------------------------------------------------- Fixed13(f32 fvalue)721 explicit Fixed13( f32 fvalue ) 722 { 723 m_Float32 = fvalue; 724 } 725 726 GetFloat32Value()727 f32 GetFloat32Value() const { return m_Float32; } GetFixed13Value()728 u16 GetFixed13Value() const { return Float32ToFixed13( m_Float32 ); } 729 730 //-------------------------------------------------------------------------- 731 //! @brief 13bit fixed から 32bit float に変換します。 732 //! 733 //! @param[in] fixed13 13bit 固定小数のビットを表現した整数値です。 734 //! 735 //! @return f32 に変換した値を返します。 736 //-------------------------------------------------------------------------- Fixed13ToFloat32(u32 fixed13)737 static f32 Fixed13ToFloat32(u32 fixed13) 738 { 739 f32 float32 = static_cast<f32>(fixed13); 740 741 if (fixed13 & (0x1 << (TOTAL_WIDTH - 1))) 742 { 743 float32 -= (0x1 << TOTAL_WIDTH); 744 } 745 746 return float32 / (0x1 << DECIMAL_WIDTH); 747 } 748 749 //-------------------------------------------------------------------------- 750 //! @brief f32 から 13bit fixed に変換します。 751 //! 752 //! @param[in] value 32bit float の値です。 753 //! 754 //! @return 16bit 浮動小数のビット表現を返します。 755 //-------------------------------------------------------------------------- Float32ToFixed13(f32 value)756 static u16 Float32ToFixed13(f32 value) 757 { 758 f32 fixed = value; 759 fixed += ((0x1 << INT_WIDTH) / 2); 760 fixed *= (0x1 << DECIMAL_WIDTH); 761 762 if (fixed < 0) 763 { 764 fixed = 0.0f; 765 } 766 else if (fixed >= (0x1 << TOTAL_WIDTH)) 767 { 768 fixed = (0x1 << TOTAL_WIDTH) - 1; 769 } 770 771 fixed -= 0x1 << (TOTAL_WIDTH - 1); 772 773 return static_cast<u16>(static_cast<s16>(fixed) & MASK); 774 } 775 776 private: 777 f32 m_Float32; 778 779 enum 780 { 781 INT_WIDTH = 2, 782 DECIMAL_WIDTH = 11, 783 TOTAL_WIDTH = 13, 784 MASK = (0x1 << TOTAL_WIDTH) - 1 785 }; 786 }; 787 788 789 //-------------------------------------------------------------------------- 790 //! @brief 11bit 固定小数用のユーティリティです。 791 // 792 // 11bit 固定小数のビットフォーマットは次の通りです。 793 // decimal : 小数部 11 bit. 794 //--------------------------------------------------------------------------- 795 class Fixed11 796 { 797 public: 798 //-------------------------------------------------------------------------- 799 //! @brief デフォルトコンストラクタです。 800 //-------------------------------------------------------------------------- Fixed11()801 Fixed11() : m_Float32( 0.0f ) {} 802 803 //-------------------------------------------------------------------------- 804 //! @brief コンストラクタです。 805 //! 806 //! @param[in] fixed11 11bit 固定小数のビットを表現した整数値です。 807 //-------------------------------------------------------------------------- Fixed11(u32 fixed11)808 explicit Fixed11( u32 fixed11 ) 809 { 810 m_Float32 = Fixed11ToFloat32( fixed11 ); 811 } 812 813 //-------------------------------------------------------------------------- 814 //! @brief コンストラクタです。 815 //! 816 //! @param[in] fvalue 32bit 浮動小数の値です。 817 //-------------------------------------------------------------------------- Fixed11(f32 fvalue)818 explicit Fixed11( f32 fvalue ) 819 { 820 m_Float32 = fvalue; 821 } 822 823 GetFloat32Value()824 f32 GetFloat32Value() const { return m_Float32; } GetFixed11Value()825 u16 GetFixed11Value() const { return Float32ToFixed11( m_Float32 ); } 826 827 //-------------------------------------------------------------------------- 828 //! @brief 11bit fixed から 32bit float に変換します。 829 //! 830 //! @param[in] fixed11 11bit 固定小数のビットを表現した整数値です。 831 //! 832 //! @return f32 に変換した値を返します。 833 //-------------------------------------------------------------------------- Fixed11ToFloat32(u32 fixed11)834 static f32 Fixed11ToFloat32(u32 fixed11) 835 { 836 f32 float32 = static_cast<f32>(fixed11); 837 return float32 / MASK; 838 } 839 840 //-------------------------------------------------------------------------- 841 //! @brief f32 から 11bit fixed に変換します。 842 //! 843 //! @param[in] value 32bit float の値です。 844 //! 845 //! @return 16bit 浮動小数のビット表現を返します。 846 //-------------------------------------------------------------------------- Float32ToFixed11(f32 value)847 static u16 Float32ToFixed11(f32 value) 848 { 849 u32 fixed; 850 u32 v_ = *(u32*)&value; 851 852 if (value <= 0 || (v_ & 0x7f800000) == 0x7f800000) 853 { 854 fixed = 0; 855 } 856 else 857 { 858 value *= 1 << (DECIMAL_WIDTH - 0); 859 if (value >= (1 << DECIMAL_WIDTH)) 860 { 861 fixed = (1 << DECIMAL_WIDTH) - 1; 862 } 863 else 864 { 865 fixed = (unsigned)(value); 866 } 867 } 868 869 return static_cast<u16>(static_cast<s16>(fixed) & MASK); 870 } 871 872 private: 873 f32 m_Float32; 874 875 enum 876 { 877 INT_WIDTH = 2, 878 DECIMAL_WIDTH = 11, 879 TOTAL_WIDTH = 11, 880 MASK = (0x1 << TOTAL_WIDTH) - 1 881 }; 882 }; 883 884 } /* namespace util */ 885 } /* namespace nn */ 886 887 #endif // __cplusplus 888 889 #endif // NN_UTIL_UTIL_FLOAT24_H_ 890