UNPKG

@openhps/core

Version:

Open Hybrid Positioning System - Core component

159 lines (142 loc) 4.47 kB
import { clamp } from '../math/MathUtils.js'; // Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf const _tables = /*@__PURE__*/_generateTables(); function _generateTables() { // float32 to float16 helpers const buffer = new ArrayBuffer(4); const floatView = new Float32Array(buffer); const uint32View = new Uint32Array(buffer); const baseTable = new Uint32Array(512); const shiftTable = new Uint32Array(512); for (let i = 0; i < 256; ++i) { const e = i - 127; // very small number (0, -0) if (e < -27) { baseTable[i] = 0x0000; baseTable[i | 0x100] = 0x8000; shiftTable[i] = 24; shiftTable[i | 0x100] = 24; // small number (denorm) } else if (e < -14) { baseTable[i] = 0x0400 >> -e - 14; baseTable[i | 0x100] = 0x0400 >> -e - 14 | 0x8000; shiftTable[i] = -e - 1; shiftTable[i | 0x100] = -e - 1; // normal number } else if (e <= 15) { baseTable[i] = e + 15 << 10; baseTable[i | 0x100] = e + 15 << 10 | 0x8000; shiftTable[i] = 13; shiftTable[i | 0x100] = 13; // large number (Infinity, -Infinity) } else if (e < 128) { baseTable[i] = 0x7c00; baseTable[i | 0x100] = 0xfc00; shiftTable[i] = 24; shiftTable[i | 0x100] = 24; // stay (NaN, Infinity, -Infinity) } else { baseTable[i] = 0x7c00; baseTable[i | 0x100] = 0xfc00; shiftTable[i] = 13; shiftTable[i | 0x100] = 13; } } // float16 to float32 helpers const mantissaTable = new Uint32Array(2048); const exponentTable = new Uint32Array(64); const offsetTable = new Uint32Array(64); for (let i = 1; i < 1024; ++i) { let m = i << 13; // zero pad mantissa bits let e = 0; // zero exponent // normalized while ((m & 0x00800000) === 0) { m <<= 1; e -= 0x00800000; // decrement exponent } m &= ~0x00800000; // clear leading 1 bit e += 0x38800000; // adjust bias mantissaTable[i] = m | e; } for (let i = 1024; i < 2048; ++i) { mantissaTable[i] = 0x38000000 + (i - 1024 << 13); } for (let i = 1; i < 31; ++i) { exponentTable[i] = i << 23; } exponentTable[31] = 0x47800000; exponentTable[32] = 0x80000000; for (let i = 33; i < 63; ++i) { exponentTable[i] = 0x80000000 + (i - 32 << 23); } exponentTable[63] = 0xc7800000; for (let i = 1; i < 64; ++i) { if (i !== 32) { offsetTable[i] = 1024; } } return { floatView: floatView, uint32View: uint32View, baseTable: baseTable, shiftTable: shiftTable, mantissaTable: mantissaTable, exponentTable: exponentTable, offsetTable: offsetTable }; } /** * Returns a half precision floating point value (FP16) from the given single * precision floating point value (FP32). * * @param {number} val - A single precision floating point value. * @return {number} The FP16 value. */ function toHalfFloat(val) { if (Math.abs(val) > 65504) console.warn('THREE.DataUtils.toHalfFloat(): Value out of range.'); val = clamp(val, -65504, 65504); _tables.floatView[0] = val; const f = _tables.uint32View[0]; const e = f >> 23 & 0x1ff; return _tables.baseTable[e] + ((f & 0x007fffff) >> _tables.shiftTable[e]); } /** * Returns a single precision floating point value (FP32) from the given half * precision floating point value (FP16). * * @param {number} val - A half precision floating point value. * @return {number} The FP32 value. */ function fromHalfFloat(val) { const m = val >> 10; _tables.uint32View[0] = _tables.mantissaTable[_tables.offsetTable[m] + (val & 0x3ff)] + _tables.exponentTable[m]; return _tables.floatView[0]; } /** * A class containing utility functions for data. * * @hideconstructor */ class DataUtils { /** * Returns a half precision floating point value (FP16) from the given single * precision floating point value (FP32). * * @param {number} val - A single precision floating point value. * @return {number} The FP16 value. */ static toHalfFloat(val) { return toHalfFloat(val); } /** * Returns a single precision floating point value (FP32) from the given half * precision floating point value (FP16). * * @param {number} val - A half precision floating point value. * @return {number} The FP32 value. */ static fromHalfFloat(val) { return fromHalfFloat(val); } } export { toHalfFloat, fromHalfFloat, DataUtils };