DataUtils.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import { clamp } from '../math/MathUtils.js';
  2. // Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
  3. const _tables = /*@__PURE__*/ _generateTables();
  4. function _generateTables() {
  5. // float32 to float16 helpers
  6. const buffer = new ArrayBuffer( 4 );
  7. const floatView = new Float32Array( buffer );
  8. const uint32View = new Uint32Array( buffer );
  9. const baseTable = new Uint32Array( 512 );
  10. const shiftTable = new Uint32Array( 512 );
  11. for ( let i = 0; i < 256; ++ i ) {
  12. const e = i - 127;
  13. // very small number (0, -0)
  14. if ( e < - 27 ) {
  15. baseTable[ i ] = 0x0000;
  16. baseTable[ i | 0x100 ] = 0x8000;
  17. shiftTable[ i ] = 24;
  18. shiftTable[ i | 0x100 ] = 24;
  19. // small number (denorm)
  20. } else if ( e < - 14 ) {
  21. baseTable[ i ] = 0x0400 >> ( - e - 14 );
  22. baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000;
  23. shiftTable[ i ] = - e - 1;
  24. shiftTable[ i | 0x100 ] = - e - 1;
  25. // normal number
  26. } else if ( e <= 15 ) {
  27. baseTable[ i ] = ( e + 15 ) << 10;
  28. baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000;
  29. shiftTable[ i ] = 13;
  30. shiftTable[ i | 0x100 ] = 13;
  31. // large number (Infinity, -Infinity)
  32. } else if ( e < 128 ) {
  33. baseTable[ i ] = 0x7c00;
  34. baseTable[ i | 0x100 ] = 0xfc00;
  35. shiftTable[ i ] = 24;
  36. shiftTable[ i | 0x100 ] = 24;
  37. // stay (NaN, Infinity, -Infinity)
  38. } else {
  39. baseTable[ i ] = 0x7c00;
  40. baseTable[ i | 0x100 ] = 0xfc00;
  41. shiftTable[ i ] = 13;
  42. shiftTable[ i | 0x100 ] = 13;
  43. }
  44. }
  45. // float16 to float32 helpers
  46. const mantissaTable = new Uint32Array( 2048 );
  47. const exponentTable = new Uint32Array( 64 );
  48. const offsetTable = new Uint32Array( 64 );
  49. for ( let i = 1; i < 1024; ++ i ) {
  50. let m = i << 13; // zero pad mantissa bits
  51. let e = 0; // zero exponent
  52. // normalized
  53. while ( ( m & 0x00800000 ) === 0 ) {
  54. m <<= 1;
  55. e -= 0x00800000; // decrement exponent
  56. }
  57. m &= ~ 0x00800000; // clear leading 1 bit
  58. e += 0x38800000; // adjust bias
  59. mantissaTable[ i ] = m | e;
  60. }
  61. for ( let i = 1024; i < 2048; ++ i ) {
  62. mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 );
  63. }
  64. for ( let i = 1; i < 31; ++ i ) {
  65. exponentTable[ i ] = i << 23;
  66. }
  67. exponentTable[ 31 ] = 0x47800000;
  68. exponentTable[ 32 ] = 0x80000000;
  69. for ( let i = 33; i < 63; ++ i ) {
  70. exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 );
  71. }
  72. exponentTable[ 63 ] = 0xc7800000;
  73. for ( let i = 1; i < 64; ++ i ) {
  74. if ( i !== 32 ) {
  75. offsetTable[ i ] = 1024;
  76. }
  77. }
  78. return {
  79. floatView: floatView,
  80. uint32View: uint32View,
  81. baseTable: baseTable,
  82. shiftTable: shiftTable,
  83. mantissaTable: mantissaTable,
  84. exponentTable: exponentTable,
  85. offsetTable: offsetTable
  86. };
  87. }
  88. // float32 to float16
  89. function toHalfFloat( val ) {
  90. if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' );
  91. val = clamp( val, - 65504, 65504 );
  92. _tables.floatView[ 0 ] = val;
  93. const f = _tables.uint32View[ 0 ];
  94. const e = ( f >> 23 ) & 0x1ff;
  95. return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] );
  96. }
  97. // float16 to float32
  98. function fromHalfFloat( val ) {
  99. const m = val >> 10;
  100. _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ];
  101. return _tables.floatView[ 0 ];
  102. }
  103. const DataUtils = {
  104. toHalfFloat: toHalfFloat,
  105. fromHalfFloat: fromHalfFloat,
  106. };
  107. export {
  108. toHalfFloat,
  109. fromHalfFloat,
  110. DataUtils
  111. };
粤ICP备19079148号