UNPKG

image-in-browser

Version:

Package for encoding / decoding images, transforming images, applying filters, drawing primitives on images on the client side (no need for server Node.js)

210 lines 6.05 kB
import { BitUtils } from './bit-utils.js'; export class Float16 { static get _toFloatFloat32() { return this._toFloatFloat32Data !== undefined ? this._toFloatFloat32Data : this.initialize(); } constructor(f) { this.bits = f !== undefined ? Float16.doubleToFloat16(f) : 0; } static convert(i) { const s = (i >>> 16) & 0x00008000; let e = ((i >>> 23) & 0x000000ff) - (127 - 15); let m = i & 0x007fffff; if (e <= 0) { if (e < -10) { return s; } m |= 0x00800000; const t = 14 - e; const a = (1 << (t - 1)) - 1; const b = (m >>> t) & 1; m = (m + a + b) >>> t; return s | m; } else if (e === 0xff - (127 - 15)) { if (m === 0) { return s | 0x7c00; } else { m >>>= 13; return s | 0x7c00 | m | (m === 0 ? 1 : 0); } } else { m = m + 0x00000fff + ((m >>> 13) & 1); if ((m & 0x00800000) !== 0) { m = 0; e += 1; } if (e > 30) { return s | 0x7c00; } return s | (e << 10) | (m >>> 13); } } static initialize() { if (this._toFloatFloat32Data !== undefined) { return this._toFloatFloat32Data; } const floatUint32Data = new Uint32Array(1 << 16); this._toFloatFloat32Data = new Float32Array(floatUint32Data.buffer); this._eLut = new Uint16Array(1 << 9); for (let i = 0; i < 0x100; i++) { const e = (i & 0x0ff) - (127 - 15); if (e <= 0 || e >= 30) { this._eLut[i] = 0; this._eLut[i | 0x100] = 0; } else { this._eLut[i] = e << 10; this._eLut[i | 0x100] = (e << 10) | 0x8000; } } const iMax = 1 << 16; for (let i = 0; i < iMax; i++) { floatUint32Data[i] = this.halfToFloat(i); } return this._toFloatFloat32Data; } static halfToFloat(y) { const s = (y >>> 15) & 0x00000001; let e = (y >>> 10) & 0x0000001f; let m = y & 0x000003ff; if (e === 0) { if (m === 0) { return s << 31; } else { while ((m & 0x00000400) === 0) { m <<= 1; e -= 1; } e += 1; m &= ~0x00000400; } } else if (e === 31) { if (m === 0) { return (s << 31) | 0x7f800000; } else { return (s << 31) | 0x7f800000 | (m << 13); } } e += 127 - 15; m <<= 13; return (s << 31) | (e << 23) | m; } static from(other) { const float16 = new Float16(); float16.bits = other.bits; return float16; } static fromBits(bits) { const float16 = new Float16(); float16.bits = bits; return float16; } static float16ToDouble(bits) { return this._toFloatFloat32[bits]; } static doubleToFloat16(n) { const f = n; const xI = BitUtils.float32ToUint32(f); if (f === 0) { return xI >>> 16; } if (this._toFloatFloat32Data === undefined) { this.initialize(); } let e = (xI >>> 23) & 0x000001ff; e = this._eLut[e]; if (e !== 0) { const m = xI & 0x007fffff; return e + ((m + 0x00000fff + ((m >>> 13) & 1)) >>> 13); } return this.convert(xI); } static posInf() { return Float16.fromBits(0x7c00); } static negInf() { return Float16.fromBits(0xfc00); } static qNan() { return Float16.fromBits(0x7fff); } static sNan() { return Float16.fromBits(0x7dff); } toDouble() { return Float16._toFloatFloat32[this.bits]; } minus() { return Float16.fromBits(this.bits ^ 0x8000); } add(f) { const d = f instanceof Float16 ? f.toDouble() : typeof f === 'number' ? f : 0; return new Float16(this.toDouble() + d); } sub(f) { const d = f instanceof Float16 ? f.toDouble() : typeof f === 'number' ? f : 0; return new Float16(this.toDouble() - d); } mul(f) { const d = f instanceof Float16 ? f.toDouble() : typeof f === 'number' ? f : 0; return new Float16(this.toDouble() * d); } div(f) { const d = f instanceof Float16 ? f.toDouble() : typeof f === 'number' ? f : 0; return new Float16(this.toDouble() / d); } round(n) { if (n >= 10) { return Float16.from(this); } const s = this.bits & 0x8000; let e = this.bits & 0x7fff; e >>>= 9 - n; e += e & 1; e <<= 9 - n; if (e >= 0x7c00) { e = this.bits; e >>>= 10 - n; e <<= 10 - n; } return Float16.fromBits(s | e); } isFinite() { const e = (this.bits >>> 10) & 0x001f; return e < 31; } isNormalized() { const e = (this.bits >>> 10) & 0x001f; return e > 0 && e < 31; } isDenormalized() { const e = (this.bits >>> 10) & 0x001f; const m = this.bits & 0x3ff; return e === 0 && m !== 0; } isZero() { return (this.bits & 0x7fff) === 0; } isNaN() { const e = (this.bits >>> 10) & 0x001f; const m = this.bits & 0x3ff; return e === 31 && m !== 0; } isInfinity() { const e = (this.bits >>> 10) & 0x001f; const m = this.bits & 0x3ff; return e === 31 && m === 0; } isNegative() { return (this.bits & 0x8000) !== 0; } } //# sourceMappingURL=float16.js.map