Skip to content

Commit

Permalink
Added Float16
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderOMara committed Nov 16, 2024
1 parent 0555da9 commit 0a1bd76
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 1 deletion.
3 changes: 2 additions & 1 deletion deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"license": "MIT",
"exports": {
".": "./mod.ts",
"./i24": "./i24.ts"
"./i24": "./i24.ts",
"./f16": "./f16.ts"
},
"imports": {
"@deno/dnt": "jsr:@deno/dnt@^0.41.3",
Expand Down
71 changes: 71 additions & 0 deletions f16.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { assertEquals } from '@std/assert';

import { getFloat16, setFloat16 } from './f16.ts';
import f16 from './spec/f16.json' with { type: 'json' };
import f64i16 from './spec/f64i16.json' with { type: 'json' };

const F16 = (f16 as (string | number)[]).map(Number);
const F64I16 = (f64i16 as (string | number)[][]).map((a) => a.map(Number)) as [
number,
number,
][];

Deno.test('getFloat16 BE', () => {
const dataView = new DataView(new ArrayBuffer(2));
Object.defineProperty(dataView, 'getFloat16', {
value: null,
});
for (let i = 0; i < F16.length; i++) {
dataView.setUint16(0, i, false);
assertEquals(getFloat16(dataView, 0, false), F16[i]);
}
});

Deno.test('getFloat16 LE', () => {
const dataView = new DataView(new ArrayBuffer(2));
Object.defineProperty(dataView, 'getFloat16', {
value: null,
});
for (let i = 0; i < F16.length; i++) {
dataView.setUint16(0, i, true);
assertEquals(getFloat16(dataView, 0, true), F16[i]);
}
});

Deno.test('setFloat16 BE', () => {
const dataView = new DataView(new ArrayBuffer(2));
Object.defineProperty(dataView, 'setFloat16', {
value: null,
});
for (let i = 0; i < F16.length; i++) {
setFloat16(dataView, 0, F16[i], false);
assertEquals(getFloat16(dataView, 0, false), F16[i]);
setFloat16(dataView, 0, F16[i] + Number.EPSILON, false);
assertEquals(getFloat16(dataView, 0, false), F16[i]);
setFloat16(dataView, 0, F16[i] - Number.EPSILON, false);
assertEquals(getFloat16(dataView, 0, false), F16[i]);
}
for (const [f64, i16] of F64I16) {
setFloat16(dataView, 0, f64, false);
assertEquals(dataView.getUint16(0, false), i16);
}
});

Deno.test('setFloat16 LE', () => {
const dataView = new DataView(new ArrayBuffer(2));
Object.defineProperty(dataView, 'setFloat16', {
value: null,
});
for (let i = 0; i < F16.length; i++) {
setFloat16(dataView, 0, F16[i], true);
assertEquals(getFloat16(dataView, 0, true), F16[i]);
setFloat16(dataView, 0, F16[i] + Number.EPSILON, true);
assertEquals(getFloat16(dataView, 0, true), F16[i]);
setFloat16(dataView, 0, F16[i] - Number.EPSILON, true);
assertEquals(getFloat16(dataView, 0, true), F16[i]);
}
for (const [f64, i16] of F64I16) {
setFloat16(dataView, 0, f64, true);
assertEquals(dataView.getUint16(0, true), i16);
}
});
67 changes: 67 additions & 0 deletions f16.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
let b;

/**
* Get 16-bit float.
*
* @param dataView Data view.
* @param byteOffset Byte offset.
* @param littleEndian Little endian.
* @returns Float value.
*/
export function getFloat16(
dataView: DataView,
offset: number,
littleEndian = false,
): number {
let m = dataView.getUint16(offset, littleEndian);
const s = m >> 8;
let e = s & 127;
m = (e & 3) * 256 + (m & 255);
if ((e >>= 2) === 31) {
m = m ? NaN : Infinity;
} else {
if (e) {
m += 1024;
e--;
}
m *= Math.pow(2, e - 24);
}
return (s >> 7) ? -m : m;
}

/**
* Set 16-bit float.
*
* @param dataView Data view.
* @param byteOffset Byte offset.
* @param value Float value.
* @param littleEndian Little endian.
*/
export function setFloat16(
dataView: DataView,
offset: number,
value: number,
littleEndian = false,
): void {
b ??= new DataView(new ArrayBuffer(4));
b.setFloat32(0, value);
let f = b.getUint32(0);
let v = f & 0x80000000;
f ^= v;
v >>= 16;
if (f >= 0x47800000) {
v |= 0x7c00 | (f > 0x7f800000 ? 512 | f >> 13 & 1023 : 0);
} else if (f >= 0x33000000) {
let e = f >> 23;
if (f >= 0x38800000) {
v |= e - 112 << 10 | f >> 13 & 1023;
v += f >> 12 & (f << 20 ? 1 : v & 1);
} else {
e = 126 - e;
f = f & 0x7fffff | 0x800000;
v |= f >> e--;
v += f >> e & (f << 32 - e ? 1 : v & 1);
}
}
dataView.setUint16(offset, v, littleEndian);
}
1 change: 1 addition & 0 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './f16.ts';
export * from './i24.ts';

0 comments on commit 0a1bd76

Please sign in to comment.