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
JavaScript
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