Skip to content

Commit 5289c40

Browse files
fix(binary): update precision for float/uint conversions (both ways)
- add tests
1 parent ea17e2d commit 5289c40

File tree

3 files changed

+56
-14
lines changed

3 files changed

+56
-14
lines changed

packages/binary/src/float.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { FnN, FnN2 } from "@thi.ng/api";
1+
import type { FnN, FnN2, FnN3 } from "@thi.ng/api";
22

33
const F64 = new Float64Array(1);
44
const F32 = new Float32Array(F64.buffer);
@@ -78,43 +78,45 @@ export const floatToSortableInt: FnN = (x) => {
7878
return x < 0 ? ~i | (1 << 31) : i;
7979
};
8080

81-
const clamp11: FnN = (x) => (x < -1 ? -1 : x > 1 ? 1 : x);
81+
/** @internal */
82+
const __f2u: FnN3 = (x, n, p) =>
83+
x < 0 ? (x < -1 ? n : x * n) : x > 1 ? p : x * p;
8284

8385
/**
8486
* Converts normalized float ([-1..1] range) to u8.
8587
*
8688
* @param x -
8789
*/
88-
export const f32u8: FnN = (x) => (clamp11(x) * 0x7f) & 0xff;
90+
export const f32u8: FnN = (x) => __f2u(x, 0x80, 0x7f) & 0xff;
8991

9092
/**
9193
* Converts normalized float ([-1..1] range) to u16.
9294
*
9395
* @param x -
9496
*/
95-
export const f32u16: FnN = (x) => (clamp11(x) * 0x7fff) & 0xffff;
97+
export const f32u16: FnN = (x) => __f2u(x, 0x8000, 0x7fff) & 0xffff;
9698

9799
/**
98100
* Converts normalized float ([-1..1] range) to u24.
99101
*
100102
* @param x -
101103
*/
102-
export const f32u24: FnN = (x) => (clamp11(x) * 0x7fffff) & 0xffffff;
104+
export const f32u24: FnN = (x) => __f2u(x, 0x80_0000, 0x7f_ffff) & 0xff_ffff;
103105

104106
/**
105107
* Converts normalized float ([-1..1] range) to u32.
106108
*
107109
* @param x -
108110
*/
109-
export const f32u32: FnN = (x) => (clamp11(x) * 0x7fffffff) >>> 0;
111+
export const f32u32: FnN = (x) => __f2u(x, 0x8000_0000, 0x7fff_ffff) >>> 0;
110112

111113
/**
112114
* Reverse op of {@link f32u8}.
113115
*
114116
* @param x -
115117
*/
116118
export const u8f32: FnN = (x) => (
117-
(x &= 0xff), (x | ((x >> 7) * 0xffffff00)) / 0x7f
119+
(x &= 0xff), (x | ((x >> 7) * 0xffff_ff00)) / (0x7f + (x >> 7))
118120
);
119121

120122
/**
@@ -123,7 +125,7 @@ export const u8f32: FnN = (x) => (
123125
* @param x -
124126
*/
125127
export const u16f32: FnN = (x) => (
126-
(x &= 0xffff), (x | ((x >> 15) * 0xffff0000)) / 0x7fff
128+
(x &= 0xffff), (x | ((x >> 15) * 0xffff_0000)) / (0x7fff + (x >> 15))
127129
);
128130

129131
/**
@@ -132,12 +134,12 @@ export const u16f32: FnN = (x) => (
132134
* @param x -
133135
*/
134136
export const u24f32: FnN = (x) => (
135-
(x &= 0xffffff), (x | ((x >> 23) * 0xff000000)) / 0x7fffff
137+
(x &= 0xffffff), (x | ((x >> 23) * 0xff00_0000)) / (0x7f_ffff + (x >> 23))
136138
);
137139

138140
/**
139141
* Reverse op of {@link f32u32}.
140142
*
141143
* @param x -
142144
*/
143-
export const u32f32: FnN = (x) => (x | 0) / 0x7fffffff;
145+
export const u32f32: FnN = (x) => (x | 0) / (0x7fff_ffff + (x >>> 31));

packages/binary/test/float.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { expect, test } from "bun:test";
2+
import { f32u16, f32u8, u16f32, u8f32 } from "../src/index.js";
3+
4+
const VALS8 = [
5+
[-1.2, 0x80, -1],
6+
[-1, 0x80],
7+
[-0.5, 0xc0],
8+
[0.5, 0x3f],
9+
[1, 0x7f],
10+
[1.2, 0x7f, 1],
11+
];
12+
13+
const VALS16 = [
14+
[-1.2, 0x8000, -1],
15+
[-1, 0x8000],
16+
[-0.5, 0xc000],
17+
[0.5, 0x3fff],
18+
[1, 0x7fff],
19+
[1.2, 0x7fff, 1],
20+
];
21+
22+
test("f32u8", () => {
23+
for (let [f, u] of VALS8) {
24+
expect(f32u8(f)).toBe(u);
25+
}
26+
});
27+
28+
test("u8f32", () => {
29+
for (let [f, u, f2] of VALS8) {
30+
expect(u8f32(u)).toBeCloseTo(f2 || f, 2);
31+
}
32+
});
33+
34+
test("f32u16", () => {
35+
for (let [f, u] of VALS16) {
36+
expect(f32u16(f)).toBe(u);
37+
}
38+
});
39+
40+
test("u16f32", () => {
41+
for (let [f, u, f2] of VALS16) {
42+
expect(u16f32(u)).toBeCloseTo(f2 || f, 4);
43+
}
44+
});

packages/binary/test/main.test.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)