-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0555da9
commit 533456b
Showing
4 changed files
with
157 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
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', () => { | ||
for (const poly of [true, false]) { | ||
const dataView = new DataView(new ArrayBuffer(2)); | ||
if (poly) { | ||
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', () => { | ||
for (const poly of [true, false]) { | ||
const dataView = new DataView(new ArrayBuffer(2)); | ||
if (poly) { | ||
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', () => { | ||
for (const poly of [true, false]) { | ||
const dataView = new DataView(new ArrayBuffer(2)); | ||
if (poly) { | ||
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', () => { | ||
for (const poly of [true, false]) { | ||
const dataView = new DataView(new ArrayBuffer(2)); | ||
if (poly) { | ||
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); | ||
} | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from './f16.ts'; | ||
export * from './i24.ts'; |