@openhps/core
Version:
Open Hybrid Positioning System - Core component
159 lines (142 loc) • 4.47 kB
JavaScript
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 };