From d97b552420ac60cfe5ff7498afbf71ef04e3c95d Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:28 -0800 Subject: [PATCH 001/132] tests(cbrt): add tests in cbrt.test.ts --- src/cbrt.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/cbrt.test.ts diff --git a/src/cbrt.test.ts b/src/cbrt.test.ts new file mode 100644 index 0000000..6a4df7f --- /dev/null +++ b/src/cbrt.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { cbrt } from "./cbrt.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("cbrt", () => { + it("is a function", () => { + assert.strictEqual(typeof cbrt, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(cbrt.length, 1); + }); + + it("matches Math.cbrt", () => { + const native = Math.cbrt; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = cbrt(input); + assertClose(actual, expected); + } + }); +}); From f45811cbf04dbf088523495b91485b348b6afb2a Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:35 -0800 Subject: [PATCH 002/132] tests(log2): add tests in log2.test.ts --- src/log2.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/log2.test.ts diff --git a/src/log2.test.ts b/src/log2.test.ts new file mode 100644 index 0000000..e66f034 --- /dev/null +++ b/src/log2.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { log2 } from "./log2.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("log2", () => { + it("is a function", () => { + assert.strictEqual(typeof log2, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(log2.length, 1); + }); + + it("matches Math.log2", () => { + const native = Math.log2; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = log2(input); + assertClose(actual, expected); + } + }); +}); From ff64da83cd114112b987eb9d1213a304f603fb88 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:37 -0800 Subject: [PATCH 003/132] tests(log10): add tests in log10.test.ts --- src/log10.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/log10.test.ts diff --git a/src/log10.test.ts b/src/log10.test.ts new file mode 100644 index 0000000..b2d3da4 --- /dev/null +++ b/src/log10.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { log10 } from "./log10.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("log10", () => { + it("is a function", () => { + assert.strictEqual(typeof log10, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(log10.length, 1); + }); + + it("matches Math.log10", () => { + const native = Math.log10; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = log10(input); + assertClose(actual, expected); + } + }); +}); From 3a7af6f316c1cd2c54efd985b70182c18ca26d8e Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:38 -0800 Subject: [PATCH 004/132] tests(trunc): add tests in trunc.test.ts --- src/trunc.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/trunc.test.ts diff --git a/src/trunc.test.ts b/src/trunc.test.ts new file mode 100644 index 0000000..f4f37fe --- /dev/null +++ b/src/trunc.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertSameValue } from "./internal/_test_utils.ts"; +import { trunc } from "./trunc.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("trunc", () => { + it("is a function", () => { + assert.strictEqual(typeof trunc, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(trunc.length, 1); + }); + + it("matches Math.trunc", () => { + const native = Math.trunc; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = trunc(input); + assertSameValue(actual, expected); + } + }); +}); From 34563ee81bb71a5eed924938d178403efa585e33 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:39 -0800 Subject: [PATCH 005/132] tests(ceil): add tests in ceil.test.ts --- src/ceil.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/ceil.test.ts diff --git a/src/ceil.test.ts b/src/ceil.test.ts new file mode 100644 index 0000000..b42e98f --- /dev/null +++ b/src/ceil.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertSameValue } from "./internal/_test_utils.ts"; +import { ceil } from "./ceil.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("ceil", () => { + it("is a function", () => { + assert.strictEqual(typeof ceil, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(ceil.length, 1); + }); + + it("matches Math.ceil", () => { + const native = Math.ceil; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = ceil(input); + assertSameValue(actual, expected); + } + }); +}); From 90d788baf8b72b3e621f703656e8089f75c9f599 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:41 -0800 Subject: [PATCH 006/132] tests(asin): add tests in asin.test.ts --- src/asin.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/asin.test.ts diff --git a/src/asin.test.ts b/src/asin.test.ts new file mode 100644 index 0000000..90cbf2e --- /dev/null +++ b/src/asin.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { asin } from "./asin.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("asin", () => { + it("is a function", () => { + assert.strictEqual(typeof asin, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(asin.length, 1); + }); + + it("matches Math.asin", () => { + const native = Math.asin; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = asin(input); + assertClose(actual, expected); + } + }); +}); From 19dfee03a1a71ef19fb852a45c16bd3029ff945d Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:42 -0800 Subject: [PATCH 007/132] tests(random): add tests in random.test.ts --- src/random.test.ts | 109 +++++++++++++-------------------------------- 1 file changed, 32 insertions(+), 77 deletions(-) diff --git a/src/random.test.ts b/src/random.test.ts index da68352..0ba1959 100644 --- a/src/random.test.ts +++ b/src/random.test.ts @@ -1,41 +1,37 @@ -import { describe, it } from "jsr:@std/testing@1/bdd"; -import { assert, assertEquals } from "jsr:@std/assert@1"; -import { expect } from "jsr:@std/expect@1"; +import assert from "node:assert"; +import { describe, it } from "node:test"; import { MT19937, random } from "./random.ts"; +const seed = 42; + describe("random", () => { it("is a function", () => { - expect(typeof random).toBe("function"); + assert.strictEqual(typeof random, "function"); }); it("is named 'random'", () => { - expect(random.name).toBe("random"); + assert.strictEqual(random.name, "random"); }); it("has an arity of 0", () => { - expect(random.length).toBe(0); + assert.strictEqual(random.length, 0); }); - it("should return a number", () => { - expect(typeof random()).toBe("number"); + it("returns a number", () => { + assert.strictEqual(typeof random(), "number"); }); - it("should always return a number between [0, 1)", () => { - let last; - for (let i = 0; i < 100; i++) { + it("returns numbers in [0, 1)", () => { + for (let i = 0; i < 50; i++) { const value = random(); - expect(value).toBeGreaterThanOrEqual(0); - expect(value).toBeLessThan(1); - expect(!last || last !== value, `${i}. ${value} should be !== ${last}`) - .toBe(true); - last = value; + assert.ok(value >= 0 && value < 1); } }); - it("should support seeding", () => { - expect(typeof random.init).toBe("function"); - random.init(42); - expect(random()).toBe(0.37454011430963874); + it("supports seeding", () => { + assert.strictEqual(typeof random.init, "function"); + random.init(seed); + assert.strictEqual(random(), 0.37454011430963874); }); }); @@ -43,85 +39,44 @@ describe("MT19937", () => { const mt19937 = new MT19937(); it("is an object-like value", () => { - assert( - mt19937 != null && typeof mt19937 === "object" || - typeof mt19937 === "function", + assert.ok( + mt19937 != null && + (typeof mt19937 === "object" || typeof mt19937 === "function"), ); }); + it("has a method named random", () => { - assert(mt19937.random != null && typeof mt19937.random === "function"); + assert.ok(mt19937.random != null && typeof mt19937.random === "function"); }); + it("has a method named init", () => { - assert(mt19937.init != null && typeof mt19937.init === "function"); + assert.ok(mt19937.init != null && typeof mt19937.init === "function"); }); + it("has a method named randomInt", () => { - assert( + assert.ok( mt19937.randomInt != null && typeof mt19937.randomInt === "function", ); }); - it("generates a random number on [0, 1)-real-interval", () => { + + it("generates a number in [0, 1)", () => { const result = mt19937.random(); - assert(result >= 0 && result < 1); + assert.ok(result >= 0 && result < 1); }); - it("produces the same sequence given the same seed", () => { - const seed = 5489; - mt19937.init(seed); + + it("produces the same sequence for the same seed", () => { + mt19937.init(5489); const expected = [ 0.8147236919030547, 0.13547700410708785, 0.9057919341139495, 0.8350085897836834, 0.12698681186884642, - 0.9688677710946649, - 0.9133758556563407, - 0.22103404277004302, - 0.6323592499829829, - 0.30816705035977066, - 0.09754040162079036, - 0.5472205963451415, - 0.2784982183948159, - 0.1883819759823382, - 0.5468815190251917, - 0.9928813017904758, - 0.9575068296398968, - 0.9964613253250718, - 0.9648885338101536, - 0.967694936785847, - 0.15761307650245726, - 0.7258389631751925, - 0.9705927788745612, - 0.9811096915509552, - 0.9571669497527182, - 0.10986175062134862, - 0.4853756483644247, - 0.7981058566365391, - 0.8002804731950164, - 0.297029449371621, - 0.14188634511083364, - 0.004783484386280179, - 0.4217612857464701, - 0.11246451595798135, - 0.9157355236820877, - 0.6397633568849415, - 0.792207325110212, - 0.8784306452143937, - 0.9594924252014607, - 0.5036626774817705, - 0.6557406960055232, - 0.7979286150075495, - 0.03571167937479913, - 0.3612940013408661, - 0.849129305453971, - 0.21192433219403028, - 0.9339932457078248, - 0.6813595383428037, - 0.6787351581733674, - 0.3987385197542608, ]; const actual = Array.from( { length: expected.length }, () => mt19937.random(), ); - assertEquals(actual, expected); + assert.deepStrictEqual(actual, expected); }); }); From 42b1e644694a6e440f65030497b6ac22040890e9 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:43 -0800 Subject: [PATCH 008/132] tests(log): add tests in log.test.ts --- src/log.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/log.test.ts diff --git a/src/log.test.ts b/src/log.test.ts new file mode 100644 index 0000000..94769a4 --- /dev/null +++ b/src/log.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { log } from "./log.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("log", () => { + it("is a function", () => { + assert.strictEqual(typeof log, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(log.length, 1); + }); + + it("matches Math.log", () => { + const native = Math.log; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = log(input); + assertClose(actual, expected); + } + }); +}); From a76505964c3d97429de6107dc06aa4d1b973f38c Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:45 -0800 Subject: [PATCH 009/132] tests(float32): add tests in float32/guards.test.ts --- src/float32/guards.test.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/float32/guards.test.ts diff --git a/src/float32/guards.test.ts b/src/float32/guards.test.ts new file mode 100644 index 0000000..f8eca69 --- /dev/null +++ b/src/float32/guards.test.ts @@ -0,0 +1,34 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { isFiniteFloat32, isFloat32 } from "./guards.ts"; +import { roundFloat32 } from "./round.ts"; + +const cases = [0, -0, 1, -1, 0.1, 0.5, 3.14, 42, Infinity, -Infinity, NaN]; + +describe("isFloat32", () => { + it("is a function", () => { + assert.strictEqual(typeof isFloat32, "function"); + }); + + it("matches roundFloat32 equivalence", () => { + for (const value of cases) { + const expected = typeof value === "number" && !Number.isNaN(value) && + value === roundFloat32(value); + assert.strictEqual(isFloat32(value), expected); + } + }); +}); + +describe("isFiniteFloat32", () => { + it("is a function", () => { + assert.strictEqual(typeof isFiniteFloat32, "function"); + }); + + it("checks float32 and finiteness", () => { + for (const value of cases) { + const expected = typeof value === "number" && Number.isFinite(value) && + value === roundFloat32(value); + assert.strictEqual(isFiniteFloat32(value), expected); + } + }); +}); From cd478d8787aba2278c7180a466bb90c48a35d2eb Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:46 -0800 Subject: [PATCH 010/132] tests(float32): add tests in float32/constants.test.ts --- src/float32/constants.test.ts | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/float32/constants.test.ts diff --git a/src/float32/constants.test.ts b/src/float32/constants.test.ts new file mode 100644 index 0000000..5797b9e --- /dev/null +++ b/src/float32/constants.test.ts @@ -0,0 +1,36 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import float32, { + FLOAT32_EXPONENT_BIAS, + FLOAT32_EXPONENT_BITS, + FLOAT32_MANTISSA_BITS, + FLOAT32_NAN, + FLOAT32_NEGATIVE_INFINITY, + FLOAT32_NEGATIVE_ZERO, + FLOAT32_POSITIVE_INFINITY, + FLOAT32_POSITIVE_ZERO, +} from "./constants.ts"; + +describe("float32/constants", () => { + it("exposes expected numeric constants", () => { + assert.strictEqual(typeof FLOAT32_NAN, "number"); + assert.strictEqual(FLOAT32_POSITIVE_INFINITY, 0x7F800000); + assert.strictEqual(FLOAT32_NEGATIVE_INFINITY, 0xFF800000); + assert.strictEqual(FLOAT32_NEGATIVE_ZERO, 0x80000000); + assert.strictEqual(FLOAT32_POSITIVE_ZERO, 0x00000000); + assert.strictEqual(FLOAT32_EXPONENT_BITS, 8); + assert.strictEqual(FLOAT32_MANTISSA_BITS, 23); + assert.strictEqual(FLOAT32_EXPONENT_BIAS, 127); + }); + + it("matches default export shape", () => { + assert.strictEqual(float32.exponent, FLOAT32_EXPONENT_BITS); + assert.strictEqual(float32.mantissa, FLOAT32_MANTISSA_BITS); + assert.strictEqual(float32.bias, FLOAT32_EXPONENT_BIAS); + assert.strictEqual(float32.nan, FLOAT32_NAN); + assert.strictEqual(float32.positive_infinity, FLOAT32_POSITIVE_INFINITY); + assert.strictEqual(float32.negative_infinity, FLOAT32_NEGATIVE_INFINITY); + assert.strictEqual(float32.negative_zero, FLOAT32_NEGATIVE_ZERO); + assert.strictEqual(float32.positive_zero, FLOAT32_POSITIVE_ZERO); + }); +}); From 19b928ffc9a86ada2bdf033dd8bd23ead11e8902 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:48 -0800 Subject: [PATCH 011/132] tests(float32): add tests in float32/index.test.ts --- src/float32/index.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/float32/index.test.ts diff --git a/src/float32/index.test.ts b/src/float32/index.test.ts new file mode 100644 index 0000000..424b7ce --- /dev/null +++ b/src/float32/index.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import * as float32 from "./index.ts"; + +describe("float32/index", () => { + it("exports float32 utilities", () => { + assert.strictEqual(typeof float32.encodeFloat32, "function"); + assert.strictEqual(typeof float32.decodeFloat32, "function"); + assert.strictEqual(typeof float32.roundFloat32, "function"); + assert.strictEqual(typeof float32.isFloat32, "function"); + assert.strictEqual(typeof float32.isFiniteFloat32, "function"); + }); +}); From 51a02975ca409bd0b37159e177785cfa58663830 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:49 -0800 Subject: [PATCH 012/132] tests(float32): add tests in float32/encode.test.ts --- src/float32/encode.test.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/float32/encode.test.ts diff --git a/src/float32/encode.test.ts b/src/float32/encode.test.ts new file mode 100644 index 0000000..a09c992 --- /dev/null +++ b/src/float32/encode.test.ts @@ -0,0 +1,21 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { encodeFloat32 } from "./encode.ts"; + +const cases = [0, -0, 1, -1, 3.14, 42, Infinity, -Infinity]; + +describe("encodeFloat32", () => { + it("is a function", () => { + assert.strictEqual(typeof encodeFloat32, "function"); + }); + + it("matches DataView float32 encoding", () => { + const view = new DataView(new ArrayBuffer(4)); + for (const value of cases) { + view.setFloat32(0, value); + const expected = view.getUint32(0); + const actual = encodeFloat32(value); + assert.strictEqual(actual, expected); + } + }); +}); From 80f741f4729daa383d9e9efeda5b75369058b97d Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:50 -0800 Subject: [PATCH 013/132] tests(float32): add tests in float32/decode.test.ts --- src/float32/decode.test.ts | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/float32/decode.test.ts diff --git a/src/float32/decode.test.ts b/src/float32/decode.test.ts new file mode 100644 index 0000000..6ad391c --- /dev/null +++ b/src/float32/decode.test.ts @@ -0,0 +1,38 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { decodeFloat32 } from "./decode.ts"; + +const cases = [ + 0x00000000, + 0x80000000, + 0x3F800000, + 0xBF800000, + 0x7F800000, + 0xFF800000, + 0x40490FDB, +]; + +describe("decodeFloat32", () => { + it("is a function", () => { + assert.strictEqual(typeof decodeFloat32, "function"); + }); + + it("decodes known bit patterns", () => { + assert.strictEqual(Object.is(decodeFloat32(0x00000000), 0), true); + assert.strictEqual(Object.is(decodeFloat32(0x80000000), -0), true); + assert.strictEqual(decodeFloat32(0x3F800000), 1); + assert.strictEqual(decodeFloat32(0xBF800000), -1); + assert.strictEqual(decodeFloat32(0x7F800000), Infinity); + assert.strictEqual(decodeFloat32(0xFF800000), -Infinity); + }); + + it("matches DataView float32 decoding", () => { + const view = new DataView(new ArrayBuffer(4)); + for (const bits of cases) { + view.setUint32(0, bits); + const expected = view.getFloat32(0); + const actual = decodeFloat32(bits); + assert.strictEqual(actual, expected); + } + }); +}); From 423dd03574295e25bc50fadfa7bc53f59ab4a987 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:52 -0800 Subject: [PATCH 014/132] tests(float32): add tests in float32/round.test.ts --- src/float32/round.test.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/float32/round.test.ts diff --git a/src/float32/round.test.ts b/src/float32/round.test.ts new file mode 100644 index 0000000..f163415 --- /dev/null +++ b/src/float32/round.test.ts @@ -0,0 +1,23 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { roundFloat32 } from "./round.ts"; + +const cases = [0, -0, 1, -1, 3.14, 42, Infinity, -Infinity, NaN]; + +describe("roundFloat32", () => { + it("is a function", () => { + assert.strictEqual(typeof roundFloat32, "function"); + }); + + it("matches Math.fround", () => { + for (const value of cases) { + const expected = Math.fround(value); + const actual = roundFloat32(value); + if (Number.isNaN(expected)) { + assert.ok(Number.isNaN(actual)); + } else { + assert.strictEqual(actual, expected); + } + } + }); +}); From 3835bfce1d8fe40750c6542328cac9a2c89347c7 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:53 -0800 Subject: [PATCH 015/132] tests(clamp): add tests in clamp.test.ts --- src/clamp.test.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/clamp.test.ts diff --git a/src/clamp.test.ts b/src/clamp.test.ts new file mode 100644 index 0000000..e37307b --- /dev/null +++ b/src/clamp.test.ts @@ -0,0 +1,29 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { clamp } from "./clamp.ts"; + +const cases: Array<[number, number, number]> = [ + [-1, 0, 1], + [0.5, 0, 1], + [2, 0, 1], + [10, -5, 5], + [-10, -5, 5], +]; + +describe("clamp", () => { + it("is a function", () => { + assert.strictEqual(typeof clamp, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(clamp.length, 3); + }); + + it("matches the min/max definition", () => { + for (const [value, lower, upper] of cases) { + const expected = Math.min(Math.max(value, lower), upper); + const actual = clamp(value, lower, upper); + assert.strictEqual(actual, expected); + } + }); +}); From 112661c6e971ee731ff1e99d51ceefa7d517dd39 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:54 -0800 Subject: [PATCH 016/132] tests(clz32): add tests in clz32.test.ts --- src/clz32.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/clz32.test.ts diff --git a/src/clz32.test.ts b/src/clz32.test.ts new file mode 100644 index 0000000..badbdd4 --- /dev/null +++ b/src/clz32.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertSameValue } from "./internal/_test_utils.ts"; +import { clz32 } from "./clz32.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("clz32", () => { + it("is a function", () => { + assert.strictEqual(typeof clz32, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(clz32.length, 1); + }); + + it("matches Math.clz32", () => { + const native = Math.clz32; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = clz32(input); + assertSameValue(actual, expected); + } + }); +}); From bc9441d08dfcb89f5a1c3742b54b2b38e2c0c32a Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:56 -0800 Subject: [PATCH 017/132] tests(abs): add tests in abs.test.ts --- src/abs.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/abs.test.ts diff --git a/src/abs.test.ts b/src/abs.test.ts new file mode 100644 index 0000000..ccf668a --- /dev/null +++ b/src/abs.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertSameValue } from "./internal/_test_utils.ts"; +import { abs } from "./abs.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("abs", () => { + it("is a function", () => { + assert.strictEqual(typeof abs, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(abs.length, 1); + }); + + it("matches Math.abs", () => { + const native = Math.abs; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = abs(input); + assertSameValue(actual, expected); + } + }); +}); From 95175dea633965fcd1247203eb7e9cacd0ae86ef Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:57 -0800 Subject: [PATCH 018/132] tests(constants): add tests in constants/log2e.test.ts --- src/constants/log2e.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/log2e.test.ts diff --git a/src/constants/log2e.test.ts b/src/constants/log2e.test.ts new file mode 100644 index 0000000..5c26a7d --- /dev/null +++ b/src/constants/log2e.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { LOG2E } from "./log2e.ts"; + +describe("LOG2E", () => { + it("is a number", () => { + assert.strictEqual(typeof LOG2E, "number"); + }); + + it("matches Math.LOG2E", () => { + assert.strictEqual(LOG2E, Math.LOG2E); + }); +}); From de6fff95fec26b83733abb03481a072264ef9011 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:52:59 -0800 Subject: [PATCH 019/132] tests(constants): add tests in constants/max_safe_integer.test.ts --- src/constants/max_safe_integer.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/max_safe_integer.test.ts diff --git a/src/constants/max_safe_integer.test.ts b/src/constants/max_safe_integer.test.ts new file mode 100644 index 0000000..7d0905b --- /dev/null +++ b/src/constants/max_safe_integer.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { MAX_SAFE_INTEGER } from "./max_safe_integer.ts"; + +describe("MAX_SAFE_INTEGER", () => { + it("is a number", () => { + assert.strictEqual(typeof MAX_SAFE_INTEGER, "number"); + }); + + it("matches Number.MAX_SAFE_INTEGER", () => { + assert.strictEqual(MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER); + }); +}); From 9692166c1825217f124cc6a73bcb637578c5d553 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:00 -0800 Subject: [PATCH 020/132] tests(constants): add tests in constants/ln2.test.ts --- src/constants/ln2.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/ln2.test.ts diff --git a/src/constants/ln2.test.ts b/src/constants/ln2.test.ts new file mode 100644 index 0000000..c16b4b5 --- /dev/null +++ b/src/constants/ln2.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { LN2 } from "./ln2.ts"; + +describe("LN2", () => { + it("is a number", () => { + assert.strictEqual(typeof LN2, "number"); + }); + + it("matches Math.LN2", () => { + assert.strictEqual(LN2, Math.LN2); + }); +}); From 423dbb9763a753f48228befffde60df98b55c7c3 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:01 -0800 Subject: [PATCH 021/132] tests(constants): add tests in constants/log10e.test.ts --- src/constants/log10e.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/log10e.test.ts diff --git a/src/constants/log10e.test.ts b/src/constants/log10e.test.ts new file mode 100644 index 0000000..1a0a71f --- /dev/null +++ b/src/constants/log10e.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { LOG10E } from "./log10e.ts"; + +describe("LOG10E", () => { + it("is a number", () => { + assert.strictEqual(typeof LOG10E, "number"); + }); + + it("matches Math.LOG10E", () => { + assert.strictEqual(LOG10E, Math.LOG10E); + }); +}); From b1788d59ad22429b1bc0bf7b234384f31c4ec253 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:03 -0800 Subject: [PATCH 022/132] tests(constants): add tests in constants/positive_zero.test.ts --- src/constants/positive_zero.test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/constants/positive_zero.test.ts diff --git a/src/constants/positive_zero.test.ts b/src/constants/positive_zero.test.ts new file mode 100644 index 0000000..f5689af --- /dev/null +++ b/src/constants/positive_zero.test.ts @@ -0,0 +1,14 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { POSITIVE_ZERO } from "./positive_zero.ts"; + +describe("POSITIVE_ZERO", () => { + it("is +0", () => { + assert.strictEqual(typeof POSITIVE_ZERO, "number"); + assert.ok(Object.is(POSITIVE_ZERO, 0)); + }); + + it("is not -0", () => { + assert.ok(!Object.is(POSITIVE_ZERO, -0)); + }); +}); From 9fe6267c55cae20915b6e0bcf793f7cd556abd3d Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:04 -0800 Subject: [PATCH 023/132] tests(constants): add tests in constants/epsilon.test.ts --- src/constants/epsilon.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/epsilon.test.ts diff --git a/src/constants/epsilon.test.ts b/src/constants/epsilon.test.ts new file mode 100644 index 0000000..88d274c --- /dev/null +++ b/src/constants/epsilon.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { EPSILON } from "./epsilon.ts"; + +describe("EPSILON", () => { + it("is a number", () => { + assert.strictEqual(typeof EPSILON, "number"); + }); + + it("matches Number.EPSILON", () => { + assert.strictEqual(EPSILON, Number.EPSILON); + }); +}); From 70429d57bc9af0e5d1c2c2ee8dc80e123f536da8 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:05 -0800 Subject: [PATCH 024/132] tests(constants): add tests in constants/negative_zero.test.ts --- src/constants/negative_zero.test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/constants/negative_zero.test.ts diff --git a/src/constants/negative_zero.test.ts b/src/constants/negative_zero.test.ts new file mode 100644 index 0000000..1a15721 --- /dev/null +++ b/src/constants/negative_zero.test.ts @@ -0,0 +1,14 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { NEGATIVE_ZERO } from "./negative_zero.ts"; + +describe("NEGATIVE_ZERO", () => { + it("is -0", () => { + assert.strictEqual(typeof NEGATIVE_ZERO, "number"); + assert.ok(Object.is(NEGATIVE_ZERO, -0)); + }); + + it("is not +0", () => { + assert.ok(!Object.is(NEGATIVE_ZERO, 0)); + }); +}); From e7ba4f8626b2e894606474f28ed062f8b7e2d48e Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:07 -0800 Subject: [PATCH 025/132] tests(constants): add tests in constants/index.test.ts --- src/constants/index.test.ts | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/constants/index.test.ts diff --git a/src/constants/index.test.ts b/src/constants/index.test.ts new file mode 100644 index 0000000..541f600 --- /dev/null +++ b/src/constants/index.test.ts @@ -0,0 +1,44 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import * as constants from "./index.ts"; + +const mathKeys = [ + "E", + "LN2", + "LN10", + "LOG2E", + "LOG10E", + "PI", + "SQRT1_2", + "SQRT2", +] as const; + +const numberKeys = [ + "EPSILON", + "MAX_SAFE_INTEGER", + "MIN_SAFE_INTEGER", + "MAX_VALUE", + "MIN_VALUE", + "POSITIVE_INFINITY", + "NEGATIVE_INFINITY", +] as const; + +describe("constants/index", () => { + it("exposes Math constants", () => { + for (const key of mathKeys) { + assert.strictEqual(constants[key], Math[key]); + } + }); + + it("exposes Number constants", () => { + for (const key of numberKeys) { + assert.strictEqual(constants[key], Number[key]); + } + }); + + it("exposes NaN and zeros", () => { + assert.ok(Number.isNaN(constants.NAN)); + assert.ok(Object.is(constants.POSITIVE_ZERO, 0)); + assert.ok(Object.is(constants.NEGATIVE_ZERO, -0)); + }); +}); From 0a86f5afa94f6885cabd26aefb458f48bff627f3 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:08 -0800 Subject: [PATCH 026/132] tests(constants): add tests in constants/nan.test.ts --- src/constants/nan.test.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/constants/nan.test.ts diff --git a/src/constants/nan.test.ts b/src/constants/nan.test.ts new file mode 100644 index 0000000..93604a8 --- /dev/null +++ b/src/constants/nan.test.ts @@ -0,0 +1,18 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { NAN, NaN as NaNValue } from "./nan.ts"; + +describe("NAN", () => { + it("is a number", () => { + assert.strictEqual(typeof NAN, "number"); + }); + + it("matches Number.NaN", () => { + assert.ok(Number.isNaN(NAN)); + assert.ok(Number.isNaN(Number.NaN)); + }); + + it("exports NaN alias", () => { + assert.ok(Number.isNaN(NaNValue)); + }); +}); From 702b8ce4405f7f7323c8b41ab73da7d9674d8413 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:10 -0800 Subject: [PATCH 027/132] tests(constants): add tests in constants/sqrt1_2.test.ts --- src/constants/sqrt1_2.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/sqrt1_2.test.ts diff --git a/src/constants/sqrt1_2.test.ts b/src/constants/sqrt1_2.test.ts new file mode 100644 index 0000000..359967d --- /dev/null +++ b/src/constants/sqrt1_2.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { SQRT1_2 } from "./sqrt1_2.ts"; + +describe("SQRT1_2", () => { + it("is a number", () => { + assert.strictEqual(typeof SQRT1_2, "number"); + }); + + it("matches Math.SQRT1_2", () => { + assert.strictEqual(SQRT1_2, Math.SQRT1_2); + }); +}); From 1d2874a6074f876cc2110378ff6a8ac1c87f5f40 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:11 -0800 Subject: [PATCH 028/132] tests(constants): add tests in constants/ln10.test.ts --- src/constants/ln10.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/ln10.test.ts diff --git a/src/constants/ln10.test.ts b/src/constants/ln10.test.ts new file mode 100644 index 0000000..c3afc1d --- /dev/null +++ b/src/constants/ln10.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { LN10 } from "./ln10.ts"; + +describe("LN10", () => { + it("is a number", () => { + assert.strictEqual(typeof LN10, "number"); + }); + + it("matches Math.LN10", () => { + assert.strictEqual(LN10, Math.LN10); + }); +}); From de73d8fabba143078952044917004104f1829cce Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:12 -0800 Subject: [PATCH 029/132] tests(constants): add tests in constants/positive_infinity.test.ts --- src/constants/positive_infinity.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/positive_infinity.test.ts diff --git a/src/constants/positive_infinity.test.ts b/src/constants/positive_infinity.test.ts new file mode 100644 index 0000000..7ce6cdf --- /dev/null +++ b/src/constants/positive_infinity.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { POSITIVE_INFINITY } from "./positive_infinity.ts"; + +describe("POSITIVE_INFINITY", () => { + it("is a number", () => { + assert.strictEqual(typeof POSITIVE_INFINITY, "number"); + }); + + it("matches Number.POSITIVE_INFINITY", () => { + assert.strictEqual(POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + }); +}); From 30e0ce6e39f61d25918e5022a2bfd07bb65527eb Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:14 -0800 Subject: [PATCH 030/132] tests(constants): add tests in constants/min_safe_integer.test.ts --- src/constants/min_safe_integer.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/min_safe_integer.test.ts diff --git a/src/constants/min_safe_integer.test.ts b/src/constants/min_safe_integer.test.ts new file mode 100644 index 0000000..b1eb40c --- /dev/null +++ b/src/constants/min_safe_integer.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { MIN_SAFE_INTEGER } from "./min_safe_integer.ts"; + +describe("MIN_SAFE_INTEGER", () => { + it("is a number", () => { + assert.strictEqual(typeof MIN_SAFE_INTEGER, "number"); + }); + + it("matches Number.MIN_SAFE_INTEGER", () => { + assert.strictEqual(MIN_SAFE_INTEGER, Number.MIN_SAFE_INTEGER); + }); +}); From b25afdb8e62e380b38ba4811315481b0e3699833 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:15 -0800 Subject: [PATCH 031/132] tests(constants): add tests in constants/e.test.ts --- src/constants/e.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/e.test.ts diff --git a/src/constants/e.test.ts b/src/constants/e.test.ts new file mode 100644 index 0000000..bacce9e --- /dev/null +++ b/src/constants/e.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { E } from "./e.ts"; + +describe("E", () => { + it("is a number", () => { + assert.strictEqual(typeof E, "number"); + }); + + it("matches Math.E", () => { + assert.strictEqual(E, Math.E); + }); +}); From 2f1ec352dcf835841f6521cbaec408607ac6b04e Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:16 -0800 Subject: [PATCH 032/132] tests(constants): add tests in constants/max_value.test.ts --- src/constants/max_value.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/max_value.test.ts diff --git a/src/constants/max_value.test.ts b/src/constants/max_value.test.ts new file mode 100644 index 0000000..c092cc0 --- /dev/null +++ b/src/constants/max_value.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { MAX_VALUE } from "./max_value.ts"; + +describe("MAX_VALUE", () => { + it("is a number", () => { + assert.strictEqual(typeof MAX_VALUE, "number"); + }); + + it("matches Number.MAX_VALUE", () => { + assert.strictEqual(MAX_VALUE, Number.MAX_VALUE); + }); +}); From 671ee01aba7e25ae39e20e6a5d679a5ceb1837a2 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:18 -0800 Subject: [PATCH 033/132] tests(constants): add tests in constants/negative_infinity.test.ts --- src/constants/negative_infinity.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/negative_infinity.test.ts diff --git a/src/constants/negative_infinity.test.ts b/src/constants/negative_infinity.test.ts new file mode 100644 index 0000000..8e23b04 --- /dev/null +++ b/src/constants/negative_infinity.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { NEGATIVE_INFINITY } from "./negative_infinity.ts"; + +describe("NEGATIVE_INFINITY", () => { + it("is a number", () => { + assert.strictEqual(typeof NEGATIVE_INFINITY, "number"); + }); + + it("matches Number.NEGATIVE_INFINITY", () => { + assert.strictEqual(NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); + }); +}); From aa78c31dd5c171c8116d7e99e0c344e0feffa040 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:19 -0800 Subject: [PATCH 034/132] tests(constants): add tests in constants/pi.test.ts --- src/constants/pi.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/pi.test.ts diff --git a/src/constants/pi.test.ts b/src/constants/pi.test.ts new file mode 100644 index 0000000..722de99 --- /dev/null +++ b/src/constants/pi.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { PI } from "./pi.ts"; + +describe("PI", () => { + it("is a number", () => { + assert.strictEqual(typeof PI, "number"); + }); + + it("matches Math.PI", () => { + assert.strictEqual(PI, Math.PI); + }); +}); From e59164b71209bc864907a064f7182033ec30424f Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:21 -0800 Subject: [PATCH 035/132] tests(constants): add tests in constants/sqrt2.test.ts --- src/constants/sqrt2.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/sqrt2.test.ts diff --git a/src/constants/sqrt2.test.ts b/src/constants/sqrt2.test.ts new file mode 100644 index 0000000..3ee5fe9 --- /dev/null +++ b/src/constants/sqrt2.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { SQRT2 } from "./sqrt2.ts"; + +describe("SQRT2", () => { + it("is a number", () => { + assert.strictEqual(typeof SQRT2, "number"); + }); + + it("matches Math.SQRT2", () => { + assert.strictEqual(SQRT2, Math.SQRT2); + }); +}); From 6339b2d2e604baf25662f4bab5e322ec2a203a09 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:22 -0800 Subject: [PATCH 036/132] tests(constants): add tests in constants/infinity.test.ts --- src/constants/infinity.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/constants/infinity.test.ts diff --git a/src/constants/infinity.test.ts b/src/constants/infinity.test.ts new file mode 100644 index 0000000..5922ebe --- /dev/null +++ b/src/constants/infinity.test.ts @@ -0,0 +1,10 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { NEGATIVE_INFINITY, POSITIVE_INFINITY } from "./infinity.ts"; + +describe("constants/infinity", () => { + it("exports positive and negative infinity", () => { + assert.strictEqual(POSITIVE_INFINITY, Number.POSITIVE_INFINITY); + assert.strictEqual(NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); + }); +}); From 057b0ac0ec15e1383896e7fb6010a286ee4d880b Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:23 -0800 Subject: [PATCH 037/132] tests(constants): add tests in constants/min_value.test.ts --- src/constants/min_value.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/constants/min_value.test.ts diff --git a/src/constants/min_value.test.ts b/src/constants/min_value.test.ts new file mode 100644 index 0000000..56dd8f1 --- /dev/null +++ b/src/constants/min_value.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { MIN_VALUE } from "./min_value.ts"; + +describe("MIN_VALUE", () => { + it("is a number", () => { + assert.strictEqual(typeof MIN_VALUE, "number"); + }); + + it("matches Number.MIN_VALUE", () => { + assert.strictEqual(MIN_VALUE, Number.MIN_VALUE); + }); +}); From c4eabadadfb259ba70be7941370fa1e9de6ff107 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:25 -0800 Subject: [PATCH 038/132] tests(expm1): add tests in expm1.test.ts --- src/expm1.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/expm1.test.ts diff --git a/src/expm1.test.ts b/src/expm1.test.ts new file mode 100644 index 0000000..96e6d93 --- /dev/null +++ b/src/expm1.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { expm1 } from "./expm1.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("expm1", () => { + it("is a function", () => { + assert.strictEqual(typeof expm1, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(expm1.length, 1); + }); + + it("matches Math.expm1", () => { + const native = Math.expm1; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = expm1(input); + assertClose(actual, expected); + } + }); +}); From 88c15b5cf9fb8b59bb7a8eb60339cc607c0714ff Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:26 -0800 Subject: [PATCH 039/132] tests(sin): add tests in sin.test.ts --- src/sin.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/sin.test.ts diff --git a/src/sin.test.ts b/src/sin.test.ts new file mode 100644 index 0000000..c80405e --- /dev/null +++ b/src/sin.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { sin } from "./sin.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("sin", () => { + it("is a function", () => { + assert.strictEqual(typeof sin, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(sin.length, 1); + }); + + it("matches Math.sin", () => { + const native = Math.sin; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = sin(input); + assertClose(actual, expected); + } + }); +}); From 3227628f5b68e52475e973955f870d5712f70ebf Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:27 -0800 Subject: [PATCH 040/132] tests(constants): add tests in constants.test.ts --- src/constants.test.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/constants.test.ts b/src/constants.test.ts index 086b8c4..48cf8db 100644 --- a/src/constants.test.ts +++ b/src/constants.test.ts @@ -1,6 +1,7 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; import * as constants from "./constants/index.ts"; -import { describe, it } from "jsr:@std/testing@1/bdd"; -import { expect } from "jsr:@std/expect@1"; +import { assertSameValue } from "./internal/_test_utils.ts"; const cases = { Math: [ @@ -33,7 +34,8 @@ for (const kind of Object.keys(cases) as (keyof typeof cases)[]) { const parent = globalThis[kind]; const expected = parent[key as keyof typeof parent]; it(`is equal to ${kind}.${key}`, () => { - expect(value).toBe(expected); + assert.strictEqual(typeof value, "number"); + assertSameValue(value, expected as number); }); }); } From 2afde59bfc63330c617a2c9c149051890af68ae7 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:29 -0800 Subject: [PATCH 041/132] tests(atan): add tests in atan.test.ts --- src/atan.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/atan.test.ts diff --git a/src/atan.test.ts b/src/atan.test.ts new file mode 100644 index 0000000..208073b --- /dev/null +++ b/src/atan.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { atan } from "./atan.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("atan", () => { + it("is a function", () => { + assert.strictEqual(typeof atan, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(atan.length, 1); + }); + + it("matches Math.atan", () => { + const native = Math.atan; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = atan(input); + assertClose(actual, expected); + } + }); +}); From c1ad7eca1b400f3d86fd1282512d68e144a240a5 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:30 -0800 Subject: [PATCH 042/132] tests(max): add tests in max.test.ts --- src/max.test.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/max.test.ts diff --git a/src/max.test.ts b/src/max.test.ts new file mode 100644 index 0000000..08a6de8 --- /dev/null +++ b/src/max.test.ts @@ -0,0 +1,33 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertSameValue } from "./internal/_test_utils.ts"; +import { max } from "./max.ts"; + +const cases: Array = [ + [1, 2, 3], + [-10, -5, -1], + [1, -1, 0], + [NaN, 1, 2], + [0.0, -0], + [Infinity, 1], + [], +]; + +describe("max", () => { + it("is a function", () => { + assert.strictEqual(typeof max, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(max.length, 0); + }); + + it("matches Math.max", () => { + const native = Math.max; + for (const args of cases) { + const expected = native(...args); + const actual = max(...args); + assertSameValue(actual, expected); + } + }); +}); From 414c0820c373e779ffe41f4789abb5cdf69c1fc6 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:31 -0800 Subject: [PATCH 043/132] tests(asinh): add tests in asinh.test.ts --- src/asinh.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/asinh.test.ts diff --git a/src/asinh.test.ts b/src/asinh.test.ts new file mode 100644 index 0000000..7253df6 --- /dev/null +++ b/src/asinh.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { asinh } from "./asinh.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("asinh", () => { + it("is a function", () => { + assert.strictEqual(typeof asinh, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(asinh.length, 1); + }); + + it("matches Math.asinh", () => { + const native = Math.asinh; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = asinh(input); + assertClose(actual, expected); + } + }); +}); From 26059420920b755fea18d4a8770139e56480761f Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:33 -0800 Subject: [PATCH 044/132] tests(sinh): add tests in sinh.test.ts --- src/sinh.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/sinh.test.ts diff --git a/src/sinh.test.ts b/src/sinh.test.ts new file mode 100644 index 0000000..4275a5e --- /dev/null +++ b/src/sinh.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { sinh } from "./sinh.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("sinh", () => { + it("is a function", () => { + assert.strictEqual(typeof sinh, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(sinh.length, 1); + }); + + it("matches Math.sinh", () => { + const native = Math.sinh; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = sinh(input); + assertClose(actual, expected); + } + }); +}); From 4c194487d5efcc18bbbd2191d651c69720e0e3d6 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:34 -0800 Subject: [PATCH 045/132] tests(index): add tests in index.test.ts --- src/index.test.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/index.test.ts diff --git a/src/index.test.ts b/src/index.test.ts new file mode 100644 index 0000000..320fda7 --- /dev/null +++ b/src/index.test.ts @@ -0,0 +1,24 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import * as math from "./index.ts"; +import mathDefault from "./index.ts"; +import { assertClose, assertSameValue } from "./internal/_test_utils.ts"; + +describe("index", () => { + it("exports a default namespace", () => { + assert.ok(mathDefault != null && typeof mathDefault === "object"); + assert.strictEqual(mathDefault.abs, math.abs); + }); + + it("exposes core constants", () => { + assertSameValue(math.PI, Math.PI); + assertSameValue(math.E, Math.E); + assertSameValue(math.EPSILON, Number.EPSILON); + }); + + it("matches native Math for sample functions", () => { + assertSameValue(math.abs(-2), Math.abs(-2)); + assertClose(math.sin(Math.PI / 3), Math.sin(Math.PI / 3)); + assertClose(math.log(2), Math.log(2)); + }); +}); From 691a3dc738316ef3c0232f5120da109268a63b7d Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:36 -0800 Subject: [PATCH 046/132] tests(acos): add tests in acos.test.ts --- src/acos.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/acos.test.ts diff --git a/src/acos.test.ts b/src/acos.test.ts new file mode 100644 index 0000000..8fc681c --- /dev/null +++ b/src/acos.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { acos } from "./acos.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("acos", () => { + it("is a function", () => { + assert.strictEqual(typeof acos, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(acos.length, 1); + }); + + it("matches Math.acos", () => { + const native = Math.acos; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = acos(input); + assertClose(actual, expected); + } + }); +}); From cf10a1c5b44282fb047a316c31ced216272279e0 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:37 -0800 Subject: [PATCH 047/132] tests(atan2): add tests in atan2.test.ts --- src/atan2.test.ts | 60 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/atan2.test.ts diff --git a/src/atan2.test.ts b/src/atan2.test.ts new file mode 100644 index 0000000..12980ed --- /dev/null +++ b/src/atan2.test.ts @@ -0,0 +1,60 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose, assertSameValue } from "./internal/_test_utils.ts"; +import { atan2 } from "./atan2.ts"; +import { PI } from "./constants/pi.ts"; +import { isNegativeZero } from "./guards/negative_zero.ts"; + +const PI_OVER_2 = PI / 2, PI_OVER_4 = PI / 4; + +const cases: [inputs: [number, number], output: number][] = [ + [[0, 1], 0], + [[0, 0], 0], + [[-0, 0], -0], + [[0, -0], PI], + [[-0, -0], -PI], + [[1, 0], PI_OVER_2], + [[-1, -1], -3 * PI_OVER_4], + [[0, -1], PI], + [[-0, -1], -PI], + [[1, -0], PI_OVER_2], + [[NaN, 1], NaN], + [[Infinity, 0], PI_OVER_2], + [[-Infinity, 0], -PI_OVER_2], + [[0, Infinity], 0], + [[-0, Infinity], -0], + [[-0, -Infinity], -PI], + [[0, -Infinity], PI], + [[Infinity, Infinity], PI_OVER_4], + [[-Infinity, Infinity], -PI_OVER_4], + [[Infinity, -Infinity], 3 * PI_OVER_4], + [[-Infinity, -Infinity], -3 * PI_OVER_4], + [[-1, -Infinity], -PI], + [[1, -Infinity], PI], +]; + +describe("atan2", () => { + it("is a function", () => { + assert.strictEqual(typeof atan2, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(atan2.length, 2); + }); + + it("matches Math.atan2", () => { + const native = Math.atan2; + for (const [args, expected] of cases) { + const actual_res = atan2(...args); + assertSameValue( + actual_res, + expected, + `Expected atan2(${args}) === ${ + isNegativeZero(expected) ? "-0" : expected + }. Received: ${actual_res}`, + ); + const native_res = native(...args); + assertClose(actual_res, native_res); + } + }); +}); From 7fa57d285e2a2bde8a56d7ef36f0631ffd10c124 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:38 -0800 Subject: [PATCH 048/132] tests(guards): add tests in guards/positive_zero.test.ts --- src/guards/positive_zero.test.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/guards/positive_zero.test.ts diff --git a/src/guards/positive_zero.test.ts b/src/guards/positive_zero.test.ts new file mode 100644 index 0000000..0a5396d --- /dev/null +++ b/src/guards/positive_zero.test.ts @@ -0,0 +1,18 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { isPositiveZero } from "./positive_zero.ts"; + +const cases = [0, -0, 1, -1, NaN, Infinity, -Infinity]; + +describe("isPositiveZero", () => { + it("is a function", () => { + assert.strictEqual(typeof isPositiveZero, "function"); + }); + + it("matches Object.is(x, 0) and not -0", () => { + for (const value of cases) { + const expected = Object.is(value, 0) && !Object.is(value, -0); + assert.strictEqual(isPositiveZero(value), expected); + } + }); +}); From 8414cdb0a5920af8194de9ecf6e8f309e6f49efd Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:40 -0800 Subject: [PATCH 049/132] tests(guards): add tests in guards/safe_integer.test.ts --- src/guards/safe_integer.test.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/guards/safe_integer.test.ts diff --git a/src/guards/safe_integer.test.ts b/src/guards/safe_integer.test.ts new file mode 100644 index 0000000..75179f6 --- /dev/null +++ b/src/guards/safe_integer.test.ts @@ -0,0 +1,28 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { isSafeInteger } from "./safe_integer.ts"; + +const cases = [ + 0, + 1, + -1, + Number.MAX_SAFE_INTEGER, + Number.MIN_SAFE_INTEGER, + Number.MAX_SAFE_INTEGER + 1, + Number.MIN_SAFE_INTEGER - 1, + 1.5, + NaN, + Infinity, +]; + +describe("isSafeInteger", () => { + it("is a function", () => { + assert.strictEqual(typeof isSafeInteger, "function"); + }); + + it("matches Number.isSafeInteger", () => { + for (const value of cases) { + assert.strictEqual(isSafeInteger(value), Number.isSafeInteger(value)); + } + }); +}); From 03ce7aa6986254469a54796cd2d5daafc4eae211 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:41 -0800 Subject: [PATCH 050/132] tests(guards): add tests in guards/negative_zero.test.ts --- src/guards/negative_zero.test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/guards/negative_zero.test.ts diff --git a/src/guards/negative_zero.test.ts b/src/guards/negative_zero.test.ts new file mode 100644 index 0000000..8a0df28 --- /dev/null +++ b/src/guards/negative_zero.test.ts @@ -0,0 +1,17 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { isNegativeZero } from "./negative_zero.ts"; + +const cases = [0, -0, 1, -1, NaN, Infinity, -Infinity]; + +describe("isNegativeZero", () => { + it("is a function", () => { + assert.strictEqual(typeof isNegativeZero, "function"); + }); + + it("matches Object.is(x, -0)", () => { + for (const value of cases) { + assert.strictEqual(isNegativeZero(value), Object.is(value, -0)); + } + }); +}); From c4b51a1c0016ca2dcb12b8e6f33ddc636746ba9b Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:42 -0800 Subject: [PATCH 051/132] tests(guards): add tests in guards/index.test.ts --- src/guards/index.test.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/guards/index.test.ts diff --git a/src/guards/index.test.ts b/src/guards/index.test.ts new file mode 100644 index 0000000..d52bd17 --- /dev/null +++ b/src/guards/index.test.ts @@ -0,0 +1,18 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import * as guards from "./index.ts"; + +describe("guards/index", () => { + it("exposes guard functions", () => { + assert.strictEqual(typeof guards.isFinite, "function"); + assert.strictEqual(typeof guards.isNaN, "function"); + assert.strictEqual(typeof guards.isInteger, "function"); + assert.strictEqual(typeof guards.isSafeInteger, "function"); + }); + + it("matches native counterparts for sample values", () => { + assert.strictEqual(guards.isFinite(1), Number.isFinite(1)); + assert.strictEqual(guards.isSafeInteger(10), Number.isSafeInteger(10)); + assert.strictEqual(guards.isNumberInteger(10), Number.isInteger(10)); + }); +}); From 96d9254afcdf7047832beee13276dc8b8e833aba Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:44 -0800 Subject: [PATCH 052/132] tests(guards): add tests in guards/nan.test.ts --- src/guards/nan.test.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/guards/nan.test.ts diff --git a/src/guards/nan.test.ts b/src/guards/nan.test.ts new file mode 100644 index 0000000..a5a8b3d --- /dev/null +++ b/src/guards/nan.test.ts @@ -0,0 +1,27 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { isNaN, NAN, NaN as NaNValue } from "./nan.ts"; + +const cases: unknown[] = [0, 1, NaN, "foo", "42", null, undefined]; + +describe("isNaN", () => { + it("is a function", () => { + assert.strictEqual(typeof isNaN, "function"); + }); + + it("matches global isNaN", () => { + for (const value of cases) { + assert.strictEqual( + isNaN(value as number), + globalThis.isNaN(value as number), + ); + } + }); +}); + +describe("NAN", () => { + it("is NaN", () => { + assert.ok(Number.isNaN(NAN)); + assert.ok(Number.isNaN(NaNValue)); + }); +}); From a32c1bb79013d152cf1de811a30c6bae564e0ea1 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:45 -0800 Subject: [PATCH 053/132] tests(guards): add tests in guards/integer.test.ts --- src/guards/integer.test.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/guards/integer.test.ts diff --git a/src/guards/integer.test.ts b/src/guards/integer.test.ts new file mode 100644 index 0000000..6140796 --- /dev/null +++ b/src/guards/integer.test.ts @@ -0,0 +1,31 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { isInteger, isNumberInteger } from "./integer.ts"; + +const cases: unknown[] = [0, 1, -1, 1.2, -2.5, NaN, Infinity, -Infinity, "3"]; + +describe("isInteger", () => { + it("is a function", () => { + assert.strictEqual(typeof isInteger, "function"); + }); + + it("coerces and matches Number.isInteger", () => { + for (const value of cases) { + const expected = Number.isInteger(+value); + assert.strictEqual(isInteger(value as number), expected); + } + }); +}); + +describe("isNumberInteger", () => { + it("is a function", () => { + assert.strictEqual(typeof isNumberInteger, "function"); + }); + + it("matches Number.isInteger for numbers", () => { + const numericCases = [0, 1, -1, 1.2, -2.5, NaN, Infinity, -Infinity]; + for (const value of numericCases) { + assert.strictEqual(isNumberInteger(value), Number.isInteger(value)); + } + }); +}); From bea4c5c4c80f58580d2aa7857751b8f32f5818b1 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:47 -0800 Subject: [PATCH 054/132] tests(guards): add tests in guards/positive_infinity.test.ts --- src/guards/positive_infinity.test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/guards/positive_infinity.test.ts diff --git a/src/guards/positive_infinity.test.ts b/src/guards/positive_infinity.test.ts new file mode 100644 index 0000000..2e85245 --- /dev/null +++ b/src/guards/positive_infinity.test.ts @@ -0,0 +1,17 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { isPositiveInfinity } from "./positive_infinity.ts"; + +const cases = [0, 1, -1, Infinity, -Infinity, NaN]; + +describe("isPositiveInfinity", () => { + it("is a function", () => { + assert.strictEqual(typeof isPositiveInfinity, "function"); + }); + + it("identifies +Infinity", () => { + for (const value of cases) { + assert.strictEqual(isPositiveInfinity(value), value === Infinity); + } + }); +}); From f4c48d91f0c0a23b62a7e3a1bb55ac44d7b75c1c Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:48 -0800 Subject: [PATCH 055/132] tests(guards): add tests in guards/negative_infinity.test.ts --- src/guards/negative_infinity.test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/guards/negative_infinity.test.ts diff --git a/src/guards/negative_infinity.test.ts b/src/guards/negative_infinity.test.ts new file mode 100644 index 0000000..dd83d0d --- /dev/null +++ b/src/guards/negative_infinity.test.ts @@ -0,0 +1,17 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { isNegativeInfinity } from "./negative_infinity.ts"; + +const cases = [0, 1, -1, Infinity, -Infinity, NaN]; + +describe("isNegativeInfinity", () => { + it("is a function", () => { + assert.strictEqual(typeof isNegativeInfinity, "function"); + }); + + it("identifies -Infinity", () => { + for (const value of cases) { + assert.strictEqual(isNegativeInfinity(value), value === -Infinity); + } + }); +}); From d8ad953f20f8869dc6dc3f9bdfd38840a95208b1 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:49 -0800 Subject: [PATCH 056/132] tests(guards): add tests in guards/infinity.test.ts --- src/guards/infinity.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/guards/infinity.test.ts diff --git a/src/guards/infinity.test.ts b/src/guards/infinity.test.ts new file mode 100644 index 0000000..04f9852 --- /dev/null +++ b/src/guards/infinity.test.ts @@ -0,0 +1,10 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { isNegativeInfinity, isPositiveInfinity } from "./infinity.ts"; + +describe("guards/infinity", () => { + it("re-exports positive/negative infinity checks", () => { + assert.strictEqual(isPositiveInfinity(Infinity), true); + assert.strictEqual(isNegativeInfinity(-Infinity), true); + }); +}); From 2f7a0d93a70cb9521f677cbf87019176f1fb4e84 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:51 -0800 Subject: [PATCH 057/132] tests(guards): add tests in guards/finite.test.ts --- src/guards/finite.test.ts | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/guards/finite.test.ts diff --git a/src/guards/finite.test.ts b/src/guards/finite.test.ts new file mode 100644 index 0000000..433e42b --- /dev/null +++ b/src/guards/finite.test.ts @@ -0,0 +1,35 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { isFinite } from "./finite.ts"; + +const cases: unknown[] = [ + 0, + 1, + -1, + 1.5, + NaN, + Infinity, + -Infinity, + "1", +]; + +describe("isFinite", () => { + it("is a function", () => { + assert.strictEqual(typeof isFinite, "function"); + }); + + it("matches Number.isFinite for numbers", () => { + const numericCases = [0, 1, -1, 1.5, NaN, Infinity, -Infinity]; + for (const value of numericCases) { + assert.strictEqual(isFinite(value), Number.isFinite(value)); + } + }); + + it("returns false for non-numbers", () => { + for (const value of cases) { + if (typeof value !== "number") { + assert.strictEqual(isFinite(value), false); + } + } + }); +}); From bc54f3e0b10a31dd38b992e44a98cf2356b9f1f1 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:52 -0800 Subject: [PATCH 058/132] tests(tan): add tests in tan.test.ts --- src/tan.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/tan.test.ts diff --git a/src/tan.test.ts b/src/tan.test.ts new file mode 100644 index 0000000..f711ecd --- /dev/null +++ b/src/tan.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { tan } from "./tan.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("tan", () => { + it("is a function", () => { + assert.strictEqual(typeof tan, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(tan.length, 1); + }); + + it("matches Math.tan", () => { + const native = Math.tan; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = tan(input); + assertClose(actual, expected); + } + }); +}); From 08aed8c7bd25147ef230a689aa7371cb6b6aac95 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:53 -0800 Subject: [PATCH 059/132] tests(ieee754): add tests in ieee754.test.ts --- src/ieee754.test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/ieee754.test.ts diff --git a/src/ieee754.test.ts b/src/ieee754.test.ts new file mode 100644 index 0000000..68cc47a --- /dev/null +++ b/src/ieee754.test.ts @@ -0,0 +1,17 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import * as ieee754 from "./ieee754.ts"; + +describe("ieee754", () => { + it("re-exports float16 utilities", () => { + assert.strictEqual(typeof ieee754.encodeFloat16, "function"); + assert.strictEqual(typeof ieee754.decodeFloat16, "function"); + assert.strictEqual(typeof ieee754.roundFloat16, "function"); + }); + + it("re-exports float32 utilities", () => { + assert.strictEqual(typeof ieee754.encodeFloat32, "function"); + assert.strictEqual(typeof ieee754.decodeFloat32, "function"); + assert.strictEqual(typeof ieee754.roundFloat32, "function"); + }); +}); From f251b516272cc4ad70708224dd32b97375e185a3 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:55 -0800 Subject: [PATCH 060/132] tests(floor): add tests in floor.test.ts --- src/floor.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/floor.test.ts diff --git a/src/floor.test.ts b/src/floor.test.ts new file mode 100644 index 0000000..266e459 --- /dev/null +++ b/src/floor.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertSameValue } from "./internal/_test_utils.ts"; +import { floor } from "./floor.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("floor", () => { + it("is a function", () => { + assert.strictEqual(typeof floor, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(floor.length, 1); + }); + + it("matches Math.floor", () => { + const native = Math.floor; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = floor(input); + assertSameValue(actual, expected); + } + }); +}); From 151dc4fc7e20a7160a15746cb5fc2823bb0eaf14 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:56 -0800 Subject: [PATCH 061/132] tests(tanh): add tests in tanh.test.ts --- src/tanh.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/tanh.test.ts diff --git a/src/tanh.test.ts b/src/tanh.test.ts new file mode 100644 index 0000000..7384e05 --- /dev/null +++ b/src/tanh.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { tanh } from "./tanh.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("tanh", () => { + it("is a function", () => { + assert.strictEqual(typeof tanh, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(tanh.length, 1); + }); + + it("matches Math.tanh", () => { + const native = Math.tanh; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = tanh(input); + assertClose(actual, expected); + } + }); +}); From a681e828b75f8dfb4bef29727e25f41aa6ceab2c Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:58 -0800 Subject: [PATCH 062/132] tests(imul): add tests in imul.test.ts --- src/imul.test.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/imul.test.ts diff --git a/src/imul.test.ts b/src/imul.test.ts new file mode 100644 index 0000000..3df361f --- /dev/null +++ b/src/imul.test.ts @@ -0,0 +1,28 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertSameValue } from "./internal/_test_utils.ts"; +import { imul } from "./imul.ts"; + +const cases: Array<[number, number]> = [[2, 3], [-1, 8], [4294967295, 5], [ + 0, + 123, +], [3.5, 2]]; + +describe("imul", () => { + it("is a function", () => { + assert.strictEqual(typeof imul, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(imul.length, 2); + }); + + it("matches Math.imul", () => { + const native = Math.imul; + for (const [a, b] of cases) { + const expected = native(a, b); + const actual = imul(a, b); + assertSameValue(actual, expected); + } + }); +}); From 83de2cb9d2e8e930b7db33126c936601a101db10 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:53:59 -0800 Subject: [PATCH 063/132] tests(float16): add tests in float16/guards.test.ts --- src/float16/guards.test.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/float16/guards.test.ts diff --git a/src/float16/guards.test.ts b/src/float16/guards.test.ts new file mode 100644 index 0000000..87f7c47 --- /dev/null +++ b/src/float16/guards.test.ts @@ -0,0 +1,20 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { isFloat16 } from "./guards.ts"; +import { roundFloat16 } from "./round.ts"; + +const cases = [0, -0, 1, -1, 0.1, 0.5, 3.14, 42, Infinity, -Infinity, NaN]; + +describe("isFloat16", () => { + it("is a function", () => { + assert.strictEqual(typeof isFloat16, "function"); + }); + + it("matches roundFloat16 equivalence", () => { + for (const value of cases) { + const expected = typeof value === "number" && !Number.isNaN(value) && + value === roundFloat16(value); + assert.strictEqual(isFloat16(value), expected); + } + }); +}); From 113645b93a2cff523470e20356dd783ce0984243 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:00 -0800 Subject: [PATCH 064/132] tests(float16): add tests in float16/constants.test.ts --- src/float16/constants.test.ts | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/float16/constants.test.ts diff --git a/src/float16/constants.test.ts b/src/float16/constants.test.ts new file mode 100644 index 0000000..0cc855c --- /dev/null +++ b/src/float16/constants.test.ts @@ -0,0 +1,36 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import float16, { + FLOAT16_EXPONENT_BIAS, + FLOAT16_EXPONENT_BITS, + FLOAT16_MANTISSA_BITS, + FLOAT16_NAN, + FLOAT16_NEGATIVE_INFINITY, + FLOAT16_NEGATIVE_ZERO, + FLOAT16_POSITIVE_INFINITY, + FLOAT16_POSITIVE_ZERO, +} from "./constants.ts"; + +describe("float16/constants", () => { + it("exposes expected numeric constants", () => { + assert.strictEqual(typeof FLOAT16_NAN, "number"); + assert.strictEqual(FLOAT16_POSITIVE_INFINITY, 0x7C00); + assert.strictEqual(FLOAT16_NEGATIVE_INFINITY, 0xFC00); + assert.strictEqual(FLOAT16_NEGATIVE_ZERO, 0x8000); + assert.strictEqual(FLOAT16_POSITIVE_ZERO, 0x0000); + assert.strictEqual(FLOAT16_EXPONENT_BITS, 0x5); + assert.strictEqual(FLOAT16_MANTISSA_BITS, 0xA); + assert.strictEqual(FLOAT16_EXPONENT_BIAS, 0xF); + }); + + it("matches default export shape", () => { + assert.strictEqual(float16.exponent, FLOAT16_EXPONENT_BITS); + assert.strictEqual(float16.mantissa, FLOAT16_MANTISSA_BITS); + assert.strictEqual(float16.bias, FLOAT16_EXPONENT_BIAS); + assert.strictEqual(float16.nan, FLOAT16_NAN); + assert.strictEqual(float16.positive_infinity, FLOAT16_POSITIVE_INFINITY); + assert.strictEqual(float16.negative_infinity, FLOAT16_NEGATIVE_INFINITY); + assert.strictEqual(float16.negative_zero, FLOAT16_NEGATIVE_ZERO); + assert.strictEqual(float16.positive_zero, FLOAT16_POSITIVE_ZERO); + }); +}); From bff2bfa744a786f18b7c40f9fd7bbe49b8ff35e9 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:02 -0800 Subject: [PATCH 065/132] tests(float16): add tests in float16/index.test.ts --- src/float16/index.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/float16/index.test.ts diff --git a/src/float16/index.test.ts b/src/float16/index.test.ts new file mode 100644 index 0000000..897253b --- /dev/null +++ b/src/float16/index.test.ts @@ -0,0 +1,12 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import * as float16 from "./index.ts"; + +describe("float16/index", () => { + it("exports float16 utilities", () => { + assert.strictEqual(typeof float16.encodeFloat16, "function"); + assert.strictEqual(typeof float16.decodeFloat16, "function"); + assert.strictEqual(typeof float16.roundFloat16, "function"); + assert.strictEqual(typeof float16.isFloat16, "function"); + }); +}); From 034a367ed2c4a1a0b27f84b1296cb06325453c93 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:03 -0800 Subject: [PATCH 066/132] tests(float16): add tests in float16/encode.test.ts --- src/float16/encode.test.ts | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/float16/encode.test.ts diff --git a/src/float16/encode.test.ts b/src/float16/encode.test.ts new file mode 100644 index 0000000..d1400e6 --- /dev/null +++ b/src/float16/encode.test.ts @@ -0,0 +1,35 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { encodeFloat16 } from "./encode.ts"; + +const cases = [0, -0, 1, -1, 3.14, 42, Infinity, -Infinity]; + +describe("encodeFloat16", () => { + it("is a function", () => { + assert.strictEqual(typeof encodeFloat16, "function"); + }); + + it("returns a 16-bit unsigned integer", () => { + for (const value of cases) { + const encoded = encodeFloat16(value); + assert.ok(encoded >= 0 && encoded <= 0xFFFF); + } + }); + + it("matches DataView float16 encoding when available", () => { + const view = new DataView(new ArrayBuffer(2)); + const setFloat16 = (view as unknown as { + setFloat16?: (offset: number, value: number) => void; + }).setFloat16; + const getUint16 = view.getUint16.bind(view); + if (typeof setFloat16 !== "function") { + return; + } + for (const value of cases) { + setFloat16.call(view, 0, value); + const expected = getUint16(0); + const actual = encodeFloat16(value); + assert.strictEqual(actual, expected); + } + }); +}); From 0d95931eb426287b2d3d5465198456dc330dd9ba Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:04 -0800 Subject: [PATCH 067/132] tests(float16): add tests in float16/decode.test.ts --- src/float16/decode.test.ts | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/float16/decode.test.ts diff --git a/src/float16/decode.test.ts b/src/float16/decode.test.ts new file mode 100644 index 0000000..8c93c9e --- /dev/null +++ b/src/float16/decode.test.ts @@ -0,0 +1,41 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { decodeFloat16 } from "./decode.ts"; + +const cases = [0x0000, 0x8000, 0x3C00, 0xBC00, 0x7C00, 0xFC00, 0x7E00, 0x4248]; + +describe("decodeFloat16", () => { + it("is a function", () => { + assert.strictEqual(typeof decodeFloat16, "function"); + }); + + it("decodes known bit patterns", () => { + assert.strictEqual(Object.is(decodeFloat16(0x0000), 0), true); + assert.strictEqual(Object.is(decodeFloat16(0x8000), -0), true); + assert.strictEqual(decodeFloat16(0x3C00), 1); + assert.strictEqual(decodeFloat16(0xBC00), -1); + assert.strictEqual(decodeFloat16(0x7C00), Infinity); + assert.strictEqual(decodeFloat16(0xFC00), -Infinity); + assert.ok(Number.isNaN(decodeFloat16(0x7E00))); + }); + + it("matches DataView float16 decoding when available", () => { + const view = new DataView(new ArrayBuffer(2)); + const getFloat16 = + (view as unknown as { getFloat16?: (offset: number) => number }) + .getFloat16; + if (typeof getFloat16 !== "function") { + return; + } + for (const bits of cases) { + view.setUint16(0, bits); + const expected = getFloat16.call(view, 0); + const actual = decodeFloat16(bits); + if (Number.isNaN(expected)) { + assert.ok(Number.isNaN(actual)); + } else { + assert.strictEqual(actual, expected); + } + } + }); +}); From 8fea689754657c36a31e3ad204db30eb5258d6ea Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:06 -0800 Subject: [PATCH 068/132] tests(float16): add tests in float16/round.test.ts --- src/float16/round.test.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/float16/round.test.ts diff --git a/src/float16/round.test.ts b/src/float16/round.test.ts new file mode 100644 index 0000000..5a1e1bc --- /dev/null +++ b/src/float16/round.test.ts @@ -0,0 +1,27 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { roundFloat16 } from "./round.ts"; + +const cases = [0, -0, 1, -1, 3.14, 42, Infinity, -Infinity, NaN]; + +describe("roundFloat16", () => { + it("is a function", () => { + assert.strictEqual(typeof roundFloat16, "function"); + }); + + it("matches Math.f16round when available", () => { + const native = Math.f16round as ((x: number) => number) | undefined; + if (typeof native !== "function") { + return; + } + for (const value of cases) { + const expected = native(value); + const actual = roundFloat16(value); + if (Number.isNaN(expected)) { + assert.ok(Number.isNaN(actual)); + } else { + assert.strictEqual(actual, expected); + } + } + }); +}); From 111d253456241d8ee6a5dade048a5483c3789f8c Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:07 -0800 Subject: [PATCH 069/132] tests(types): add tests in types/precision.test.ts --- src/types/precision.test.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/types/precision.test.ts diff --git a/src/types/precision.test.ts b/src/types/precision.test.ts new file mode 100644 index 0000000..7d90c99 --- /dev/null +++ b/src/types/precision.test.ts @@ -0,0 +1,28 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import type { + FloatPrecision, + P16, + P32, + P64, + P8, + Precision, +} from "./precision.ts"; + +const p8Value = 8 as P8; +const p16Value = 16 as P16; +const p32Value = 32 as P32; +const p64Value = 64 as P64; +const precisionValue = 32 as Precision; +const floatPrecisionValue = 32 as FloatPrecision; + +describe("types/precision", () => { + it("supports precision literals", () => { + assert.strictEqual(p8Value, 8); + assert.strictEqual(p16Value, 16); + assert.strictEqual(p32Value, 32); + assert.strictEqual(p64Value, 64); + assert.strictEqual(precisionValue, 32); + assert.strictEqual(floatPrecisionValue, 32); + }); +}); From 76bcb7d34a610ba7d0848669eec924c9477b0729 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:09 -0800 Subject: [PATCH 070/132] tests(types): add tests in types/safe_integer.test.ts --- src/types/safe_integer.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/types/safe_integer.test.ts diff --git a/src/types/safe_integer.test.ts b/src/types/safe_integer.test.ts new file mode 100644 index 0000000..6672704 --- /dev/null +++ b/src/types/safe_integer.test.ts @@ -0,0 +1,11 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import type { SafeInteger } from "./safe_integer.ts"; + +const safeValue = 1 as SafeInteger; + +describe("types/safe_integer", () => { + it("supports safe integer branding", () => { + assert.strictEqual(typeof safeValue, "number"); + }); +}); From 2bd2971603a53330b8fe0c19ba12953524f46557 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:10 -0800 Subject: [PATCH 071/132] tests(types): add tests in types/index.test.ts --- src/types/index.test.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/types/index.test.ts diff --git a/src/types/index.test.ts b/src/types/index.test.ts new file mode 100644 index 0000000..06009af --- /dev/null +++ b/src/types/index.test.ts @@ -0,0 +1,25 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import type { + Finite, + Float, + Integer, + Precision, + SafeInteger, +} from "./index.ts"; + +const finiteValue = 1 as Finite; +const floatValue = 1 as Float; +const integerValue = 1 as Integer; +const precisionValue = 32 as Precision; +const safeValue = 1 as SafeInteger; + +describe("types/index", () => { + it("re-exports type helpers", () => { + assert.strictEqual(typeof finiteValue, "number"); + assert.strictEqual(typeof floatValue, "number"); + assert.strictEqual(typeof integerValue, "number"); + assert.strictEqual(precisionValue, 32); + assert.strictEqual(typeof safeValue, "number"); + }); +}); From 97d1cd994d8f82815a2f99506f58cdd152261cf7 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:11 -0800 Subject: [PATCH 072/132] tests(types): add tests in types/integer.test.ts --- src/types/integer.test.ts | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/types/integer.test.ts diff --git a/src/types/integer.test.ts b/src/types/integer.test.ts new file mode 100644 index 0000000..d91b921 --- /dev/null +++ b/src/types/integer.test.ts @@ -0,0 +1,46 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import type { + BigInt64, + BigUint64, + Int16, + Int32, + Int64, + Int8, + Integer, + Uint16, + Uint32, + Uint64, + Uint8, + Unsigned, +} from "./integer.ts"; + +const intValue = 1 as Integer; +const uintValue = 1 as Unsigned; +const int8Value = 1 as Int8; +const uint8Value = 1 as Uint8; +const int16Value = 1 as Int16; +const uint16Value = 1 as Uint16; +const int32Value = 1 as Int32; +const uint32Value = 1 as Uint32; +const int64Value = 1 as Int64; +const uint64Value = 1 as Uint64; +const bigint64Value = 1n as BigInt64; +const biguint64Value = 1n as BigUint64; + +describe("types/integer", () => { + it("supports integer branding", () => { + assert.strictEqual(typeof intValue, "number"); + assert.strictEqual(typeof uintValue, "number"); + assert.strictEqual(typeof int8Value, "number"); + assert.strictEqual(typeof uint8Value, "number"); + assert.strictEqual(typeof int16Value, "number"); + assert.strictEqual(typeof uint16Value, "number"); + assert.strictEqual(typeof int32Value, "number"); + assert.strictEqual(typeof uint32Value, "number"); + assert.strictEqual(typeof int64Value, "number"); + assert.strictEqual(typeof uint64Value, "number"); + assert.strictEqual(typeof bigint64Value, "bigint"); + assert.strictEqual(typeof biguint64Value, "bigint"); + }); +}); From 9e8288f0b8cc2b2b27eeba8fa451ae82e4585d56 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:13 -0800 Subject: [PATCH 073/132] tests(types): add tests in types/finite.test.ts --- src/types/finite.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/types/finite.test.ts diff --git a/src/types/finite.test.ts b/src/types/finite.test.ts new file mode 100644 index 0000000..fefd760 --- /dev/null +++ b/src/types/finite.test.ts @@ -0,0 +1,11 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import type { Finite } from "./finite.ts"; + +const finiteValue = 1 as Finite; + +describe("types/finite", () => { + it("supports finite branding", () => { + assert.strictEqual(typeof finiteValue, "number"); + }); +}); From 078fea95f6128edb817a71ddd72e95ff245d7fb7 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:14 -0800 Subject: [PATCH 074/132] tests(types): add tests in types/float.test.ts --- src/types/float.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/types/float.test.ts diff --git a/src/types/float.test.ts b/src/types/float.test.ts new file mode 100644 index 0000000..0c65695 --- /dev/null +++ b/src/types/float.test.ts @@ -0,0 +1,19 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import type { Double, Float, Float16, Float32, Float64 } from "./float.ts"; + +const floatValue = 1 as Float; +const float16Value = 1 as Float16; +const float32Value = 1 as Float32; +const float64Value = 1 as Float64; +const doubleValue = 1 as Double; + +describe("types/float", () => { + it("supports float branding", () => { + assert.strictEqual(typeof floatValue, "number"); + assert.strictEqual(typeof float16Value, "number"); + assert.strictEqual(typeof float32Value, "number"); + assert.strictEqual(typeof float64Value, "number"); + assert.strictEqual(typeof doubleValue, "number"); + }); +}); From a11be3f189e0fe5bfee23b932176ef1ed26bbc24 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:15 -0800 Subject: [PATCH 075/132] tests(cos): add tests in cos.test.ts --- src/cos.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/cos.test.ts diff --git a/src/cos.test.ts b/src/cos.test.ts new file mode 100644 index 0000000..df6b893 --- /dev/null +++ b/src/cos.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { cos } from "./cos.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("cos", () => { + it("is a function", () => { + assert.strictEqual(typeof cos, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(cos.length, 1); + }); + + it("matches Math.cos", () => { + const native = Math.cos; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = cos(input); + assertClose(actual, expected); + } + }); +}); From 4c856bfa01b75830265591a7bf12964320e38123 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:17 -0800 Subject: [PATCH 076/132] tests(sqrt): add tests in sqrt.test.ts --- src/sqrt.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/sqrt.test.ts diff --git a/src/sqrt.test.ts b/src/sqrt.test.ts new file mode 100644 index 0000000..a0c0090 --- /dev/null +++ b/src/sqrt.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { sqrt } from "./sqrt.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("sqrt", () => { + it("is a function", () => { + assert.strictEqual(typeof sqrt, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(sqrt.length, 1); + }); + + it("matches Math.sqrt", () => { + const native = Math.sqrt; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = sqrt(input); + assertClose(actual, expected); + } + }); +}); From 745fdca777adb33be3e9c7cab08f10b86fe2821b Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:18 -0800 Subject: [PATCH 077/132] tests(atanh): add tests in atanh.test.ts --- src/atanh.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/atanh.test.ts diff --git a/src/atanh.test.ts b/src/atanh.test.ts new file mode 100644 index 0000000..2edac01 --- /dev/null +++ b/src/atanh.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { atanh } from "./atanh.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("atanh", () => { + it("is a function", () => { + assert.strictEqual(typeof atanh, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(atanh.length, 1); + }); + + it("matches Math.atanh", () => { + const native = Math.atanh; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = atanh(input); + assertClose(actual, expected); + } + }); +}); From df5067c08056404cf3082f03853d5bd8ec7a6985 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:19 -0800 Subject: [PATCH 078/132] tests(min): add tests in min.test.ts --- src/min.test.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/min.test.ts diff --git a/src/min.test.ts b/src/min.test.ts new file mode 100644 index 0000000..5c4cbb6 --- /dev/null +++ b/src/min.test.ts @@ -0,0 +1,33 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertSameValue } from "./internal/_test_utils.ts"; +import { min } from "./min.ts"; + +const cases: Array = [ + [1, 2, 3], + [-10, -5, -1], + [1, -1, 0], + [NaN, 1, 2], + [0.0, -0], + [-Infinity, 1], + [], +]; + +describe("min", () => { + it("is a function", () => { + assert.strictEqual(typeof min, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(min.length, 0); + }); + + it("matches Math.min", () => { + const native = Math.min; + for (const args of cases) { + const expected = native(...args); + const actual = min(...args); + assertSameValue(actual, expected); + } + }); +}); From 61ec53471f4f7d99af591aafcbc15e329110ff9d Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:21 -0800 Subject: [PATCH 079/132] tests(pow): add tests in pow.test.ts --- src/pow.test.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/pow.test.ts diff --git a/src/pow.test.ts b/src/pow.test.ts new file mode 100644 index 0000000..cf39bab --- /dev/null +++ b/src/pow.test.ts @@ -0,0 +1,34 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { pow } from "./pow.ts"; + +const cases: Array<[number, number]> = [ + [2, 3], + [4, 0.5], + [-2, 3], + [-2, 2], + [2, -1], + [0, 0], + [-1, 0.5], + [NaN, 2], +]; + +describe("pow", () => { + it("is a function", () => { + assert.strictEqual(typeof pow, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(pow.length, 2); + }); + + it("matches Math.pow", () => { + const native = Math.pow; + for (const [a, b] of cases) { + const expected = native(a, b); + const actual = pow(a, b); + assertClose(actual, expected); + } + }); +}); From b63d225586d403c2b7095226a1885873d348521b Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:22 -0800 Subject: [PATCH 080/132] tests(trigonometry): add tests in trigonometry.test.ts --- src/trigonometry.test.ts | 222 ++++++++++++--------------------------- 1 file changed, 66 insertions(+), 156 deletions(-) diff --git a/src/trigonometry.test.ts b/src/trigonometry.test.ts index d792662..550b70b 100644 --- a/src/trigonometry.test.ts +++ b/src/trigonometry.test.ts @@ -1,5 +1,6 @@ -import { describe, it } from "jsr:@std/testing@1/bdd"; -import { expect } from "jsr:@std/expect@1"; +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; import { acos, acosh, @@ -14,179 +15,88 @@ import { tanh, } from "./index.ts"; -describe("Math Trigonometric Functions", () => { - describe("acos", () => { - it("should return a value close to Math.acos for valid inputs", () => { - expect(acos(0)).toBeCloseTo(Math.acos(0), 10); - expect(acos(1)).toBeCloseTo(Math.acos(1), 10); - expect(acos(-1)).toBeCloseTo(Math.acos(-1), 10); - }); - it("should return NaN for inputs outside the range [-1, 1]", () => { - expect(acos(2)).toBeNaN(); - expect(acos(-2)).toBeNaN(); - }); - it("should handle NaN and Infinity inputs", () => { - expect(acos(NaN)).toBeNaN(); - expect(acos(Infinity)).toBeNaN(); - expect(acos(-Infinity)).toBeNaN(); - }); +const unaryCases = [0, 0.5, -0.5, 1, -1, Math.PI / 2, Math.PI, NaN]; + +describe("Math trigonometric functions", () => { + it("acos matches Math.acos", () => { + for (const value of unaryCases) { + assertClose(acos(value), Math.acos(value)); + } }); - describe("asin", () => { - it("should return a value close to Math.asin for valid inputs", () => { - expect(asin(0)).toBeCloseTo(Math.asin(0), 10); - expect(asin(1)).toBeCloseTo(Math.asin(1), 10); - expect(asin(-1)).toBeCloseTo(Math.asin(-1), 10); - }); - it("should return NaN for inputs outside the range [-1, 1]", () => { - expect(asin(2)).toBeNaN(); - expect(asin(-2)).toBeNaN(); - }); - it("should handle NaN and Infinity inputs", () => { - expect(asin(NaN)).toBeNaN(); - expect(asin(Infinity)).toBeNaN(); - expect(asin(-Infinity)).toBeNaN(); - }); + it("asin matches Math.asin", () => { + for (const value of unaryCases) { + assertClose(asin(value), Math.asin(value)); + } }); - describe("atan", () => { - it("should return a value close to Math.atan for valid inputs", () => { - expect(atan(0)).toBeCloseTo(Math.atan(0), 10); - expect(atan(1)).toBeCloseTo(Math.atan(1), 10); - expect(atan(-1)).toBeCloseTo(Math.atan(-1), 10); - }); - it("should return ±π/2 for Infinity and -Infinity inputs", () => { - expect(atan(Infinity)).toBeCloseTo(Math.atan(Infinity), 10); - expect(atan(-Infinity)).toBeCloseTo(Math.atan(-Infinity), 10); - }); - it("should handle NaN and -0", () => { - expect(atan(NaN)).toBeNaN(); - expect(atan(-0)).toBe(-0); - }); + it("atan matches Math.atan", () => { + for (const value of unaryCases) { + assertClose(atan(value), Math.atan(value)); + } }); - describe("atan2", () => { - it("should return a value close to Math.atan2 for valid inputs", () => { - expect(atan2(1, 1)).toBeCloseTo(Math.atan2(1, 1), 10); - expect(atan2(-1, -1)).toBeCloseTo(Math.atan2(-1, -1), 10); - }); - it("should handle cases with 0 and -0 as inputs", () => { - expect(atan2(0, 1)).toBeCloseTo(Math.atan2(0, 1), 10); - expect(atan2(0, -1)).toBeCloseTo(Math.atan2(0, -1), 10); - expect(atan2(-0, -1)).toBeCloseTo(Math.atan2(-0, -1), 10); - }); - it("should handle Infinity, -Infinity, and NaN inputs", () => { - expect(atan2(Infinity, Infinity)).toBeCloseTo( - Math.atan2(Infinity, Infinity), - 10, - ); - expect(atan2(-Infinity, -Infinity)).toBeCloseTo( - Math.atan2(-Infinity, -Infinity), - 10, - ); - expect(atan2(NaN, 1)).toBeNaN(); - expect(atan2(1, NaN)).toBeNaN(); - }); + it("atan2 matches Math.atan2", () => { + const cases: Array<[number, number]> = [ + [0, 1], + [1, 0], + [-1, -1], + [0, -1], + [-0, -1], + [1, -0], + [NaN, 1], + ]; + for (const [y, x] of cases) { + assertClose(atan2(y, x), Math.atan2(y, x)); + } }); - describe("acosh", () => { - it("should return a value close to Math.acosh for valid inputs", () => { - expect(acosh(1)).toBeCloseTo(Math.acosh(1), 10); - expect(acosh(2)).toBeCloseTo(Math.acosh(2), 10); - }); - it("should return Infinity for Infinity input", () => { - expect(acosh(Infinity)).toBe(Infinity); - }); - it("should return NaN for inputs less than 1 and NaN", () => { - expect(acosh(0)).toBeNaN(); - expect(acosh(-1)).toBeNaN(); - expect(acosh(NaN)).toBeNaN(); - }); + it("acosh matches Math.acosh", () => { + const cases = [1, 2, 10, 0.5, -1, NaN, Infinity]; + for (const value of cases) { + assertClose(acosh(value), Math.acosh(value)); + } }); - describe("asinh", () => { - it("should return a value close to Math.asinh for valid inputs", () => { - expect(asinh(0)).toBeCloseTo(Math.asinh(0), 10); - expect(asinh(1)).toBeCloseTo(Math.asinh(1), 10); - expect(asinh(-1)).toBeCloseTo(Math.asinh(-1), 10); - }); - it("should return Infinity for Infinity input", () => { - expect(asinh(Infinity)).toBe(Infinity); - expect(asinh(-Infinity)).toBe(-Infinity); - }); - it("should return NaN for NaN input", () => { - expect(asinh(NaN)).toBeNaN(); - }); + it("asinh matches Math.asinh", () => { + const cases = [-2, -1, 0, 1, 2, NaN, Infinity, -Infinity]; + for (const value of cases) { + assertClose(asinh(value), Math.asinh(value)); + } }); - describe("atanh", () => { - it("should return a value close to Math.atanh for values in the range (-1, 1)", () => { - expect(atanh(0)).toBeCloseTo(Math.atanh(0), 10); - expect(atanh(0.5)).toBeCloseTo(Math.atanh(0.5), 10); - expect(atanh(-0.5)).toBeCloseTo(Math.atanh(-0.5), 10); - }); - it("should return ±Infinity for inputs ±1", () => { - expect(atanh(1)).toBe(Infinity); - expect(atanh(-1)).toBe(-Infinity); - }); - it("should return NaN for inputs outside (-1, 1) and for NaN", () => { - expect(atanh(2)).toBeNaN(); - expect(atanh(-2)).toBeNaN(); - expect(atanh(NaN)).toBeNaN(); - }); + it("atanh matches Math.atanh", () => { + const cases = [-0.9, -0.5, 0, 0.5, 0.9, 1, -1, 2, NaN]; + for (const value of cases) { + assertClose(atanh(value), Math.atanh(value)); + } }); - describe("cos", () => { - it("should return a value close to Math.cos for valid inputs", () => { - expect(cos(0)).toBeCloseTo(Math.cos(0), 10); - expect(cos(Math.PI / 2)).toBeCloseTo(Math.cos(Math.PI / 2), 10); - expect(cos(Math.PI)).toBeCloseTo(Math.cos(Math.PI), 10); - }); - it("should return NaN for Infinity, -Infinity, and NaN", () => { - expect(cos(Infinity)).toBeNaN(); - expect(cos(-Infinity)).toBeNaN(); - expect(cos(NaN)).toBeNaN(); - }); + it("cos matches Math.cos", () => { + const cases = [0, Math.PI / 2, Math.PI, -Math.PI, NaN, Infinity]; + for (const value of cases) { + assertClose(cos(value), Math.cos(value)); + } }); - describe("sin", () => { - it("should return a value close to Math.sin for valid inputs", () => { - expect(sin(0)).toBeCloseTo(Math.sin(0), 10); - expect(sin(Math.PI / 2)).toBeCloseTo(Math.sin(Math.PI / 2), 10); - expect(sin(Math.PI)).toBeCloseTo(Math.sin(Math.PI), 10); - }); - it("should return NaN for Infinity, -Infinity, and NaN", () => { - expect(sin(Infinity)).toBeNaN(); - expect(sin(-Infinity)).toBeNaN(); - expect(sin(NaN)).toBeNaN(); - }); + it("sin matches Math.sin", () => { + const cases = [0, Math.PI / 2, Math.PI, -Math.PI, NaN, Infinity]; + for (const value of cases) { + assertClose(sin(value), Math.sin(value)); + } }); - describe("tan", () => { - it("should return a value close to Math.tan for valid inputs", () => { - expect(tan(0)).toBeCloseTo(Math.tan(0), 10); - expect(tan(Math.PI / 4)).toBeCloseTo(Math.tan(Math.PI / 4), 10); - expect(tan(-Math.PI / 4)).toBeCloseTo(Math.tan(-Math.PI / 4), 10); - }); - it("should return NaN for Infinity, -Infinity, and NaN", () => { - expect(tan(Infinity)).toBeNaN(); - expect(tan(-Infinity)).toBeNaN(); - expect(tan(NaN)).toBeNaN(); - }); + it("tan matches Math.tan", () => { + const cases = [0, Math.PI / 4, -Math.PI / 4, 1, NaN, Infinity]; + for (const value of cases) { + assertClose(tan(value), Math.tan(value)); + } }); - describe("tanh", () => { - it("should return a value close to Math.tanh for valid inputs", () => { - expect(tanh(0)).toBeCloseTo(Math.tanh(0), 10); - expect(tanh(1)).toBeCloseTo(Math.tanh(1), 10); - expect(tanh(-1)).toBeCloseTo(Math.tanh(-1), 10); - }); - it("should return ±1 for ±Infinity inputs", () => { - expect(tanh(Infinity)).toBeCloseTo(Math.tanh(Infinity), 10); - expect(tanh(-Infinity)).toBeCloseTo(Math.tanh(-Infinity), 10); - }); - it("should return NaN for NaN input", () => { - expect(tanh(NaN)).toBeNaN(); - }); + it("tanh matches Math.tanh", () => { + const cases = [-2, -1, 0, 1, 2, Infinity, -Infinity, NaN]; + for (const value of cases) { + assertClose(tanh(value), Math.tanh(value)); + } }); }); From c8801bfb701b7f78cfa89605ed97ea60742508a6 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:24 -0800 Subject: [PATCH 081/132] tests(sign): add tests in sign.test.ts --- src/sign.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/sign.test.ts diff --git a/src/sign.test.ts b/src/sign.test.ts new file mode 100644 index 0000000..e873882 --- /dev/null +++ b/src/sign.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertSameValue } from "./internal/_test_utils.ts"; +import { sign } from "./sign.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("sign", () => { + it("is a function", () => { + assert.strictEqual(typeof sign, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(sign.length, 1); + }); + + it("matches Math.sign", () => { + const native = Math.sign; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = sign(input); + assertSameValue(actual, expected); + } + }); +}); From da145a1464c4a3d760e208c604bbd2509b4cce59 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:25 -0800 Subject: [PATCH 082/132] tests(exp): add tests in exp.test.ts --- src/exp.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/exp.test.ts diff --git a/src/exp.test.ts b/src/exp.test.ts new file mode 100644 index 0000000..aab293d --- /dev/null +++ b/src/exp.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { exp } from "./exp.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("exp", () => { + it("is a function", () => { + assert.strictEqual(typeof exp, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(exp.length, 1); + }); + + it("matches Math.exp", () => { + const native = Math.exp; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = exp(input); + assertClose(actual, expected); + } + }); +}); From 9e5bb653415f9af95c4a8d0f0595a90d708add8c Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:26 -0800 Subject: [PATCH 083/132] tests(f16round): add tests in f16round.test.ts --- src/f16round.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/f16round.test.ts diff --git a/src/f16round.test.ts b/src/f16round.test.ts new file mode 100644 index 0000000..880ae83 --- /dev/null +++ b/src/f16round.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertSameValue } from "./internal/_test_utils.ts"; +import { f16round } from "./f16round.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("f16round", () => { + it("is a function", () => { + assert.strictEqual(typeof f16round, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(f16round.length, 1); + }); + + it("matches Math.f16round", () => { + const native = Math.f16round; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = f16round(input); + assertSameValue(actual, expected); + } + }); +}); From d1f77d4da110556f8d58d214b04295d5594b39e2 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:28 -0800 Subject: [PATCH 084/132] tests(log1p): add tests in log1p.test.ts --- src/log1p.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/log1p.test.ts diff --git a/src/log1p.test.ts b/src/log1p.test.ts new file mode 100644 index 0000000..da1c971 --- /dev/null +++ b/src/log1p.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { log1p } from "./log1p.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("log1p", () => { + it("is a function", () => { + assert.strictEqual(typeof log1p, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(log1p.length, 1); + }); + + it("matches Math.log1p", () => { + const native = Math.log1p; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = log1p(input); + assertClose(actual, expected); + } + }); +}); From 16c47f9b4f1d15604dfa01bfea6604016e0361f0 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:29 -0800 Subject: [PATCH 085/132] tests(round): add tests in round.test.ts --- src/round.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/round.test.ts diff --git a/src/round.test.ts b/src/round.test.ts new file mode 100644 index 0000000..bf8fc80 --- /dev/null +++ b/src/round.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertSameValue } from "./internal/_test_utils.ts"; +import { round } from "./round.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("round", () => { + it("is a function", () => { + assert.strictEqual(typeof round, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(round.length, 1); + }); + + it("matches Math.round", () => { + const native = Math.round; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = round(input); + assertSameValue(actual, expected); + } + }); +}); From 39c3a8e9a6dc5f3451a6e0ad7a0649bd9a94c6d6 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:30 -0800 Subject: [PATCH 086/132] tests(hypot): add tests in hypot.test.ts --- src/hypot.test.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/hypot.test.ts diff --git a/src/hypot.test.ts b/src/hypot.test.ts new file mode 100644 index 0000000..0bd3246 --- /dev/null +++ b/src/hypot.test.ts @@ -0,0 +1,28 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { hypot } from "./hypot.ts"; + +const cases: Array = [[3, 4], [0, 0], [1, 2, 3], [Infinity, 1], [ + NaN, + 1, +], []]; + +describe("hypot", () => { + it("is a function", () => { + assert.strictEqual(typeof hypot, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(hypot.length, 0); + }); + + it("matches Math.hypot", () => { + const native = Math.hypot; + for (const args of cases) { + const expected = native(...args); + const actual = hypot(...args); + assertClose(actual, expected); + } + }); +}); From bedc0951c7060a107329b447186e247299a845f9 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:32 -0800 Subject: [PATCH 087/132] tests(cosh): add tests in cosh.test.ts --- src/cosh.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/cosh.test.ts diff --git a/src/cosh.test.ts b/src/cosh.test.ts new file mode 100644 index 0000000..507ad11 --- /dev/null +++ b/src/cosh.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { cosh } from "./cosh.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("cosh", () => { + it("is a function", () => { + assert.strictEqual(typeof cosh, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(cosh.length, 1); + }); + + it("matches Math.cosh", () => { + const native = Math.cosh; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = cosh(input); + assertClose(actual, expected); + } + }); +}); From a7b5532ba410dbee7acbdd49750d1e2100e14a02 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:33 -0800 Subject: [PATCH 088/132] tests(fround): add tests in fround.test.ts --- src/fround.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/fround.test.ts diff --git a/src/fround.test.ts b/src/fround.test.ts new file mode 100644 index 0000000..a7a1c0e --- /dev/null +++ b/src/fround.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertSameValue } from "./internal/_test_utils.ts"; +import { fround } from "./fround.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("fround", () => { + it("is a function", () => { + assert.strictEqual(typeof fround, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(fround.length, 1); + }); + + it("matches Math.fround", () => { + const native = Math.fround; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = fround(input); + assertSameValue(actual, expected); + } + }); +}); From a8c6bb1626deac14eb6090d7767066f5f9653b8b Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:54:35 -0800 Subject: [PATCH 089/132] tests(acosh): add tests in acosh.test.ts --- src/acosh.test.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/acosh.test.ts diff --git a/src/acosh.test.ts b/src/acosh.test.ts new file mode 100644 index 0000000..5e2f4e1 --- /dev/null +++ b/src/acosh.test.ts @@ -0,0 +1,40 @@ +import assert from "node:assert"; +import { describe, it } from "node:test"; +import { assertClose } from "./internal/_test_utils.ts"; +import { acosh } from "./acosh.ts"; + +const cases: number[] = [ + -2.5, + -1, + -0.0, + 0.0, + 0.5, + 1, + 2, + 10, + Infinity, + -Infinity, + NaN, +]; + +describe("acosh", () => { + it("is a function", () => { + assert.strictEqual(typeof acosh, "function"); + }); + + it("has the expected arity", () => { + assert.strictEqual(acosh.length, 1); + }); + + it("matches Math.acosh", () => { + const native = Math.acosh; + if (typeof native !== "function") { + return; + } + for (const input of cases) { + const expected = native(input); + const actual = acosh(input); + assertClose(actual, expected); + } + }); +}); From e64480e96d67336e549734d49fd31f6ff22750e6 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 16:56:24 -0800 Subject: [PATCH 090/132] tests(internal): create shared test helpers module --- src/internal/_test_utils.ts | 56 +++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/internal/_test_utils.ts diff --git a/src/internal/_test_utils.ts b/src/internal/_test_utils.ts new file mode 100644 index 0000000..c2d8902 --- /dev/null +++ b/src/internal/_test_utils.ts @@ -0,0 +1,56 @@ +import assert from "node:assert"; + +export const DEFAULT_EPSILON = 1e-12; + +export function assertSameValue( + actual: number, + expected: number, + message?: string, +): void { + if (Number.isNaN(expected)) { + assert.ok(Number.isNaN(actual), message ?? "Expected NaN"); + return; + } + if (Object.is(expected, -0)) { + assert.ok(Object.is(actual, -0), message ?? "Expected -0"); + return; + } + assert.strictEqual(actual, expected, message); +} + +export function assertClose( + actual: number, + expected: number, + epsilon: number = DEFAULT_EPSILON, + message?: string, +): void { + if (Number.isNaN(expected)) { + assert.ok(Number.isNaN(actual), message ?? "Expected NaN"); + return; + } + if (Object.is(expected, -0)) { + assert.ok(Object.is(actual, -0), message ?? "Expected -0"); + return; + } + if (expected === 0) { + assert.ok( + Math.abs(actual) <= epsilon, + message ?? `Expected ${actual} to be within ${epsilon} of 0`, + ); + assert.ok( + !Object.is(actual, -0), + message ?? "Expected +0 (not -0)", + ); + return; + } + if (!Number.isFinite(expected)) { + assertSameValue(actual, expected, message); + return; + } + const diff = Math.abs(actual - expected); + const scale = Math.max(1, Math.abs(expected)); + assert.ok( + diff <= epsilon * scale, + message ?? `Expected ${actual} to be within ${epsilon} of ${expected}`, + ); +} From 001eb1899db29e5303d68eb481f01c310aa903c3 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:47:05 -0800 Subject: [PATCH 091/132] chore(internal): add ArrayFrom to primordials --- src/internal/primordials.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/internal/primordials.ts b/src/internal/primordials.ts index ddcdf6b..94f65d9 100644 --- a/src/internal/primordials.ts +++ b/src/internal/primordials.ts @@ -19,6 +19,7 @@ export const Object: ObjectConstructor = globalThis.Object; export const ObjectPrototype = Object.prototype; export const Array: ArrayConstructor = globalThis.Array; +export const ArrayFrom: typeof Array.from = Array.from.bind(Array); export const ArrayPrototype = Array.prototype; export const Function: FunctionConstructor = globalThis.Function; From a91ded9c8699fc4c18764a658da660bfe5d47e60 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:47:46 -0800 Subject: [PATCH 092/132] refactor(random): clean up MT19937 class, use ArrayFrom primordial --- src/random.ts | 101 +++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 55 deletions(-) diff --git a/src/random.ts b/src/random.ts index cad9567..e9ef1fc 100644 --- a/src/random.ts +++ b/src/random.ts @@ -13,7 +13,20 @@ * ``` * @module random */ -import { DateNow } from "./internal/primordials.ts"; +import { ArrayFrom, DateNow } from "./internal/primordials.ts"; + +/** Period parameters */ +const N = 624; +/** The number of 32 bit words */ +const M = 397; +/** Constant Vector A */ +const MATRIX_A = 0x9908b0df; +/** Most significant W-R bits */ +const UPPER_MASK = 0x80000000; +/** Least significant R bits */ +const LOWER_MASK = 0x7fffffff; +/** UPPER_MASK + LOWER_MASK + 1 */ +const TOTAL_MASK = 0x100000000; /** * Mersenne Twister implementation in TypeScript. @@ -80,31 +93,18 @@ export class MT19937 { return MT19937.#instance.randomInt(); } - /** Period parameters */ - readonly #N = 624; - /** The number of 32 bit words */ - readonly #M = 397; - /** Constant Vector A */ - readonly #MATRIX_A = 0x9908b0df; - /** Most significant W-R bits */ - readonly #UPPER_MASK = 0x80000000; - /** Least significant R bits */ - readonly #LOWER_MASK = 0x7fffffff; - /** UPPER_MASK + LOWER_MASK + 1 */ - readonly #TOTAL_MASK = 0x100000000; - /** the array for the state vector */ - #mt = Array.from({ length: 624 }, () => 0); + #mt = ArrayFrom({ length: N }, () => 0); /** mti == N + 1 means mt[N] is not initialized */ - #mti = 625; + #mti = N + 1; /** * Initializes a new instance of the MersenneTwister class. * @param seed - The seed value. */ constructor(seed?: number) { - this.init(seed ?? DateNow() >>> 0); + this.init(seed); } /** @@ -112,19 +112,17 @@ export class MT19937 { * @param seed - The seed value. */ init(seed?: number): this { - seed ??= DateNow() >>> 0; + seed ??= DateNow(); this.#mt[0] = seed >>> 0; const mt = this.#mt; - for (let i = 1; i < this.#N; i++) { + const x = 1812433253, y = 0xffff0000, z = 0x0000ffff; + for (let i = 1; i < N; i++) { const s = mt[i - 1] ^ (mt[i - 1] >>> 30); - let l = (s & 0xffff0000) >>> 16; - l *= 1812433253; - l <<= 16; - let r = s & 0x0000ffff; - r *= 1812433253; + const l = (((s & y) >>> 16) * x) << 16; + const r = (s & z) * x; mt[this.#mti = i] = (l + r + i) >>> 0; } - this.#mti = this.#N; + this.#mti = N; return this; } @@ -136,29 +134,29 @@ export class MT19937 { let i = 1, j = 0; const len = seeds.length; this.init(19650218); - let k = this.#N > len ? this.#N : len; + let k = N > len ? N : len; + const w = 1566083941; + const x = 1664525, y = 0xffff0000, z = 0x0000ffff; for (; k > 0; k--) { const s = this.#mt[i - 1] ^ (this.#mt[i - 1] >>> 30); - const x = 1664525, y = 0xffff0000, z = 0x0000ffff; const u = (s & z) * x; let t = ((s & y) >>> 16) * x << 16; this.#mt[i] = (t = this.#mt[i] ^ t + u, t += seeds[j] + j, t >>> 0); i++, j++; - if (i >= this.#N) { - this.#mt[0] = this.#mt[this.#N - 1]; + if (i >= N) { + this.#mt[0] = this.#mt[N - 1]; i = 1; } if (j >= len) j = 0; } - for (k = this.#N - 1; k > 0; k--) { + for (k = N - 1; k > 0; k--) { const s = this.#mt[i - 1] ^ (this.#mt[i - 1] >>> 30); - this.#mt[i] = ((this.#mt[i] ^ - (((s & 0xffff0000) >>> 16) * 1566083941 << 16) + - (s & 0x0000ffff) * 1566083941) - - i) >>> 0; + let t = this.#mt[i]; + t ^= (((s & y) >>> 16) * w << 16) + (s & z) * w; + this.#mt[i] = (t - i) >>> 0; i++; - if (i >= this.#N) { - this.#mt[0] = this.#mt[this.#N - 1]; + if (i >= N) { + this.#mt[0] = this.#mt[N - 1]; i = 1; } } @@ -173,33 +171,26 @@ export class MT19937 { */ randomInt(): number { let y: number; - const mag01 = [0x0, this.#MATRIX_A]; + const mag01 = [0x0, MATRIX_A]; - if (this.#mti >= this.#N) { + if (this.#mti >= N) { let kk: number; /* a default initial seed is used */ - if (this.#mti === this.#N + 1) this.init(5489); + if (this.#mti === N + 1) this.init(5489); - for (kk = 0; kk < this.#N - this.#M; kk++) { - y = (this.#mt[kk] & this.#UPPER_MASK) | - (this.#mt[kk + 1] & this.#LOWER_MASK); - this.#mt[kk] = this.#mt[kk + this.#M] ^ (y >>> 1) ^ mag01[y & 0x1]; + for (kk = 0; kk < N - M; kk++) { + y = (this.#mt[kk] & UPPER_MASK) | (this.#mt[kk + 1] & LOWER_MASK); + this.#mt[kk] = this.#mt[kk + M] ^ (y >>> 1) ^ mag01[y & 0x1]; } - for (; kk < this.#N - 1; kk++) { - y = (this.#mt[kk] & this.#UPPER_MASK) | - (this.#mt[kk + 1] & this.#LOWER_MASK); - this.#mt[kk] = this.#mt[kk + (this.#M - this.#N)] ^ (y >>> 1) ^ - mag01[y & 0x1]; + for (; kk < N - 1; kk++) { + y = (this.#mt[kk] & UPPER_MASK) | (this.#mt[kk + 1] & LOWER_MASK); + this.#mt[kk] = this.#mt[kk + (M - N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } - y = (this.#mt[this.#N - 1] & this.#UPPER_MASK) | - (this.#mt[0] & this.#LOWER_MASK); - this.#mt[this.#N - 1] = this.#mt[this.#M - 1] ^ - (y >>> 1) ^ - mag01[y & 0x1]; - + y = (this.#mt[N - 1] & UPPER_MASK) | (this.#mt[0] & LOWER_MASK); + this.#mt[N - 1] = this.#mt[M - 1] ^ (y >>> 1) ^ mag01[y & 0x1]; this.#mti = 0; } @@ -219,7 +210,7 @@ export class MT19937 { * @returns A floating-point number between 0 and 1. */ random(): number { - return this.randomInt() / this.#TOTAL_MASK; + return this.randomInt() / TOTAL_MASK; } } From e828473e320ed6489ee2fdccbe2bee261e7b5ae5 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:49:21 -0800 Subject: [PATCH 093/132] fix(float16,float32): use type-only imports for FloatFormat --- src/float16/constants.ts | 2 +- src/float32/constants.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/float16/constants.ts b/src/float16/constants.ts index 31b1f1d..a07ae1d 100644 --- a/src/float16/constants.ts +++ b/src/float16/constants.ts @@ -11,7 +11,7 @@ * @module float16/constants */ -import { FloatFormat } from "../internal/ieee754.ts"; +import type { FloatFormat } from "../internal/ieee754.ts"; /** * Well-known bit pattern representing `NaN` in the IEEE-754 half-precision (or diff --git a/src/float32/constants.ts b/src/float32/constants.ts index 9a72c85..a24cae2 100644 --- a/src/float32/constants.ts +++ b/src/float32/constants.ts @@ -11,7 +11,7 @@ * @module float32/constants */ -import { FloatFormat } from "../internal/ieee754.ts"; +import type { FloatFormat } from "../internal/ieee754.ts"; /** * The number of bits used for the exponent in the IEEE-754 single-precision From 3ee29e20635745f24b8bb32f971504f1bcdbc3e3 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:50:12 -0800 Subject: [PATCH 094/132] fix(ieee754): ensure floating point rounding logic is sound --- src/internal/ieee754.ts | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/internal/ieee754.ts b/src/internal/ieee754.ts index f79b264..e8acfb0 100644 --- a/src/internal/ieee754.ts +++ b/src/internal/ieee754.ts @@ -85,7 +85,7 @@ function inner_encode(value: number, fmt: Format): number | bigint { // subnormal threshold = 2^(1-bias) const cutoff = pow(2, normal); - const sign = value < 0 ? 1n : 0n; + const sign = BigInt(value < 0 ? 1 : 0); const shift = BigInt(fmt.exponent + fmt.mantissa); const absolute = abs(value); if (absolute < cutoff) { @@ -97,10 +97,28 @@ function inner_encode(value: number, fmt: Format): number | bigint { // normal let expo = floor(log2(absolute)), mant = absolute / pow(2, expo); - if (mant < 1) mant *= 2, expo--; + if (mant < 1) { + mant *= 2; + expo--; + } else if (mant >= 2) { + mant /= 2; + expo++; + } + + const mant_scale = pow(2, fmt.mantissa); + let mant_bits = round((mant - 1) * mant_scale); + if (mant_bits === mant_scale) { + mant_bits = 0; + expo++; + } + + const biased = expo + fmt.bias; + if (biased >= (1 << fmt.exponent) - 1) { + return value < 0 ? fmt.negative_infinity : fmt.positive_infinity; + } - const e = BigInt(expo + fmt.bias); - const m = BigInt(round((mant - 1) * pow(2, fmt.mantissa))); + const e = BigInt(biased); + const m = BigInt(mant_bits); return (sign << shift) | (e << BigInt(fmt.mantissa)) | m; } From b03dbd3dfa1ab8fe9db8491a0a3eb1858e580791 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:50:41 -0800 Subject: [PATCH 095/132] chore: update license --- LICENSE | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/LICENSE b/LICENSE index fd78223..e45bc90 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,6 @@ -The MIT License (MIT) +# The MIT License (MIT) -Copyright © 2024+ Nicholas Berlette (https://github.com/nberlette). All rights -reserved. +Copyright (c) 2024-2026 Nicholas Berlette. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in From 274186d82b1cf1d27a3bf4f0c86417f9336bb91e Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:51:16 -0800 Subject: [PATCH 096/132] docs(readme): improve doctests, use node:assert --- README.md | 188 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 124 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index 7edb064..b789e57 100644 --- a/README.md +++ b/README.md @@ -52,12 +52,13 @@ npx jsr add @nick/math ```ts import * as math from "@nick/math"; +import assert from "node:assert"; -console.assert(math.abs(-1) === 1); -console.assert(math.acos(0.5) === 1.0471975511965979); -console.assert(math.acosh(1) === 0); -console.assert(math.log(9) === 2.1972245773362196); -console.assert(math.PI === 3.141592653589793); +assert.ok(Math.abs(math.abs(-1) - 1) < 1e-9); +assert.ok(Math.abs(math.acos(0.5) - 1.0471975511965979) < 1e-9); +assert.ok(Math.abs(math.acosh(1) - 0) < 1e-9); +assert.ok(Math.abs(math.log(9) - 2.1972245773362196) < 1e-9); +assert.ok(Math.abs(math.PI - 3.141592653589793) < 1e-9); ``` ```ts @@ -147,8 +148,9 @@ import { log } from "@nick/math/log"; ```ts import { E } from "@nick/math/constants/e"; +import assert from "node:assert"; -console.assert(E === 2.718281828459045); +assert.ok(E === 2.718281828459045); ``` ##### Type-Level Usage @@ -165,8 +167,9 @@ function assertEulersNumber(e: number): asserts e is E { ```ts import { LN10 } from "@nick/math/constants/ln10"; +import assert from "node:assert"; -console.assert(LN10 === 2.302585092994046); +assert.ok(LN10 === 2.302585092994046); ``` ##### Type-Level Usage @@ -183,8 +186,9 @@ function assertNaturalLogarithmOf10(ln10: number): asserts ln10 is LN10 { ```ts import { LN2 } from "@nick/math/constants/ln2"; +import assert from "node:assert"; -console.assert(LN2 === 0.6931471805599453); +assert.ok(LN2 === 0.6931471805599453); ``` ##### Type-Level Usage @@ -201,8 +205,9 @@ function assertNaturalLogarithmOf2(ln2: number): asserts ln2 is LN2 { ```ts import { LOG2E } from "@nick/math/constants/log2e"; +import assert from "node:assert"; -console.assert(LOG2E === 1.4426950408889634); +assert.ok(LOG2E === 1.4426950408889634); ``` ##### Type-Level Usage @@ -219,8 +224,9 @@ function assertBase2LogarithmOfE(log2e: number): asserts log2e is LOG2E { ```ts import { LOG10E } from "@nick/math/constants/log10e"; +import assert from "node:assert"; -console.assert(LOG10E === 0.4342944819032518); +assert.ok(LOG10E === 0.4342944819032518); ``` ##### Type-Level Usage @@ -239,8 +245,9 @@ function assertBase10LogarithmOfE(log10e: number): asserts log10e is LOG10E { ```ts import { PI } from "@nick/math/constants/pi"; +import assert from "node:assert"; -console.assert(PI === 3.141592653589793); +assert.ok(PI === 3.141592653589793); ``` ##### Type-Level Usage @@ -257,8 +264,9 @@ function assertPi(pi: number): asserts pi is PI { ```ts import { SQRT1_2 } from "@nick/math/constants/sqrt1_2"; +import assert from "node:assert"; -console.assert(SQRT1_2 === 0.7071067811865476); +assert.ok(SQRT1_2 === 0.7071067811865476); ``` ##### Type-Level Usage @@ -279,8 +287,9 @@ function assertSquareRootOfOneHalf( ```ts import { SQRT2 } from "@nick/math/constants/sqrt2"; +import assert from "node:assert"; -console.assert(SQRT2 === 1.4142135623730951); +assert.ok(SQRT2 === 1.4142135623730951); ``` ##### Type-Level Usage @@ -300,8 +309,9 @@ different from `1`. ```ts import { EPSILON } from "@nick/math/constants/epsilon"; +import assert from "node:assert"; -console.assert(EPSILON === 2.220446049250313e-16); +assert.ok(EPSILON === 2.220446049250313e-16); ``` ##### Type-Level Usage @@ -322,8 +332,9 @@ The maximum safe integer in JavaScript, `2^53 - 1`. ```ts import { MAX_SAFE_INTEGER } from "@nick/math/constants/max-safe-integer"; +import assert from "node:assert"; -console.assert(MAX_SAFE_INTEGER === 9007199254740991); +assert.ok(MAX_SAFE_INTEGER === 9007199254740991); ``` ##### Type-Level Usage @@ -346,8 +357,9 @@ The minimum safe integer in JavaScript, `-2^53 + 1`. ```ts import { MIN_SAFE_INTEGER } from "@nick/math/constants/min-safe-integer"; +import assert from "node:assert"; -console.assert(MIN_SAFE_INTEGER === -9007199254740991); +assert.ok(MIN_SAFE_INTEGER === -9007199254740991); ``` ##### Type-Level Usage @@ -370,8 +382,9 @@ The maximum representable value in JavaScript. ```ts import { MAX_VALUE } from "@nick/math/constants/max-value"; +import assert from "node:assert"; -console.assert(MAX_VALUE === 1.7976931348623157e308); +assert.ok(MAX_VALUE === 1.7976931348623157e308); ``` ##### Type-Level Usage @@ -392,8 +405,9 @@ The minimum representable value in JavaScript. ```ts import { MIN_VALUE } from "@nick/math/constants/min-value"; +import assert from "node:assert"; -console.assert(MIN_VALUE === 5e-324); +assert.ok(MIN_VALUE === 5e-324); ``` ##### Type-Level Usage @@ -414,8 +428,9 @@ The negative infinity value in JavaScript. ```ts import { NEGATIVE_INFINITY } from "@nick/math/constants/negative-infinity"; +import assert from "node:assert"; -console.assert(NEGATIVE_INFINITY === -Infinity); +assert.ok(NEGATIVE_INFINITY === -Infinity); ``` ##### Type-Level Usage @@ -440,8 +455,9 @@ The positive infinity value in JavaScript. ```ts import { POSITIVE_INFINITY } from "@nick/math/constants/positive-infinity"; +import assert from "node:assert"; -console.assert(POSITIVE_INFINITY === Infinity); +assert.ok(POSITIVE_INFINITY === Infinity); ``` ##### Type-Level Usage @@ -481,7 +497,7 @@ console.log(NaN); // NaN import { NaN } from "@nick/math/constants/nan"; function assertNaN(nan: number): asserts nan is NaN { - if (nan !== nan) throw new TypeError(`Expected ${NaN}, got ${nan}`); + if (!Number.isNaN(nan)) throw new TypeError(`Expected ${NaN}, got ${nan}`); } ``` @@ -495,8 +511,9 @@ Returns the absolute value of a number. ```ts import { abs } from "@nick/math/abs"; +import assert from "node:assert"; -console.assert(abs(-1) === 1); +assert.ok(abs(-1) === 1); ``` #### `acos` @@ -505,8 +522,9 @@ Returns the arccosine of a number. ```ts import { acos } from "@nick/math/acos"; +import assert from "node:assert"; -console.assert(acos(0.5) === 1.0471975511965979); +assert.ok(Math.abs(acos(0.5) - 1.0471975511965979) < 1e-9); ``` #### `acosh` @@ -515,8 +533,9 @@ Returns the inverse hyperbolic cosine of a number. ```ts import { acosh } from "@nick/math/acosh"; +import assert from "node:assert"; -console.assert(acosh(1) === 0); +assert.ok(acosh(1) === 0); ``` #### `asin` @@ -525,8 +544,9 @@ Returns the arcsine of a number. ```ts import { asin } from "@nick/math/asin"; +import assert from "node:assert"; -console.assert(asin(0.5) === 0.5235987755982989); +assert.ok(Math.abs(asin(0.5) - 0.5235987755982989) < 1e-9); ``` #### `asinh` @@ -535,8 +555,9 @@ Returns the inverse hyperbolic sine of a number. ```ts import { asinh } from "@nick/math/asinh"; +import assert from "node:assert"; -console.assert(asinh(0.5) === 0.48121182505960347); +assert.ok(Math.abs(asinh(0.5) - 0.48121182505960347) < 1e-9); ``` #### `atan` @@ -545,8 +566,9 @@ Returns the arctangent of a number. ```ts import { atan } from "@nick/math/atan"; +import assert from "node:assert"; -console.assert(atan(0.5) === 0.4636476090008061); +assert.ok(Math.abs(atan(0.5) - 0.4636476090008061) < 1e-9); ``` #### `atan2` @@ -555,8 +577,9 @@ Returns the arctangent of the quotient of its arguments. ```ts import { atan2 } from "@nick/math/atan2"; +import assert from "node:assert"; -console.assert(atan2(1, 1) === 0.7853981633974483); +assert.ok(atan2(1, 1) === 0.7853981633974483); ``` #### `atanh` @@ -565,8 +588,9 @@ Returns the inverse hyperbolic tangent of a number. ```ts import { atanh } from "@nick/math/atanh"; +import assert from "node:assert"; -console.assert(atanh(0.5) === 0.5493061443340549); +assert.ok(atanh(0.5) === 0.5493061443340549); ``` #### `cbrt` @@ -575,8 +599,9 @@ Returns the cube root of a number. ```ts import { cbrt } from "@nick/math/cbrt"; +import assert from "node:assert"; -console.assert(cbrt(27) === 3); +assert.ok(cbrt(27) === 3); ``` #### `ceil` @@ -585,8 +610,9 @@ Returns the smallest integer greater than or equal to a number. ```ts import { ceil } from "@nick/math/ceil"; +import assert from "node:assert"; -console.assert(ceil(1.5) === 2); +assert.ok(ceil(1.5) === 2); ``` #### `clz32` @@ -596,8 +622,9 @@ number. ```ts import { clz32 } from "@nick/math/clz32"; +import assert from "node:assert"; -console.assert(clz32(1) === 31); +assert.ok(clz32(1) === 31); ``` #### `cos` @@ -606,8 +633,9 @@ Returns the cosine of a number. ```ts import { cos } from "@nick/math/cos"; +import assert from "node:assert"; -console.assert(cos(0.5) === 0.8775825618903728); +assert.ok(Math.abs(cos(0.5) - 0.8775825618903728) < 1e-9); ``` #### `cosh` @@ -616,8 +644,9 @@ Returns the hyperbolic cosine of a number. ```ts import { cosh } from "@nick/math/cosh"; +import assert from "node:assert"; -console.assert(cosh(0.5) === 1.1276259652063807); +assert.ok(Math.abs(cosh(0.5) - 1.1276259652063807) < 1e-9); ``` #### `exp` @@ -626,8 +655,9 @@ Returns `E` raised to the power of a number. ```ts import { exp } from "@nick/math/exp"; +import assert from "node:assert"; -console.assert(exp(1) === 2.718281828459045); +assert.ok(Math.abs(exp(1) - 2.718281828459045) < 1e-9); ``` #### `expm1` @@ -636,8 +666,9 @@ Returns `E` raised to the power of a number, minus `1`. ```ts import { expm1 } from "@nick/math/expm1"; +import assert from "node:assert"; -console.assert(expm1(1) === 1.718281828459045); +assert.ok(Math.abs(expm1(1) - 1.718281828459045) < 1e-9); ``` #### `floor` @@ -646,8 +677,9 @@ Returns the largest integer less than or equal to a number. ```ts import { floor } from "@nick/math/floor"; +import assert from "node:assert"; -console.assert(floor(1.5) === 1); +assert.ok(floor(1.5) === 1); ``` #### `fround` @@ -672,8 +704,9 @@ standard. Introduced by the [TC39 Proposal for Float16Array]. ```ts import { f16round } from "@nick/math/f16round"; import { PI } from "@nick/math/constants/pi"; +import assert from "node:assert"; -console.assert(f16round(PI) === 3.140625); +assert.ok(f16round(PI) === 3.140625); ``` #### `hypot` @@ -682,8 +715,9 @@ Returns the square root of the sum of the squares of its arguments. ```ts import { hypot } from "@nick/math/hypot"; +import assert from "node:assert"; -console.assert(hypot(3, 4) === 5); +assert.ok(hypot(3, 4) === 5); ``` #### `imul` @@ -692,8 +726,9 @@ Returns the result of a 32-bit integer multiplication. ```ts import { imul } from "@nick/math/imul"; +import assert from "node:assert"; -console.assert(imul(2, 3) === 6); +assert.ok(imul(2, 3) === 6); ``` #### `log` @@ -702,8 +737,9 @@ Returns the natural logarithm of a number. ```ts import { log } from "@nick/math/log"; +import assert from "node:assert"; -console.assert(log(9) === 2.1972245773362196); +assert.ok(Math.abs(log(9) - 2.1972245773362196) < 1e-9); ``` #### `log1p` @@ -712,8 +748,9 @@ Returns the natural logarithm of `1` plus a number. ```ts import { log1p } from "@nick/math/log1p"; +import assert from "node:assert"; -console.assert(log1p(9) === 2.302585092994046); +assert.ok(Math.abs(log1p(9) - 2.302585092994046) < 1e-9); ``` #### `log10` @@ -722,8 +759,9 @@ Returns the base 10 logarithm of a number. ```ts import { log10 } from "@nick/math/log10"; +import assert from "node:assert"; -console.assert(log10(100) === 2); +assert.ok(Math.abs(log10(100) - 2) < 1e-9); ``` #### `log2` @@ -732,8 +770,9 @@ Returns the base 2 logarithm of a number. ```ts import { log2 } from "@nick/math/log2"; +import assert from "node:assert"; -console.assert(log2(8) === 3); +assert.ok(Math.abs(log2(8) - 3) < 1e-9); ``` #### `max` @@ -742,8 +781,9 @@ Returns the largest of zero or more numbers. ```ts import { max } from "@nick/math/max"; +import assert from "node:assert"; -console.assert(max(1, 2, 3) === 3); +assert.ok(max(1, 2, 3) === 3); ``` #### `min` @@ -752,8 +792,9 @@ Returns the smallest of zero or more numbers. ```ts import { min } from "@nick/math/min"; +import assert from "node:assert"; -console.assert(min(1, 2, 3) === 1); +assert.ok(min(1, 2, 3) === 1); ``` #### `pow` @@ -762,8 +803,9 @@ Returns the base to the exponent power. ```ts import { pow } from "@nick/math/pow"; +import assert from "node:assert"; -console.assert(pow(2, 3) === 8); +assert.ok(pow(2, 3) === 8); ``` #### `random` @@ -772,8 +814,11 @@ Returns a pseudo-random number between `0` and `1`. ```ts import { random } from "@nick/math/random"; +import assert from "node:assert"; -console.assert(random() >= 0 && random() < 1); +const value = random(); + +assert.ok(value >= 0 && value < 1); ``` #### `round` @@ -782,8 +827,9 @@ Returns the value of a number rounded to the nearest integer. ```ts import { round } from "@nick/math/round"; +import assert from "node:assert"; -console.assert(round(1.5) === 2); +assert.ok(round(1.5) === 2); ``` #### `sign` @@ -793,8 +839,9 @@ zero. ```ts import { sign } from "@nick/math/sign"; +import assert from "node:assert"; -console.assert(sign(-1) === -1); +assert.ok(sign(-1) === -1); ``` #### `sin` @@ -803,8 +850,9 @@ Returns the sine of a number. ```ts import { sin } from "@nick/math/sin"; +import assert from "node:assert"; -console.assert(sin(0.5) === 0.479425538604203); +assert.ok(Math.abs(sin(0.5) - 0.479425538604203) < 1e-9); ``` #### `sinh` @@ -813,8 +861,9 @@ Returns the hyperbolic sine of a number. ```ts import { sinh } from "@nick/math/sinh"; +import assert from "node:assert"; -console.assert(sinh(0.5) === 0.5210953054937474); +assert.ok(Math.abs(sinh(0.5) - 0.5210953054937474) < 1e-9); ``` #### `sqrt` @@ -823,8 +872,9 @@ Returns the square root of a number. ```ts import { sqrt } from "@nick/math/sqrt"; +import assert from "node:assert"; -console.assert(sqrt(9) === 3); +assert.ok(sqrt(9) === 3); ``` #### `tan` @@ -833,8 +883,9 @@ Returns the tangent of a number. ```ts import { tan } from "@nick/math/tan"; +import assert from "node:assert"; -console.assert(tan(0.5) === 0.5463024898437905); +assert.ok(Math.abs(tan(0.5) - 0.5463024898437905) < 1e-9); ``` #### `tanh` @@ -843,8 +894,9 @@ Returns the hyperbolic tangent of a number. ```ts import { tanh } from "@nick/math/tanh"; +import assert from "node:assert"; -console.assert(tanh(0.5) === 0.46211715726000974); +assert.ok(Math.abs(tanh(0.5) - 0.46211715726000974) < 1e-9); ``` #### `trunc` @@ -853,8 +905,9 @@ Returns the integer part of a number by removing any fractional digits. ```ts import { trunc } from "@nick/math/trunc"; +import assert from "node:assert"; -console.assert(trunc(1.5) === 1); +assert.ok(trunc(1.5) === 1); ``` --- @@ -867,8 +920,9 @@ Determines whether a number is finite. ```ts import { isFinite } from "@nick/math/is/finite"; +import assert from "node:assert"; -console.assert(isFinite(1)); +assert.ok(isFinite(1)); ``` #### `isInteger` @@ -877,8 +931,9 @@ Determines whether a number is an integer. ```ts import { isInteger } from "@nick/math/is/integer"; +import assert from "node:assert"; -console.assert(isInteger(1)); +assert.ok(isInteger(1)); ``` #### `isNaN` @@ -887,8 +942,9 @@ Determines whether a value is `NaN`. ```ts import { isNaN } from "@nick/math/is/nan"; +import assert from "node:assert"; -console.assert(isNaN(NaN)); +assert.ok(isNaN(NaN)); ``` #### `isSafeInteger` @@ -897,8 +953,9 @@ Determines whether a number is a safe integer. ```ts import { isSafeInteger } from "@nick/math/is/safe-integer"; +import assert from "node:assert"; -console.assert(isSafeInteger(1)); +assert.ok(isSafeInteger(1)); ``` #### `isNegativeZero` @@ -907,9 +964,10 @@ Determines whether a number is `-0`. ```ts import { isNegativeZero } from "@nick/math/is/negative-zero"; +import assert from "node:assert"; -console.assert(isNegativeZero(-0)); -console.assert(!isNegativeZero(0)); +assert.ok(isNegativeZero(-0)); +assert.ok(!isNegativeZero(0)); ``` #### `isPositiveInfinity` @@ -918,8 +976,9 @@ Determines whether a number is positive infinity. ```ts import { isPositiveInfinity } from "@nick/math/is/positive-infinity"; +import assert from "node:assert"; -console.assert(isPositiveInfinity(Infinity)); +assert.ok(isPositiveInfinity(Infinity)); ``` #### `isNegativeInfinity` @@ -928,8 +987,9 @@ Determines whether a number is negative infinity. ```ts import { isNegativeInfinity } from "@nick/math/is/negative-infinity"; +import assert from "node:assert"; -console.assert(isNegativeInfinity(-Infinity)); +assert.ok(isNegativeInfinity(-Infinity)); ``` --- From 2e5c89d2aa07c5cdfe1823fa9603d270ca5cd4d0 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:52:00 -0800 Subject: [PATCH 097/132] config: rewrite CI workflow for npm trusted publishing --- .github/workflows/ci.yml | 111 +++++++++++++++++++++++++++++++++++---- 1 file changed, 102 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b5b3851..35e88f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,26 +8,119 @@ on: pull_request: branches: - main - + workflow_dispatch: + inputs: + check: + type: boolean + description: "Run lint, fmt, and test?" + required: false + default: true + publish-jsr: + type: boolean + description: "Publish to JSR?" + required: false + default: false + publish-npm: + type: boolean + description: "Publish to NPM?" + required: false + default: false + publish-gpr: + type: boolean + description: "Publish to GPR?" + required: false + default: false jobs: check: + if: github.event.inputs.check == 'true' || github.event_name != 'workflow_dispatch' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: denoland/setup-deno@v2 with: deno-version: v2.x - - run: deno test -A --permit-no-files --parallel --no-check=remote - - run: deno fmt --check - - run: deno lint - + - id: ok + run: deno task ok + - id: coverage + uses: actions/upload-artifact@v6 + with: + path: .coverage + name: nberlette-math-coverage_${{ github.ref_name }}-${{ github.sha }} publish: + if: | + (github.event_name == 'push' && + startsWith(github.ref, 'refs/tags/') && + needs.check.result == 'success') || + (github.event_name == 'workflow_dispatch' && ( + github.event.inputs.publish-jsr == 'true' || + github.event.inputs.publish-npm == 'true' || + github.event.inputs.publish-gpr == 'true' + ) && (needs.check.result == 'success' || github.event.inputs.check == 'false')) runs-on: ubuntu-latest needs: check permissions: contents: read id-token: write - if: ((github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))) + packages: write + concurrency: + cancel-in-progress: true + group: publish-${{ github.ref_name }} steps: - - uses: actions/checkout@v4 - - run: npx jsr publish + - uses: actions/checkout@v6 + - name: "setup deno" + uses: denoland/setup-deno@v2 + with: + deno-version: v2.x + - if: | + (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || + (github.event_name == 'workflow_dispatch' && github.event.inputs.publish-jsr == 'true') + name: "publish to jsr" + run: deno publish + - if: | + (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || + (github.event_name == 'workflow_dispatch' && github.event.inputs.publish-npm == 'true') + name: "setup node for npm" + uses: actions/setup-node@v6 + with: + node-version: 24 + registry-url: "https://registry.npmjs.org" + - id: build + if: | + (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || + (github.event_name == 'workflow_dispatch' && (github.event.inputs.publish-npm == 'true' || + github.event.inputs.publish-gpr == 'true')) + name: "build for npm" + run: deno task build + env: + NO_PUBLISH: 1 + - id: artifact + if: steps.build.outcome == 'success' + uses: actions/upload-artifact@v5 + with: + path: npm + name: nberlette-math-npm_${{ github.ref_name }}-${{ github.sha }} + - if: | + (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || + (github.event_name == 'workflow_dispatch' && github.event.inputs.publish-npm == 'true') + name: "publish to npm" + run: npm publish --access public + working-directory: npm + - if: | + (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || + (github.event_name == 'workflow_dispatch' && github.event.inputs.publish-gpr == 'true') + name: "setup node for gpr" + uses: actions/setup-node@v6 + with: + node-version: 24 + registry-url: "https://npm.pkg.github.com" + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - if: | + (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || + (github.event_name == 'workflow_dispatch' && github.event.inputs.publish-gpr == 'true') + name: "publish to gpr" + env: + NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.GITHUB_TOKEN }} + working-directory: npm + run: npm publish --access public --registry https://npm.pkg.github.com From 2c4e95273f6c60a7c2298b06cc7674374cb4274f Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:52:50 -0800 Subject: [PATCH 098/132] fix(constants): ensure negative-zero module is exported --- src/constants/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/constants/index.ts b/src/constants/index.ts index 4a6d606..787a4cd 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -15,6 +15,7 @@ export * from "./max_value.ts"; export * from "./min_safe_integer.ts"; export * from "./min_value.ts"; export * from "./nan.ts"; +export * from "./negative_zero.ts"; export * from "./pi.ts"; export * from "./positive_zero.ts"; export * from "./sqrt1_2.ts"; From 4213810a6120f3f865f2215aa0a2d270924b578b Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:53:30 -0800 Subject: [PATCH 099/132] tests: fix doctest error in src/index.ts --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 883d710..df9cfd3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,7 +20,7 @@ * // ...and even those from globalThis.Number * assert.strictEqual(math.EPSILON, Number.EPSILON); * assert.strictEqual(math.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); - * assert.notStrictEqual(math.NaN, Number.NaN); // NaN !== NaN (like, ever) + * assert.strictEqual(math.NaN, Number.NaN); * // ... * assert.strictEqual(math.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER); * From d8b588e4f0e3ac0f4811d9fc3dd576d27487de7b Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:54:31 -0800 Subject: [PATCH 100/132] config: update deno.json tasks and settings --- deno.json | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/deno.json b/deno.json index 2f8ec48..c932a1c 100644 --- a/deno.json +++ b/deno.json @@ -7,6 +7,14 @@ "email": "nick@berlette.com", "url": "https://github.com/nberlette/math" }, + "lock": true, + "nodeModulesDir": "auto", + "tasks": { + "build": "deno run -Aq scripts/build.ts", + "test": "deno test -A --no-check=remote --coverage=.coverage --clean --parallel --doc", + "ok": "deno fmt --check && deno lint src && deno run test", + "fix": "deno fmt && deno lint --fix src" + }, "exports": { ".": "./src/index.ts", "./abs": "./src/abs.ts", @@ -127,11 +135,8 @@ "tags": ["recommended"] } }, - "tasks": { - "bench": "./scripts/benchmark.ts", - "test": "deno test -A --no-check=remote --coverage=.coverage --clean --parallel --doc --permit-no-files", - "ok": "deno fmt --check && deno lint src && deno run test", - "fix": "deno fmt && deno lint --fix src" + "fmt": { + "exclude": ["docs", "**/*.min.*"] }, "publish": { "include": [ From 5c7d05ebe531342d170bdbc86e2d27b8fd45e383 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:57:53 -0800 Subject: [PATCH 101/132] fix(abs): ensure abs behaves like Math.abs --- src/abs.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/abs.ts b/src/abs.ts index 42520a3..9115009 100644 --- a/src/abs.ts +++ b/src/abs.ts @@ -12,5 +12,7 @@ * @category Arithmetic */ export function abs(x: number): number { - return (x = +x) < 0 ? -x : x; + x = +x; + if (x === 0) return 0; + return x < 0 ? -x : x; } From 9603b7d7401d5fc7e107cbcf3854f2b00f84661d Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:57:54 -0800 Subject: [PATCH 102/132] fix(asinh): ensure asinh behaves like Math.asinh --- src/asinh.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/asinh.ts b/src/asinh.ts index b1b58fc..1d0a4cf 100644 --- a/src/asinh.ts +++ b/src/asinh.ts @@ -15,6 +15,7 @@ import { sqrt } from "./sqrt.ts"; * @category Trigonometry */ export function asinh(x: number): number { + if (x === 0) return x; if (!isFinite(x)) return x; return log(x + sqrt(x * x + 1)); } From 623e4fd2d132223daaba96d278d761b3e846b0ba Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:57:55 -0800 Subject: [PATCH 103/132] fix(atan): ensure atan behaves like Math.atan --- src/atan.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/atan.ts b/src/atan.ts index 8bc551e..7a68876 100644 --- a/src/atan.ts +++ b/src/atan.ts @@ -41,12 +41,12 @@ export function atan(x: number): number { // floating-point numbers const MAX_ITERATIONS = 1000; while (abs(term) > EPSILON && n < MAX_ITERATIONS) { - term *= a2; + term *= -a2; sum += term / (2 * n + 1); n++; } - return PI_OVER_4 + 2 * sum; + return PI_OVER_4 + sum; } // for x <= 0.5, use the standard Taylor series expansion From 567ce93cfd772f0d0de3a20b5f498d78289de6ff Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:57:57 -0800 Subject: [PATCH 104/132] fix(atan2): ensure atan2 behaves like Math.atan2 --- src/atan2.ts | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/atan2.ts b/src/atan2.ts index d2da9bc..f09031c 100644 --- a/src/atan2.ts +++ b/src/atan2.ts @@ -6,12 +6,15 @@ */ import { NAN } from "./constants/nan.ts"; import { PI } from "./constants/pi.ts"; -import { isFinite } from "./guards/finite.ts"; import { atan } from "./atan.ts"; +import { isNaN } from "./guards/nan.ts"; +import { isFinite } from "./guards/finite.ts"; import { isNegativeZero } from "./guards/negative_zero.ts"; import { isNegativeInfinity } from "./guards/negative_infinity.ts"; import { isPositiveInfinity } from "./guards/positive_infinity.ts"; +const PI_OVER_2 = PI / 2, PI_OVER_4 = PI / 4; + /** * Calculates the arctangent of the quotient of its arguments, `y / x`, * returning a value in the range `(-π, π]`. @@ -25,35 +28,38 @@ import { isPositiveInfinity } from "./guards/positive_infinity.ts"; export function atan2(y: number, x: number): number { // fast paths for special cases if (isNaN(y) || isNaN(x)) return NAN; - if (y === 0 && x === 0) return y; // preserve sign of y for -0 - const PI_OVER_2 = PI / 2, PI_OVER_4 = PI / 4; - // x is zero + if (y === 0 && x === 0) { + const sign = isNegativeZero(y) ? -1 : 1; + return (isNegativeZero(x) ? PI : 0) * sign; + } if (x === 0) { if (y > 0) return PI_OVER_2; if (y < 0) return -PI_OVER_2; - // y is zero, x is zero - return NAN; // undefined, per IEEE standards + return NAN; // unreachable } // x (and possibly y) is infinity/-infinity if (isPositiveInfinity(x)) { if (isPositiveInfinity(y)) return PI_OVER_4; if (isNegativeInfinity(y)) return -PI_OVER_4; - return PI_OVER_2; + return y < 0 || isNegativeZero(y) ? -0 : 0; } else if (isNegativeInfinity(x)) { if (isPositiveInfinity(y)) return 3 * PI_OVER_4; if (isNegativeInfinity(y)) return -3 * PI_OVER_4; - return -PI_OVER_2; + // deno-coverage-ignore-start + return y < 0 || isNegativeZero(y) ? -PI : PI; } else if (isFinite(x) && !isFinite(y)) { return y > 0 ? PI_OVER_2 : -PI_OVER_2; } else if (!isFinite(x) && isFinite(y)) { // preserve the sign of y for -0 if (x > 0) return isNegativeZero(y) || y < 0 ? -0 : 0; - return y >= 0 && !isNegativeZero(y) ? PI : -PI; + return y < 0 || isNegativeZero(y) ? -PI : PI; } + // deno-coverage-ignore-stop if (x > 0) return atan(y / x); - if (x < 0) return atan(y / x) + (y >= 0 && !isNegativeZero(y) ? PI : -PI); + if (x < 0) return atan(y / x) + (y < 0 || isNegativeZero(y) ? -PI : PI); + // deno-coverage-ignore return NAN; // this should never happen } From 4d8cbfc9dd7801378020c9c5516cf70f04764eb6 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:57:58 -0800 Subject: [PATCH 105/132] fix(cbrt): ensure cbrt behaves like Math.cbrt --- src/cbrt.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cbrt.ts b/src/cbrt.ts index b570f22..f5510bf 100644 --- a/src/cbrt.ts +++ b/src/cbrt.ts @@ -15,7 +15,7 @@ import { log } from "./log.ts"; * @category Arithmetic */ export function cbrt(x: number): number { - if (x === 0) return 0; + if (x === 0) return x; const absX = abs(x); const result = exp(log(absX) / 3); return x < 0 ? -result : result; From c3c3c273205d047b196f4b4873f02759f7ea461d Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:57:59 -0800 Subject: [PATCH 106/132] fix(ceil): ensure ceil behaves like Math.ceil --- src/ceil.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/ceil.ts b/src/ceil.ts index c83b637..3160479 100644 --- a/src/ceil.ts +++ b/src/ceil.ts @@ -4,7 +4,8 @@ * @module ceil */ -import { floor } from "./floor.ts"; +import { NEGATIVE_INFINITY } from "./constants/negative_infinity.ts"; +import { POSITIVE_INFINITY } from "./constants/positive_infinity.ts"; /** * Performant local implementation of the `Math.ceil` function. @@ -15,5 +16,12 @@ import { floor } from "./floor.ts"; * @tags rounding, ceiling */ export function ceil(x: number): number { - return (x = +x) < 0 ? -floor(-x) : x % 1 ? x - x % 1 + 1 : x; + x = +x; + if (x !== x || x === POSITIVE_INFINITY || x === NEGATIVE_INFINITY) return x; + if (x === 0) return x; + const remainder = x % 1; + if (remainder === 0) return x; + if (x < 0 && x > -1) return -0; + if (x > 0) return x - remainder + 1; + return x - remainder; } From a268b9e4124f8bbb656db75a42288ff0fea6ceab Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:58:01 -0800 Subject: [PATCH 107/132] fix(clz32): ensure clz32 behaves like Math.clz32 --- src/clz32.ts | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/clz32.ts b/src/clz32.ts index 1d4a1c6..d2326b2 100644 --- a/src/clz32.ts +++ b/src/clz32.ts @@ -5,8 +5,6 @@ * * @module clz32 */ -import { LOG2E } from "./constants/log2e.ts"; -import { log } from "./log.ts"; /** * Performant local implementation of the `Math.clz32` function, which counts @@ -20,6 +18,28 @@ import { log } from "./log.ts"; * @tags clz32 */ export function clz32(x: number): number { - x = (x | 0) >>> 0; - return x ? 31 - (log(x) * LOG2E | 0) : 32; + x >>>= 0; + if (x === 0) return 32; + + let count = 0; + if ((x & 0xFFFF0000) === 0) { + count += 16; + x <<= 16; + } + if ((x & 0xFF000000) === 0) { + count += 8; + x <<= 8; + } + if ((x & 0xF0000000) === 0) { + count += 4; + x <<= 4; + } + if ((x & 0xC0000000) === 0) { + count += 2; + x <<= 2; + } + if ((x & 0x80000000) === 0) { + count += 1; + } + return count; } From d57524b07e3e62343cc7c0d247434fc881f1fcfd Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:58:02 -0800 Subject: [PATCH 108/132] fix(floor): ensure floor behaves like Math.floor --- src/floor.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/floor.ts b/src/floor.ts index e3eef39..c29a1e8 100644 --- a/src/floor.ts +++ b/src/floor.ts @@ -4,7 +4,8 @@ * @category Arithmetic * @module floor */ -import { ceil } from "./ceil.ts"; +import { NEGATIVE_INFINITY } from "./constants/negative_infinity.ts"; +import { POSITIVE_INFINITY } from "./constants/positive_infinity.ts"; /** * Performant local implementation of the `Math.floor` function. @@ -15,5 +16,11 @@ import { ceil } from "./ceil.ts"; * @tags rounding, floor */ export function floor(x: number): number { - return (x = +x) < 0 ? -ceil(-x) : x - x % 1; + x = +x; + if (x !== x || x === POSITIVE_INFINITY || x === NEGATIVE_INFINITY) return x; + if (x === 0) return x; + const remainder = x % 1; + if (remainder === 0) return x; + const truncated = x - remainder; + return x < 0 ? truncated - 1 : truncated; } From f0735a37016eb4af69c49c7a2badca5c9fd67fa2 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:58:04 -0800 Subject: [PATCH 109/132] fix(hypot): ensure hypot behaves like Math.hypot --- src/hypot.ts | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/hypot.ts b/src/hypot.ts index dadde0f..b1ef693 100644 --- a/src/hypot.ts +++ b/src/hypot.ts @@ -9,7 +9,6 @@ */ import { abs } from "./abs.ts"; import { sqrt } from "./sqrt.ts"; -import { max } from "./max.ts"; /** * Calculates the hypotenuse value using the Pythagorean theorem, which is the @@ -29,7 +28,26 @@ import { max } from "./max.ts"; */ export function hypot(...values: number[]): number { if (values.length === 0) return 0; - const maximum = max(...values.map(abs)); + let hasInfinity = false; + let hasNaN = false; + let maximum = 0; + + for (const value of values) { + if (value !== value) { + hasNaN = true; + continue; + } + if (value === Infinity || value === -Infinity) { + hasInfinity = true; + continue; + } + const magnitude = abs(value); + if (magnitude > maximum) maximum = magnitude; + } + + if (hasInfinity) return Infinity; + if (hasNaN) return NaN; + if (maximum === 0) return 0; let sum = 0; for (const value of values) { From fb9e145e4280efedbb680f157cbc150ee10823eb Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:58:05 -0800 Subject: [PATCH 110/132] fix(min): ensure min behaves like Math.min --- src/min.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/min.ts b/src/min.ts index 76349a0..8eb7a4b 100644 --- a/src/min.ts +++ b/src/min.ts @@ -5,6 +5,7 @@ * @module min */ import { POSITIVE_INFINITY } from "./constants/positive_infinity.ts"; +import { isNegativeZero } from "./guards/negative_zero.ts"; /** * Returns the smallest of its arguments, or `NaN` if any argument is `NaN`. @@ -19,7 +20,13 @@ export function min(...numbers: number[]): number { for (let i = 0; i < numbers.length; i++) { const number = numbers[i]; if (number !== number) return number; - if (number < result) result = number; + if (number < result) { + result = number; + continue; + } + if (number === 0 && result === 0 && isNegativeZero(number)) { + result = number; + } } return result; } From ede680334c81ec548638c5db129c5aa1c1f2fa51 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:58:06 -0800 Subject: [PATCH 111/132] fix(round): ensure round behaves like Math.round --- src/round.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/round.ts b/src/round.ts index 6094a6d..e487f4c 100644 --- a/src/round.ts +++ b/src/round.ts @@ -3,6 +3,7 @@ * * @module round */ +import { floor } from "./floor.ts"; /** * Rounds a number to the nearest whole number. @@ -12,7 +13,8 @@ * @category Rounding */ export function round(x: number): number { - return (x = +x) < 0 ? -round(-x) : ( - x % 1 >= 0.5 ? x + 1 - x % 1 : x - x % 1 - ); + x = +x; + if (x !== x || x === 0) return x; + const rounded = floor(x + 0.5); + return rounded === 0 && x < 0 ? -0 : rounded; } From 079fc8868ffd66c17aeb9395f3ffd3eb945d64c2 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:58:08 -0800 Subject: [PATCH 112/132] fix(sinh): ensure sinh behaves like Math.sinh --- src/sinh.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sinh.ts b/src/sinh.ts index 57fe84f..0de357c 100644 --- a/src/sinh.ts +++ b/src/sinh.ts @@ -14,5 +14,6 @@ import { exp } from "./exp.ts"; * @category Trigonometry */ export function sinh(x: number): number { + if (x === 0) return x; return (exp(x) - exp(-x)) / 2; } From cf7b7f8594047a620ea1972827c826930281fd34 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:58:09 -0800 Subject: [PATCH 113/132] fix(sqrt): ensure sqrt behaves like Math.sqrt --- src/sqrt.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sqrt.ts b/src/sqrt.ts index 3899655..5d45517 100644 --- a/src/sqrt.ts +++ b/src/sqrt.ts @@ -5,6 +5,7 @@ */ import { EPSILON } from "./constants/epsilon.ts"; import { NAN } from "./constants/nan.ts"; +import { POSITIVE_INFINITY } from "./constants/positive_infinity.ts"; import { abs } from "./abs.ts"; /** @@ -27,6 +28,7 @@ import { abs } from "./abs.ts"; export function sqrt(x: number): number { if (x < 0) return NAN; // negative numbers have no real square root if (x === 0 || x === 1) return x; // sqrt(0) = 0, sqrt(1) = 1 + if (x === POSITIVE_INFINITY) return x; // use Newton's method to approximate the square root let z = x / 2, prev; From 1d8ba71979eef9da69ca83dfb5834aa4b843ae0d Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 18:58:10 -0800 Subject: [PATCH 114/132] fix(trunc): ensure trunc behaves like Math.trunc --- src/trunc.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/trunc.ts b/src/trunc.ts index a3ad460..b82465e 100644 --- a/src/trunc.ts +++ b/src/trunc.ts @@ -36,6 +36,9 @@ import { floor } from "./floor.ts"; * ``` */ export function trunc(x: number): number { - if ((x = +x) !== x) return x; // NaN - return x < 0 ? x < -1 ? ceil(x) : -0 : x < 1 ? 0 : floor(x); + x = +x; + if (x !== x) return x; + if (x === 0) return x; + if (x > -1 && x < 0) return -0; + return x < 0 ? ceil(x) : floor(x); } From 286227f033b7b8217d99d5e2474a442603b5b609 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 19:17:51 -0800 Subject: [PATCH 115/132] refactor(float16,float32)!: remove constants re-exports --- src/float16/index.ts | 1 - src/float32/index.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/float16/index.ts b/src/float16/index.ts index e73c533..6d75fbb 100644 --- a/src/float16/index.ts +++ b/src/float16/index.ts @@ -4,7 +4,6 @@ * * @module float16 */ -export * from "./constants.ts"; export * from "./decode.ts"; export * from "./encode.ts"; export * from "./guards.ts"; diff --git a/src/float32/index.ts b/src/float32/index.ts index 247b976..7d408d7 100644 --- a/src/float32/index.ts +++ b/src/float32/index.ts @@ -4,7 +4,6 @@ * * @module float32 */ -export * from "./constants.ts"; export * from "./decode.ts"; export * from "./encode.ts"; export * from "./guards.ts"; From 7213f8d0c980c3c06dd3a200e58100f54227f395 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Tue, 13 Jan 2026 19:18:26 -0800 Subject: [PATCH 116/132] ci: add build script --- scripts/build.ts | 394 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100755 scripts/build.ts diff --git a/scripts/build.ts b/scripts/build.ts new file mode 100755 index 0000000..5030d1b --- /dev/null +++ b/scripts/build.ts @@ -0,0 +1,394 @@ +#!/usr/bin/env -S deno run -A +// deno-lint-ignore-file no-explicit-any + +import * as dnt from "jsr:@deno/dnt@0.41.3"; +import * as fs from "jsr:@std/fs@1.0.6"; +import * as path from "jsr:@std/path@1"; +import * as semver from "jsr:@std/semver@1.0.3"; +import * as dax from "jsr:@david/dax@0.44.1"; +import { colors } from "jsr:@cliffy/ansi@1.0.0-rc.8/colors"; + +import denoJson from "../deno.json" with { type: "json" }; + +const JSR_SCOPE = "nick", NPM_SCOPE = "nberlette", OUT_DIR = "./npm"; + +// fetch the latest version from jsr.io to ensure this is a build +// that's worth publishing. otherwise, we'll just skip it. +type JsrMetadata = { + scope: string; + name: string; + latest: string; + versions: { [version: string]: Record }; +}; + +type NpmMetadata = { + name: string; + versions: { + [version: string]: dnt.PackageJson & { + _id: string; + _nodeVersion: string; + _npmVersion: string; + _npmUser: { + name: string; + email: string; + }; + _npmOperationalInternal: { + host: string; + tmp: string; + }; + _hasShrinkwrap: boolean; + dist: { + integrity: string; + shasum: string; + tarball: string; + signatures: object[]; + fileCount: number; + unpackedSize: number; + }; + directories: { + lib: string; + }; + [x: string]: unknown; + }; + }; + "dist-tags": { + latest?: string; + [x: string]: string | undefined; + }; + [x: string]: unknown; +}; + +async function main() { + let { name, version, license, author } = denoJson; + const description = + "Standalone implementation of the entire native Math interface, along with other useful type guards, constants, and utilities. Zero dependencies."; + const base = new dax.Path( + path.fromFileUrl(import.meta.resolve("../deno.json")), + ).parentOrThrow(); + // tmp dir used for building + const tmp = new dax.Path(await Deno.makeTempDir({ prefix: "math-" })); + + const deno = dax.build$({ + commandBuilder: new dax.CommandBuilder().cwd(base).command([ + "deno", + "run", + "-A", + ]).env({ + DENO_FUTURE: "1", + }), + extras: { + ansi: colors, + async run(...args: string[]): Promise { + const res = await deno`deno run -A ${args}`; + return res.stdoutBytes; + }, + async fmt(...args: string[]): Promise { + await deno`deno fmt ${args}`; + }, + }, + }); + + const $ = dax.build$({ + commandBuilder: new dax.CommandBuilder().cwd(base), + extras: { + ansi: colors, + glob: fs.expandGlob, + globSync: fs.expandGlobSync, + walk: fs.walk, + walkSync: fs.walkSync, + deno: deno, + async getNextVersion( + version: string, + latest?: semver.SemVer, + current?: semver.SemVer, + ) { + if (!latest && !current) return version; + latest ||= current; + current ||= latest; + + if (!isTTY()) return version; + + const prerelease = current?.prerelease ?? []; + const options = [ + ...prerelease?.length ? ["prerelease"] as const : [] as const, + "prepatch", + "preminor", + "premajor", + "prerelease", + "patch", + "minor", + "major", + ] as const; + + const candidates = options.map((t) => + [t, semver.format(semver.increment(current!, t))] as const + ); + + const index = await $.select({ + message: `🔍 Please select a version for this build ${ + $.ansi.dim(`(current: ${underline.bold(version)})`) + }`, + options: [...candidates].map(([t, v], i) => + `${v} (${t}${i === 0 ? ", default" : ""})` + ).concat([`custom ${$.ansi.dim("(input manually)")}`]), + noClear: true, + }); + + if (index != null) { + let v2 = candidates[index][1] as string | undefined; + if (index > candidates.length || v2 == null) { + v2 = await $.maybePrompt( + `Enter a new version for ${bold(name)} ${ + $.ansi.dim(`(current: ${underline.bold(version)})`) + }:`, + { + default: semver.format( + semver.increment( + current!, + prerelease.length ? "prerelease" : "patch", + ), + ), + }, + ); + } + return v2 ?? version; + } + return version; + }, + }, + }); + + const { bold, underline, red, yellow } = colors(); + + const finalOutDir = base.join(OUT_DIR).resolve(); + const outDir = await tmp.join(OUT_DIR).resolve().ensureDir(); + const npmName = name.replace(`@${JSR_SCOPE}/`, `@${NPM_SCOPE}/`); + + let proceed = true; + const meta = await getJsrMetadata(name); + if (!meta) { + proceed = isTTY() && await $.confirm( + `❓ ${bold.underline(name)} not found on ${ + yellow("jsr.io") + }. Continue anyway?`, + { default: false, noClear: true }, + ); + } + + if (!proceed) { + $.logWarn("⚠️ SKIP", `skipping build for ${name}@${version}`); + return; + } + + const latest = await getLatestVersion(name); + const current = semver.tryParse(version); + + const isNewVersion = (!latest && !!current) || + (!!latest && !!current && semver.greaterThan(current, latest)); + + if (!isNewVersion && isTTY()) { + version = await $.getNextVersion(version, latest, current); + } + + await build(); + + if (Deno.env.get("NO_PUBLISH") !== "1") { + const publish = !isTTY() || await $.confirm( + `🚀 publish ${npmName} to ${red.bold("npm")}?`, + { + default: true, + }, + ); + if (publish) await $`cd npm && npm publish --access public`; + } + + async function getJsrMetadata( + name: string, + ): Promise { + try { + return await $.request(`https://jsr.io/${name}/meta.json`) + .timeout("5s") + .showProgress(true).noThrow().json(); + } catch { + return undefined; + } + } + + async function getNpmMetadata( + name: string, + ): Promise { + try { + $.logLight(`🔍 fetching ${red.bold("npm")} package metadata for ${name}`); + return await $.request(`https://registry.npmjs.org/${name}`) + .timeout("5s") + .showProgress(true).noThrow().json(); + } catch { + return undefined; + } + } + + async function getLatestVersion( + name: string, + npm = false, + ): Promise { + const meta = await getVersions(name, npm); + return meta.latest; + } + + async function getVersions(name: string, npm?: boolean): Promise<{ + latest: semver.SemVer | undefined; + versions: semver.SemVer[]; + }> { + let meta: NpmMetadata | JsrMetadata | undefined; + if (npm) { + meta = await getNpmMetadata(npmName); + } else { + meta = await getJsrMetadata(name); + } + + if (meta?.versions) { + const tags = ( + npm ? (meta as NpmMetadata)["dist-tags"] : meta as JsrMetadata + ) ?? {}; + const versions = Object.keys(meta.versions) + .map(semver.tryParse).filter((v) => v != null).sort(semver.compare); + const latest = semver.tryParse(tags.latest ?? "") ?? versions.at(-1); + + return { latest, versions }; + } + + return { latest: undefined, versions: [] as semver.SemVer[] }; + } + + function isTTY(): boolean { + return Deno.stdout.isTerminal() || Deno.env.get("CI") == null; + } + + async function preBuild() { + await base.join("src").copy(tmp, { overwrite: true }); + await base.join("deno.json").copyToDir(tmp); + + await outDir.ensureDir(); + await outDir.emptyDir(); + await Promise.all([ + "LICENSE", + "README.md", + ].map((f) => base.join(f).copyToDir(outDir))); + + // move all src files up one level, update the imports/exports + // in index.ts and deno.json, and remove the src dir. this is + // necessary so dnt doesn't create a nested src dir in the npm + // package (which, while technically functional, is not idiomatic). + const indexTs = tmp.join("index.ts"); + let src = await indexTs.readText(); + src = src.replace(/\.\/src\//g, "./"); + await indexTs.writeText(src); + const denoJson = tmp.join("deno.json"); + let json = await denoJson.readText(); + json = json.replace(/(?<=")\.\/src\//g, "./"); + await denoJson.writeText(json); + } + + async function build() { + await preBuild(); + + const exports = Object.entries(denoJson.exports).reduce( + (o, [k, v]) => { + v = v.replace(/^\.\//, "").replace(/(?:\.d)?\.ts$/, ""); + v = v.replace(/^src\//, ""); + v = v === "mod" ? "index" : v; + (o as any)[k] = { + types: `./esm/${v}.d.ts`, + import: { + types: `./esm/${v}.d.ts`, + default: `./esm/${v}.js`, + }, + require: { + types: `./cjs/${v}.d.ts`, + default: `./cjs/${v}.js`, + }, + default: `./esm/${v}.js`, + }; + return o; + }, + {} as { + [E in keyof typeof denoJson.exports]: { + types: string; + import: { types: string; default: string }; + require: { types: string; default: string }; + default: string; + }; + }, + ); + + const packageJson = { + type: "module", + name: npmName, + version, + license, + author, + private: false, + publishConfig: { + access: "public", + }, + description, + keywords: [ + "math", + "utilities", + "arithmetic", + "trigonometry", + "standalone", + "mersenne-twister", + "ponyfill", + "deno", + "bun", + "node", + "embedded", + "typescript", + ], + repository: "https://github.com/nberlette/math.git", + homepage: "https://jsr.io/@nick/math/doc", + readme: "https://github.com/nberlette/math#readme", + bugs: "https://github.com/nberlette/math/issues", + main: exports["."].require.default, + module: exports["."].import.default, + types: exports["."].import.types ?? exports["."].types, + exports, + }; + + // build esm + cjs with dnt + await dnt.build({ + entryPoints: [tmp.join("index.ts").toString()], + outDir: outDir.toString(), + compilerOptions: { + target: "ES2020", + sourceMap: true, + skipLibCheck: true, + lib: ["ESNext"], + strictNullChecks: true, + strictFunctionTypes: true, + strictBindCallApply: true, + }, + declaration: "inline", + esModule: true, + package: packageJson, + packageManager: "npm", + shims: {}, + scriptModule: "cjs", + skipNpmInstall: true, + skipSourceOutput: false, + test: false, + typeCheck: false, + async postBuild() { + $.logStep("📦 BUILT", `${name}@${version} successfully`); + + await outDir.join("script").rename(outDir.join("cjs")); + $.logStep("🚚 MOVED", "./script -> ./cjs"); + + await outDir.copy(finalOutDir.resolve(), { overwrite: true }); + $.logStep("🚚 MOVED", `[tmp dir] -> ${finalOutDir}`); + }, + }); + } +} +if (import.meta.main) await main(); From 7c25f8ee8f1ca60eedf72e087d9262a6b5118986 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Wed, 21 Jan 2026 14:02:48 -0800 Subject: [PATCH 117/132] ci: add coveralls integration to workflow --- .github/workflows/ci.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35e88f1..bcfb4e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,11 +36,20 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 + - uses: denoland/setup-deno@v2 with: deno-version: v2.x + - id: ok run: deno task ok + + - id: coveralls + uses: coverallsapp/github-action@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + file: .coverage/lcov.info + - id: coverage uses: actions/upload-artifact@v6 with: @@ -67,15 +76,18 @@ jobs: group: publish-${{ github.ref_name }} steps: - uses: actions/checkout@v6 + - name: "setup deno" uses: denoland/setup-deno@v2 with: deno-version: v2.x + - if: | (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || (github.event_name == 'workflow_dispatch' && github.event.inputs.publish-jsr == 'true') name: "publish to jsr" run: deno publish + - if: | (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || (github.event_name == 'workflow_dispatch' && github.event.inputs.publish-npm == 'true') @@ -84,6 +96,7 @@ jobs: with: node-version: 24 registry-url: "https://registry.npmjs.org" + - id: build if: | (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || @@ -93,18 +106,21 @@ jobs: run: deno task build env: NO_PUBLISH: 1 + - id: artifact if: steps.build.outcome == 'success' - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v6 with: path: npm name: nberlette-math-npm_${{ github.ref_name }}-${{ github.sha }} + - if: | (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || (github.event_name == 'workflow_dispatch' && github.event.inputs.publish-npm == 'true') name: "publish to npm" run: npm publish --access public working-directory: npm + - if: | (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || (github.event_name == 'workflow_dispatch' && github.event.inputs.publish-gpr == 'true') @@ -115,6 +131,7 @@ jobs: registry-url: "https://npm.pkg.github.com" env: NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - if: | (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || (github.event_name == 'workflow_dispatch' && github.event.inputs.publish-gpr == 'true') From a73082a70e28aeda767b351cc0c37ae02c571ab9 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Wed, 21 Jan 2026 14:03:10 -0800 Subject: [PATCH 118/132] chore: update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 72b9649..947aa48 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ Thumbs.db .coverage coverage .cov +npm From ecee653ef5799ae069f78ace514f26cce227312c Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Wed, 21 Jan 2026 14:04:23 -0800 Subject: [PATCH 119/132] tests: update readme doc tests, fix some coverage and typechecking issues --- README.md | 350 +++++++++++-------------------------- src/float16/decode.test.ts | 2 +- src/guards/integer.test.ts | 2 +- src/random.test.ts | 26 +++ 4 files changed, 132 insertions(+), 248 deletions(-) diff --git a/README.md b/README.md index b789e57..6f894d5 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,26 @@ -
- # `@nick/math` #### Dependency-free implementation of the `Math.*` namespace -
- --- ## Overview -Standalone implementations of the **entire** native [`Math`] namespace, written -in pure TypeScript with absolutely zero dependencies. Organized in a modular -structure to encourage tree-shaking (dead code elimination) in bundlers, this -package can be imported eithr on an individual module basis, or as a namespace -suitable for use as a drop-in replacement for the standard `Math` object[^1]. +This package provides zero-dependency standalone implementations for all of the +[functions] and [constants] found in the native [`Math`] namespace, _most_ of +those found on the global `Number` constructor function, with some additional +non-standard helpers, constants, and guards for various other purposes. + +## Usage + +Written in pure TypeScript with absolutely zero dependencies. Organized in a +modular structure to facilitate bundler tree-shaking (dead code elimination), +you can either import the entire package as a namespace (useful for rapid +prototyping during development), or on a modular basis where only the features +required are imported (recommended for production). + +When imported as a namespace (or via the default export), this package is suitable +to use as a drop-in replacement for any standard `Math.*` feature's usage[^1]. [^1]: All modules in this package are implemented using 100% manual logic and arithmetic, and do not rely on any native code or objects. As such, the @@ -24,7 +30,10 @@ suitable for use as a drop-in replacement for the standard `Math` object[^1]. expected behavior, please open an issue so I can address it and attempt to improve it. Thank you! -## Install +### Install + +This package is published to [JSR] as `@nick/math`, and to [NPM] and [GPR] as +`@nberlette/math`, for maximum availability on all major package managers: ```sh deno add jsr:@nick/math @@ -38,6 +47,10 @@ pnpm add jsr:@nick/math yarn add jsr:@nick/math ``` +```sh +vlt add jsr:@nick/math +``` + ```sh bunx jsr add @nick/math ``` @@ -46,27 +59,59 @@ bunx jsr add @nick/math npx jsr add @nick/math ``` ---- +#### NPM and GPR -## Usage +```sh +deno add npm:@nberlette/math +``` + +```sh +pnpm add @nberlette/math +``` + +```sh +yarn add @nberlette/math +``` + +```sh +vlt add @nberlette/math +``` + +```sh +bun add @nberlette/math +``` + +```sh +npm i @nberlette/math +``` + +### Example Usage + +#### Namespace ```ts import * as math from "@nick/math"; import assert from "node:assert"; -assert.ok(Math.abs(math.abs(-1) - 1) < 1e-9); -assert.ok(Math.abs(math.acos(0.5) - 1.0471975511965979) < 1e-9); -assert.ok(Math.abs(math.acosh(1) - 0) < 1e-9); -assert.ok(Math.abs(math.log(9) - 2.1972245773362196) < 1e-9); -assert.ok(Math.abs(math.PI - 3.141592653589793) < 1e-9); + +assert.ok((math.acos(0.5) - Math.acos(0.5)) < 1e-9); +assert.strictEqual(math.NEGATIVE_ZERO, -0); +assert.strictEqual(math.PI, 3.141592653589793 /* Math.PI */); ``` -```ts -import { abs } from "@nick/math/abs"; +#### Modular -import { fround } from "@nick/math/fround"; +```ts +import { PI } from "@nick/math/pi"; +import { f16round } from "@nick/math/f16round"; +import { sign } from "@nick/math/sign"; +import { NEGATIVE_INFINITY } from "@nick/math/constants/negative-infinity"; +import assert from "node:assert"; -import { log } from "@nick/math/log"; +assert.strictEqual(f16round(PI), 3.140625); +assert.strictEqual(sign(-0), -0); +assert.strictEqual(sign(PI), 1); +assert.strictEqual(sign(NEGATIVE_INFINITY), -1); ``` --- @@ -150,17 +195,7 @@ import { log } from "@nick/math/log"; import { E } from "@nick/math/constants/e"; import assert from "node:assert"; -assert.ok(E === 2.718281828459045); -``` - -##### Type-Level Usage - -```ts -import { E } from "@nick/math/constants/e"; - -function assertEulersNumber(e: number): asserts e is E { - if (e !== E) throw new TypeError(`Expected ${E}, got ${e}`); -} +assert.strictEqual(E, 2.718281828459045); ``` #### `LN10` (Natural logarithm of 10) @@ -169,17 +204,7 @@ function assertEulersNumber(e: number): asserts e is E { import { LN10 } from "@nick/math/constants/ln10"; import assert from "node:assert"; -assert.ok(LN10 === 2.302585092994046); -``` - -##### Type-Level Usage - -```ts -import { LN10 } from "@nick/math/constants/ln10"; - -function assertNaturalLogarithmOf10(ln10: number): asserts ln10 is LN10 { - if (ln10 !== LN10) throw new TypeError(`Expected ${LN10}, got ${ln10}`); -} +assert.strictEqual(LN10, 2.302585092994046); ``` #### `LN2` (Natural logarithm of 2) @@ -188,17 +213,7 @@ function assertNaturalLogarithmOf10(ln10: number): asserts ln10 is LN10 { import { LN2 } from "@nick/math/constants/ln2"; import assert from "node:assert"; -assert.ok(LN2 === 0.6931471805599453); -``` - -##### Type-Level Usage - -```ts -import { LN2 } from "@nick/math/constants/ln2"; - -function assertNaturalLogarithmOf2(ln2: number): asserts ln2 is LN2 { - if (ln2 !== LN2) throw new TypeError(`Expected ${LN2}, got ${ln2}`); -} +assert.strictEqual(LN2, 0.6931471805599453); ``` #### `LOG2E` (Base 2 logarithm of E) @@ -207,17 +222,7 @@ function assertNaturalLogarithmOf2(ln2: number): asserts ln2 is LN2 { import { LOG2E } from "@nick/math/constants/log2e"; import assert from "node:assert"; -assert.ok(LOG2E === 1.4426950408889634); -``` - -##### Type-Level Usage - -```ts -import { LOG2E } from "@nick/math/constants/log2e"; - -function assertBase2LogarithmOfE(log2e: number): asserts log2e is LOG2E { - if (log2e !== LOG2E) throw new TypeError(`Expected ${LOG2E}, got ${log2e}`); -} +assert.strictEqual(LOG2E, 1.4426950408889634); ``` #### `LOG10E` (Base 10 logarithm of E) @@ -226,19 +231,7 @@ function assertBase2LogarithmOfE(log2e: number): asserts log2e is LOG2E { import { LOG10E } from "@nick/math/constants/log10e"; import assert from "node:assert"; -assert.ok(LOG10E === 0.4342944819032518); -``` - -##### Type-Level Usage - -```ts -import { LOG10E } from "@nick/math/constants/log10e"; - -function assertBase10LogarithmOfE(log10e: number): asserts log10e is LOG10E { - if (log10e !== LOG10E) { - throw new TypeError(`Expected ${LOG10E}, got ${log10e}`); - } -} +assert.strictEqual(LOG10E, 0.4342944819032518); ``` #### `PI` (π) @@ -247,17 +240,7 @@ function assertBase10LogarithmOfE(log10e: number): asserts log10e is LOG10E { import { PI } from "@nick/math/constants/pi"; import assert from "node:assert"; -assert.ok(PI === 3.141592653589793); -``` - -##### Type-Level Usage - -```ts -import { PI } from "@nick/math/constants/pi"; - -function assertPi(pi: number): asserts pi is PI { - if (pi !== PI) throw new TypeError(`Expected ${PI}, got ${pi}`); -} +assert.strictEqual(PI, 3.141592653589793); ``` #### `SQRT1_2` (Square root of 1/2) @@ -266,21 +249,7 @@ function assertPi(pi: number): asserts pi is PI { import { SQRT1_2 } from "@nick/math/constants/sqrt1_2"; import assert from "node:assert"; -assert.ok(SQRT1_2 === 0.7071067811865476); -``` - -##### Type-Level Usage - -```ts -import { SQRT1_2 } from "@nick/math/constants/sqrt1_2"; - -function assertSquareRootOfOneHalf( - sqrt1_2: number, -): asserts sqrt1_2 is SQRT1_2 { - if (sqrt1_2 !== SQRT1_2) { - throw new TypeError(`Expected ${SQRT1_2}, got ${sqrt1_2}`); - } -} +assert.strictEqual(SQRT1_2, 0.7071067811865476); ``` #### `SQRT2` (Square root of 2) @@ -289,17 +258,7 @@ function assertSquareRootOfOneHalf( import { SQRT2 } from "@nick/math/constants/sqrt2"; import assert from "node:assert"; -assert.ok(SQRT2 === 1.4142135623730951); -``` - -##### Type-Level Usage - -```ts -import { SQRT2 } from "@nick/math/constants/sqrt2"; - -function assertSquareRootOfTwo(sqrt2: number): asserts sqrt2 is SQRT2 { - if (sqrt2 !== SQRT2) throw new TypeError(`Expected ${SQRT2}, got ${sqrt2}`); -} +assert.strictEqual(SQRT2, 1.4142135623730951); ``` #### `EPSILON` @@ -311,19 +270,7 @@ different from `1`. import { EPSILON } from "@nick/math/constants/epsilon"; import assert from "node:assert"; -assert.ok(EPSILON === 2.220446049250313e-16); -``` - -##### Type-Level Usage - -```ts -import { EPSILON } from "@nick/math/constants/epsilon"; - -function assertEpsilon(epsilon: number): asserts epsilon is EPSILON { - if (epsilon !== EPSILON) { - throw new TypeError(`Expected ${EPSILON}, got ${epsilon}`); - } -} +assert.strictEqual(EPSILON, 2.220446049250313e-16); ``` #### `MAX_SAFE_INTEGER` @@ -334,21 +281,7 @@ The maximum safe integer in JavaScript, `2^53 - 1`. import { MAX_SAFE_INTEGER } from "@nick/math/constants/max-safe-integer"; import assert from "node:assert"; -assert.ok(MAX_SAFE_INTEGER === 9007199254740991); -``` - -##### Type-Level Usage - -```ts -import { MAX_SAFE_INTEGER } from "@nick/math/constants/max-safe-integer"; - -function assertMaxSafeInteger( - maxSafeInteger: number, -): asserts maxSafeInteger is MAX_SAFE_INTEGER { - if (maxSafeInteger !== MAX_SAFE_INTEGER) { - throw new TypeError(`Expected ${MAX_SAFE_INTEGER}, got ${maxSafeInteger}`); - } -} +assert.strictEqual(MAX_SAFE_INTEGER, 9007199254740991); ``` #### `MIN_SAFE_INTEGER` @@ -359,21 +292,7 @@ The minimum safe integer in JavaScript, `-2^53 + 1`. import { MIN_SAFE_INTEGER } from "@nick/math/constants/min-safe-integer"; import assert from "node:assert"; -assert.ok(MIN_SAFE_INTEGER === -9007199254740991); -``` - -##### Type-Level Usage - -```ts -import { MIN_SAFE_INTEGER } from "@nick/math/constants/min-safe-integer"; - -function assertMinSafeInteger( - minSafeInteger: number, -): asserts minSafeInteger is MIN_SAFE_INTEGER { - if (minSafeInteger !== MIN_SAFE_INTEGER) { - throw new TypeError(`Expected ${MIN_SAFE_INTEGER}, got ${minSafeInteger}`); - } -} +assert.strictEqual(MIN_SAFE_INTEGER, -9007199254740991); ``` #### `MAX_VALUE` @@ -384,19 +303,7 @@ The maximum representable value in JavaScript. import { MAX_VALUE } from "@nick/math/constants/max-value"; import assert from "node:assert"; -assert.ok(MAX_VALUE === 1.7976931348623157e308); -``` - -##### Type-Level Usage - -```ts -import { MAX_VALUE } from "@nick/math/constants/max-value"; - -function assertMaxValue(maxValue: number): asserts maxValue is MAX_VALUE { - if (maxValue !== MAX_VALUE) { - throw new TypeError(`Expected ${MAX_VALUE}, got ${maxValue}`); - } -} +assert.strictEqual(MAX_VALUE, 1.7976931348623157e308); ``` #### `MIN_VALUE` @@ -407,19 +314,7 @@ The minimum representable value in JavaScript. import { MIN_VALUE } from "@nick/math/constants/min-value"; import assert from "node:assert"; -assert.ok(MIN_VALUE === 5e-324); -``` - -##### Type-Level Usage - -```ts -import { MIN_VALUE } from "@nick/math/constants/min-value"; - -function assertMinValue(minValue: number): asserts minValue is MIN_VALUE { - if (minValue !== MIN_VALUE) { - throw new TypeError(`Expected ${MIN_VALUE}, got ${minValue}`); - } -} +assert.strictEqual(MIN_VALUE, 5e-324); ``` #### `NEGATIVE_INFINITY` @@ -430,23 +325,7 @@ The negative infinity value in JavaScript. import { NEGATIVE_INFINITY } from "@nick/math/constants/negative-infinity"; import assert from "node:assert"; -assert.ok(NEGATIVE_INFINITY === -Infinity); -``` - -##### Type-Level Usage - -```ts -import { NEGATIVE_INFINITY } from "@nick/math/constants/negative-infinity"; - -function assertNegativeInfinity( - negativeInfinity: number, -): asserts negativeInfinity is NEGATIVE_INFINITY { - if (negativeInfinity !== NEGATIVE_INFINITY) { - throw new TypeError( - `Expected ${NEGATIVE_INFINITY}, got ${negativeInfinity}`, - ); - } -} +assert.strictEqual(NEGATIVE_INFINITY, -Infinity); ``` #### `POSITIVE_INFINITY` @@ -457,23 +336,7 @@ The positive infinity value in JavaScript. import { POSITIVE_INFINITY } from "@nick/math/constants/positive-infinity"; import assert from "node:assert"; -assert.ok(POSITIVE_INFINITY === Infinity); -``` - -##### Type-Level Usage - -```ts -import { POSITIVE_INFINITY } from "@nick/math/constants/positive-infinity"; - -function assertPositiveInfinity( - positiveInfinity: number, -): asserts positiveInfinity is POSITIVE_INFINITY { - if (positiveInfinity !== POSITIVE_INFINITY) { - throw new TypeError( - `Expected ${POSITIVE_INFINITY}, got ${positiveInfinity}`, - ); - } -} +assert.strictEqual(POSITIVE_INFINITY, Infinity); ``` #### `NAN` @@ -482,23 +345,18 @@ The `NaN` value in JavaScript, representing "Not a Number". ```ts import { NAN } from "@nick/math/constants/nan"; +import assert from "node:assert"; -console.log(NAN); // NaN - -// or, to use the same name as the global constant: -import { NaN } from "@nick/math/constants/nan"; - -console.log(NaN); // NaN +assert.ok(NAN !== NAN); ``` -##### Type-Level Usage +###### Alias: `NaN` ```ts import { NaN } from "@nick/math/constants/nan"; +import assert from "node:assert"; -function assertNaN(nan: number): asserts nan is NaN { - if (!Number.isNaN(nan)) throw new TypeError(`Expected ${NaN}, got ${nan}`); -} +assert.ok(NaN !== NaN); ``` --- @@ -513,7 +371,7 @@ Returns the absolute value of a number. import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(abs(-1) === 1); +assert.strictEqual(abs(-1), 1); ``` #### `acos` @@ -535,7 +393,7 @@ Returns the inverse hyperbolic cosine of a number. import { acosh } from "@nick/math/acosh"; import assert from "node:assert"; -assert.ok(acosh(1) === 0); +assert.strictEqual(acosh(1), 0); ``` #### `asin` @@ -579,7 +437,7 @@ Returns the arctangent of the quotient of its arguments. import { atan2 } from "@nick/math/atan2"; import assert from "node:assert"; -assert.ok(atan2(1, 1) === 0.7853981633974483); +assert.strictEqual(atan2(1, 1), 0.7853981633974483); ``` #### `atanh` @@ -590,7 +448,7 @@ Returns the inverse hyperbolic tangent of a number. import { atanh } from "@nick/math/atanh"; import assert from "node:assert"; -assert.ok(atanh(0.5) === 0.5493061443340549); +assert.strictEqual(atanh(0.5), 0.5493061443340549); ``` #### `cbrt` @@ -601,7 +459,7 @@ Returns the cube root of a number. import { cbrt } from "@nick/math/cbrt"; import assert from "node:assert"; -assert.ok(cbrt(27) === 3); +assert.strictEqual(cbrt(27), 3); ``` #### `ceil` @@ -612,7 +470,7 @@ Returns the smallest integer greater than or equal to a number. import { ceil } from "@nick/math/ceil"; import assert from "node:assert"; -assert.ok(ceil(1.5) === 2); +assert.strictEqual(ceil(1.5), 2); ``` #### `clz32` @@ -624,7 +482,7 @@ number. import { clz32 } from "@nick/math/clz32"; import assert from "node:assert"; -assert.ok(clz32(1) === 31); +assert.strictEqual(clz32(1), 31); ``` #### `cos` @@ -679,7 +537,7 @@ Returns the largest integer less than or equal to a number. import { floor } from "@nick/math/floor"; import assert from "node:assert"; -assert.ok(floor(1.5) === 1); +assert.strictEqual(floor(1.5), 1); ``` #### `fround` @@ -706,7 +564,7 @@ import { f16round } from "@nick/math/f16round"; import { PI } from "@nick/math/constants/pi"; import assert from "node:assert"; -assert.ok(f16round(PI) === 3.140625); +assert.strictEqual(f16round(PI), 3.140625); ``` #### `hypot` @@ -717,7 +575,7 @@ Returns the square root of the sum of the squares of its arguments. import { hypot } from "@nick/math/hypot"; import assert from "node:assert"; -assert.ok(hypot(3, 4) === 5); +assert.strictEqual(hypot(3, 4), 5); ``` #### `imul` @@ -728,7 +586,7 @@ Returns the result of a 32-bit integer multiplication. import { imul } from "@nick/math/imul"; import assert from "node:assert"; -assert.ok(imul(2, 3) === 6); +assert.strictEqual(imul(2, 3), 6); ``` #### `log` @@ -783,7 +641,7 @@ Returns the largest of zero or more numbers. import { max } from "@nick/math/max"; import assert from "node:assert"; -assert.ok(max(1, 2, 3) === 3); +assert.strictEqual(max(1, 2, 3), 3); ``` #### `min` @@ -794,7 +652,7 @@ Returns the smallest of zero or more numbers. import { min } from "@nick/math/min"; import assert from "node:assert"; -assert.ok(min(1, 2, 3) === 1); +assert.strictEqual(min(1, 2, 3), 1); ``` #### `pow` @@ -805,7 +663,7 @@ Returns the base to the exponent power. import { pow } from "@nick/math/pow"; import assert from "node:assert"; -assert.ok(pow(2, 3) === 8); +assert.strictEqual(pow(2, 3), 8); ``` #### `random` @@ -829,7 +687,7 @@ Returns the value of a number rounded to the nearest integer. import { round } from "@nick/math/round"; import assert from "node:assert"; -assert.ok(round(1.5) === 2); +assert.strictEqual(round(1.5), 2); ``` #### `sign` @@ -841,7 +699,7 @@ zero. import { sign } from "@nick/math/sign"; import assert from "node:assert"; -assert.ok(sign(-1) === -1); +assert.strictEqual(sign(-1), -1); ``` #### `sin` @@ -874,7 +732,7 @@ Returns the square root of a number. import { sqrt } from "@nick/math/sqrt"; import assert from "node:assert"; -assert.ok(sqrt(9) === 3); +assert.strictEqual(sqrt(9), 3); ``` #### `tan` @@ -907,7 +765,7 @@ Returns the integer part of a number by removing any fractional digits. import { trunc } from "@nick/math/trunc"; import assert from "node:assert"; -assert.ok(trunc(1.5) === 1); +assert.strictEqual(trunc(1.5), 1); ``` --- diff --git a/src/float16/decode.test.ts b/src/float16/decode.test.ts index 8c93c9e..b74fca7 100644 --- a/src/float16/decode.test.ts +++ b/src/float16/decode.test.ts @@ -29,7 +29,7 @@ describe("decodeFloat16", () => { } for (const bits of cases) { view.setUint16(0, bits); - const expected = getFloat16.call(view, 0); + const expected: number= getFloat16.call(view, 0); const actual = decodeFloat16(bits); if (Number.isNaN(expected)) { assert.ok(Number.isNaN(actual)); diff --git a/src/guards/integer.test.ts b/src/guards/integer.test.ts index 6140796..a8b0dd3 100644 --- a/src/guards/integer.test.ts +++ b/src/guards/integer.test.ts @@ -2,7 +2,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; import { isInteger, isNumberInteger } from "./integer.ts"; -const cases: unknown[] = [0, 1, -1, 1.2, -2.5, NaN, Infinity, -Infinity, "3"]; +const cases = [0, 1, -1, 1.2, -2.5, NaN, Infinity, -Infinity, "3"]; describe("isInteger", () => { it("is a function", () => { diff --git a/src/random.test.ts b/src/random.test.ts index 0ba1959..934ba46 100644 --- a/src/random.test.ts +++ b/src/random.test.ts @@ -53,6 +53,13 @@ describe("MT19937", () => { assert.ok(mt19937.init != null && typeof mt19937.init === "function"); }); + it("has a method named initFromArray", () => { + assert.ok( + mt19937.initFromArray != null && + typeof mt19937.initFromArray === "function", + ); + }); + it("has a method named randomInt", () => { assert.ok( mt19937.randomInt != null && typeof mt19937.randomInt === "function", @@ -79,4 +86,23 @@ describe("MT19937", () => { ); assert.deepStrictEqual(actual, expected); }); + + it("produces the same sequence for the same seed array", () => { + const seeds = [0x123, 0x234, 0x345, 0x456]; + const left = new MT19937().initFromArray(...seeds); + const right = new MT19937().initFromArray(...seeds); + const count = 8; + const leftSeq = Array.from({ length: count }, () => left.randomInt()); + const rightSeq = Array.from({ length: count }, () => right.randomInt()); + assert.deepStrictEqual(leftSeq, rightSeq); + }); + + it("produces different sequences for different seed arrays", () => { + const left = new MT19937().initFromArray(1, 2, 3, 4); + const right = new MT19937().initFromArray(4, 3, 2, 1); + const count = 8; + const leftSeq = Array.from({ length: count }, () => left.randomInt()); + const rightSeq = Array.from({ length: count }, () => right.randomInt()); + assert.notDeepStrictEqual(leftSeq, rightSeq); + }); }); From 0fce7dc74165197c9d0fa8805ef3b0246639d1d1 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Wed, 21 Jan 2026 14:07:22 -0800 Subject: [PATCH 120/132] chore: fmt --- README.md | 6 +++--- src/float16/decode.test.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6f894d5..f6af3e2 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,9 @@ you can either import the entire package as a namespace (useful for rapid prototyping during development), or on a modular basis where only the features required are imported (recommended for production). -When imported as a namespace (or via the default export), this package is suitable -to use as a drop-in replacement for any standard `Math.*` feature's usage[^1]. +When imported as a namespace (or via the default export), this package is +suitable to use as a drop-in replacement for any standard `Math.*` feature's +usage[^1]. [^1]: All modules in this package are implemented using 100% manual logic and arithmetic, and do not rely on any native code or objects. As such, the @@ -93,7 +94,6 @@ npm i @nberlette/math import * as math from "@nick/math"; import assert from "node:assert"; - assert.ok((math.acos(0.5) - Math.acos(0.5)) < 1e-9); assert.strictEqual(math.NEGATIVE_ZERO, -0); assert.strictEqual(math.PI, 3.141592653589793 /* Math.PI */); diff --git a/src/float16/decode.test.ts b/src/float16/decode.test.ts index b74fca7..93c24f0 100644 --- a/src/float16/decode.test.ts +++ b/src/float16/decode.test.ts @@ -29,7 +29,7 @@ describe("decodeFloat16", () => { } for (const bits of cases) { view.setUint16(0, bits); - const expected: number= getFloat16.call(view, 0); + const expected: number = getFloat16.call(view, 0); const actual = decodeFloat16(bits); if (Number.isNaN(expected)) { assert.ok(Number.isNaN(actual)); From 0ddc822e59849a2873415f5b04ce020c06c8813b Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Wed, 21 Jan 2026 16:50:32 -0800 Subject: [PATCH 121/132] refactor(scripts): improve build script --- scripts/build.ts | 386 +++++++++++++++++++++++++++-------------------- 1 file changed, 222 insertions(+), 164 deletions(-) diff --git a/scripts/build.ts b/scripts/build.ts index 5030d1b..2d5da70 100755 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -9,6 +9,7 @@ import * as dax from "jsr:@david/dax@0.44.1"; import { colors } from "jsr:@cliffy/ansi@1.0.0-rc.8/colors"; import denoJson from "../deno.json" with { type: "json" }; +import process, { env } from "node:process"; const JSR_SCOPE = "nick", NPM_SCOPE = "nberlette", OUT_DIR = "./npm"; @@ -58,107 +59,196 @@ type NpmMetadata = { [x: string]: unknown; }; -async function main() { - let { name, version, license, author } = denoJson; - const description = - "Standalone implementation of the entire native Math interface, along with other useful type guards, constants, and utilities. Zero dependencies."; - const base = new dax.Path( - path.fromFileUrl(import.meta.resolve("../deno.json")), - ).parentOrThrow(); - // tmp dir used for building - const tmp = new dax.Path(await Deno.makeTempDir({ prefix: "math-" })); - - const deno = dax.build$({ - commandBuilder: new dax.CommandBuilder().cwd(base).command([ - "deno", - "run", - "-A", - ]).env({ - DENO_FUTURE: "1", - }), - extras: { - ansi: colors, - async run(...args: string[]): Promise { - const res = await deno`deno run -A ${args}`; - return res.stdoutBytes; - }, - async fmt(...args: string[]): Promise { - await deno`deno fmt ${args}`; - }, - }, - }); - - const $ = dax.build$({ - commandBuilder: new dax.CommandBuilder().cwd(base), - extras: { - ansi: colors, - glob: fs.expandGlob, - globSync: fs.expandGlobSync, - walk: fs.walk, - walkSync: fs.walkSync, - deno: deno, - async getNextVersion( - version: string, - latest?: semver.SemVer, - current?: semver.SemVer, - ) { - if (!latest && !current) return version; - latest ||= current; - current ||= latest; - - if (!isTTY()) return version; - - const prerelease = current?.prerelease ?? []; - const options = [ - ...prerelease?.length ? ["prerelease"] as const : [] as const, - "prepatch", - "preminor", - "premajor", - "prerelease", - "patch", - "minor", - "major", - ] as const; - - const candidates = options.map((t) => - [t, semver.format(semver.increment(current!, t))] as const - ); +async function getJsrMetadata( + name: string, +): Promise { + try { + return await $.request(`https://jsr.io/${name}/meta.json`) + .timeout("5s") + .showProgress(true).noThrow().json(); + } catch { + return undefined; + } +} + +async function getNpmMetadata( + name: string, +): Promise { + try { + $.logLight(`🔍 fetching ${red.bold("npm")} package metadata for ${name}`); + return await $.request(`https://registry.npmjs.org/${name}`) + .timeout("5s") + .showProgress(true).noThrow().json(); + } catch { + return undefined; + } +} + +async function getLatestVersion( + name: string, + npm = false, +): Promise { + const meta = await getVersions(name, npm); + return meta.latest; +} - const index = await $.select({ - message: `🔍 Please select a version for this build ${ - $.ansi.dim(`(current: ${underline.bold(version)})`) - }`, - options: [...candidates].map(([t, v], i) => - `${v} (${t}${i === 0 ? ", default" : ""})` - ).concat([`custom ${$.ansi.dim("(input manually)")}`]), - noClear: true, - }); - - if (index != null) { - let v2 = candidates[index][1] as string | undefined; - if (index > candidates.length || v2 == null) { - v2 = await $.maybePrompt( - `Enter a new version for ${bold(name)} ${ - $.ansi.dim(`(current: ${underline.bold(version)})`) - }:`, - { - default: semver.format( - semver.increment( - current!, - prerelease.length ? "prerelease" : "patch", - ), +function getMetadata( + name: string, + npm?: false, +): Promise; +function getMetadata(name: string, npm: true): Promise; +function getMetadata( + name: string, + npm?: boolean, +): Promise; +function getMetadata(name: string, npm?: boolean) { + return npm ? getNpmMetadata(name) : getJsrMetadata(name); +} + +async function getVersions(name: string, npm?: boolean): Promise<{ + latest: semver.SemVer | undefined; + versions: semver.SemVer[]; +}> { + const meta = await getMetadata(name, npm); + + if (meta?.versions) { + const tags = "dist-tags" in meta ? meta["dist-tags"] : meta; + const versions = Object.keys(meta.versions) + .map(semver.tryParse).filter((v) => v != null).sort(semver.compare); + const latest = semver.tryParse(tags.latest ?? "") ?? versions.at(-1); + + return { latest, versions }; + } + + return { latest: undefined, versions: [] as semver.SemVer[] }; +} + +function isTTY(): boolean { + return process.stdout.isTTY || env.CI == null; +} + +let registry = env.NPM_REGISTRY_URL || env.NPM_REGISTRY || + env.NPM_CONFIG_REGISTRY || "https://registry.npmjs.org"; + +let tag = env.DIST_TAG || env.NPM_DIST_TAG || "latest"; + +const base = new dax.Path( + path.fromFileUrl(import.meta.resolve("../deno.json")), +).parentOrThrow(); + +// tmp dir used for building +const tmp = new dax.Path(await Deno.makeTempDir({ prefix: "math-" })); + +const deno = dax.build$({ + commandBuilder: new dax.CommandBuilder().cwd(base).command([ + "deno", + "run", + "-A", + ]).env({ + DENO_FUTURE: "1", + }), + extras: { + ansi: colors, + async run(...args: string[]): Promise { + const res = await deno`deno run -A ${args}`; + return res.stdoutBytes; + }, + async fmt(...args: string[]): Promise { + await deno`deno fmt ${args}`; + }, + }, +}); + +const $ = dax.build$({ + commandBuilder: new dax.CommandBuilder().cwd(base), + extras: { + ansi: colors, + glob: fs.expandGlob, + globSync: fs.expandGlobSync, + walk: fs.walk, + walkSync: fs.walkSync, + deno: deno, + async getNextVersion( + version: string, + latest?: semver.SemVer, + current?: semver.SemVer, + ): Promise { + if (!latest && !current) return version; + latest ||= current; + current ||= latest; + + if (!isTTY()) return version; + + const prerelease = current?.prerelease ?? []; + const options = [ + "none", + "prepatch", + "preminor", + "premajor", + "prerelease", + "pre", + "patch", + "minor", + "major", + ] as const; + + const candidates = options.map((t) => + [ + t, + semver.format( + t === "none" ? current! : semver.increment(current!, t), + ), + ] as const + ); + + const index = await $.select({ + message: `🔍 Select a SemVer release type for new version ${ + $.ansi.dim(`(current: ${underline.bold.brightYellow(version)})`) + }`, + options: [...candidates].map(([t, v], i) => + `${t} -> ${bold.brightGreen(v)}${ + i === 0 ? $.ansi.dim(" (default, no change)") : "" + }` + ).concat([`custom ${$.ansi.dim("(input manually)")}`]), + noClear: true, + }); + + if (index != null) { + let v2 = candidates[index][1] as string | undefined; + if (index > candidates.length || v2 == null) { + v2 = await $.maybePrompt( + `Enter a new version for ${bold.brightCyan(name)} ${ + $.ansi.dim(`(current: ${underline.bold.brightYellow(version)})`) + }:`, + { + default: semver.format( + semver.increment( + current!, + prerelease.length ? "prerelease" : "patch", ), - }, - ); - } - return v2 ?? version; + ), + }, + ); } - return version; - }, + return v2 ?? version; + } + return version; }, - }); + getVersions, + getLatestVersion, + isTTY, + getJsrMetadata, + getNpmMetadata, + getMetadata, + }, +}); - const { bold, underline, red, yellow } = colors(); +const { bold, underline, red, yellow } = colors(); + +async function main() { + let { name, version, license, author } = denoJson; + const description = + "Standalone implementation of the entire native Math interface, along with other useful type guards, constants, and utilities. Zero dependencies."; const finalOutDir = base.join(OUT_DIR).resolve(); const outDir = await tmp.join(OUT_DIR).resolve().ensureDir(); @@ -192,76 +282,27 @@ async function main() { await build(); - if (Deno.env.get("NO_PUBLISH") !== "1") { + if (env.NO_PUBLISH !== "1") { const publish = !isTTY() || await $.confirm( `🚀 publish ${npmName} to ${red.bold("npm")}?`, { default: true, }, ); - if (publish) await $`cd npm && npm publish --access public`; - } - - async function getJsrMetadata( - name: string, - ): Promise { - try { - return await $.request(`https://jsr.io/${name}/meta.json`) - .timeout("5s") - .showProgress(true).noThrow().json(); - } catch { - return undefined; - } - } - - async function getNpmMetadata( - name: string, - ): Promise { - try { - $.logLight(`🔍 fetching ${red.bold("npm")} package metadata for ${name}`); - return await $.request(`https://registry.npmjs.org/${name}`) - .timeout("5s") - .showProgress(true).noThrow().json(); - } catch { - return undefined; - } - } - - async function getLatestVersion( - name: string, - npm = false, - ): Promise { - const meta = await getVersions(name, npm); - return meta.latest; - } - - async function getVersions(name: string, npm?: boolean): Promise<{ - latest: semver.SemVer | undefined; - versions: semver.SemVer[]; - }> { - let meta: NpmMetadata | JsrMetadata | undefined; - if (npm) { - meta = await getNpmMetadata(npmName); - } else { - meta = await getJsrMetadata(name); - } - - if (meta?.versions) { - const tags = ( - npm ? (meta as NpmMetadata)["dist-tags"] : meta as JsrMetadata - ) ?? {}; - const versions = Object.keys(meta.versions) - .map(semver.tryParse).filter((v) => v != null).sort(semver.compare); - const latest = semver.tryParse(tags.latest ?? "") ?? versions.at(-1); - - return { latest, versions }; + if (publish) { + if (isTTY()) { + const distTag = await $.maybePrompt( + `NPM dist tag to associate with this version`, + { + default: tag, + noClear: true, + }, + ); + if (distTag) tag = distTag; + } + await $`npm publish --access public --registry ${registry} --tag ${tag}` + .cwd("npm"); } - - return { latest: undefined, versions: [] as semver.SemVer[] }; - } - - function isTTY(): boolean { - return Deno.stdout.isTerminal() || Deno.env.get("CI") == null; } async function preBuild() { @@ -280,10 +321,12 @@ async function main() { // necessary so dnt doesn't create a nested src dir in the npm // package (which, while technically functional, is not idiomatic). const indexTs = tmp.join("index.ts"); + let src = await indexTs.readText(); src = src.replace(/\.\/src\//g, "./"); await indexTs.writeText(src); const denoJson = tmp.join("deno.json"); + let json = await denoJson.readText(); json = json.replace(/(?<=")\.\/src\//g, "./"); await denoJson.writeText(json); @@ -303,6 +346,10 @@ async function main() { types: `./esm/${v}.d.ts`, default: `./esm/${v}.js`, }, + "module-sync": { + types: `./esm/${v}.d.ts`, + default: `./esm/${v}.js`, + }, require: { types: `./cjs/${v}.d.ts`, default: `./cjs/${v}.js`, @@ -315,6 +362,7 @@ async function main() { [E in keyof typeof denoJson.exports]: { types: string; import: { types: string; default: string }; + "module-sync"?: { types: string; default: string }; require: { types: string; default: string }; default: string; }; @@ -322,7 +370,6 @@ async function main() { ); const packageJson = { - type: "module", name: npmName, version, license, @@ -330,7 +377,10 @@ async function main() { private: false, publishConfig: { access: "public", + registry, + tag, }, + type: "module", description, keywords: [ "math", @@ -350,9 +400,9 @@ async function main() { homepage: "https://jsr.io/@nick/math/doc", readme: "https://github.com/nberlette/math#readme", bugs: "https://github.com/nberlette/math/issues", + types: exports["."].import.types ?? exports["."].types, main: exports["."].require.default, module: exports["."].import.default, - types: exports["."].import.types ?? exports["."].types, exports, }; @@ -382,11 +432,19 @@ async function main() { async postBuild() { $.logStep("📦 BUILT", `${name}@${version} successfully`); - await outDir.join("script").rename(outDir.join("cjs")); - $.logStep("🚚 MOVED", "./script -> ./cjs"); + const cjsDir = outDir.join("cjs"); + await outDir.join("script").rename(cjsDir); + $.logStep("MOVED", "./script -> ./cjs"); + + const cjsPkgJson = cjsDir.join("package.json"); + await cjsPkgJson.ensureFile(); + $.logStep("CREATE", cjsPkgJson.toString()); + + await cjsPkgJson.writeJsonPretty({ type: "commonjs" }); + $.logStep("UPDATE", ".type='commonjs' in " + cjsPkgJson); await outDir.copy(finalOutDir.resolve(), { overwrite: true }); - $.logStep("🚚 MOVED", `[tmp dir] -> ${finalOutDir}`); + $.logStep("MOVED", `${outDir} [tmp] -> ${finalOutDir}`); }, }); } From f7b547245196512e3ff532be4420b0278db9a236 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Wed, 21 Jan 2026 17:45:54 -0800 Subject: [PATCH 122/132] refactor(atan2): remove unreachable code branches --- src/atan2.ts | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/atan2.ts b/src/atan2.ts index f09031c..409fe4e 100644 --- a/src/atan2.ts +++ b/src/atan2.ts @@ -8,7 +8,6 @@ import { NAN } from "./constants/nan.ts"; import { PI } from "./constants/pi.ts"; import { atan } from "./atan.ts"; import { isNaN } from "./guards/nan.ts"; -import { isFinite } from "./guards/finite.ts"; import { isNegativeZero } from "./guards/negative_zero.ts"; import { isNegativeInfinity } from "./guards/negative_infinity.ts"; import { isPositiveInfinity } from "./guards/positive_infinity.ts"; @@ -29,8 +28,10 @@ export function atan2(y: number, x: number): number { // fast paths for special cases if (isNaN(y) || isNaN(x)) return NAN; if (y === 0 && x === 0) { - const sign = isNegativeZero(y) ? -1 : 1; - return (isNegativeZero(x) ? PI : 0) * sign; + if (isNegativeZero(y) && isNegativeZero(x)) return -PI; + if (isNegativeZero(y)) return -0; + if (isNegativeZero(x)) return PI; + return 0; } if (x === 0) { if (y > 0) return PI_OVER_2; @@ -46,16 +47,8 @@ export function atan2(y: number, x: number): number { } else if (isNegativeInfinity(x)) { if (isPositiveInfinity(y)) return 3 * PI_OVER_4; if (isNegativeInfinity(y)) return -3 * PI_OVER_4; - // deno-coverage-ignore-start - return y < 0 || isNegativeZero(y) ? -PI : PI; - } else if (isFinite(x) && !isFinite(y)) { - return y > 0 ? PI_OVER_2 : -PI_OVER_2; - } else if (!isFinite(x) && isFinite(y)) { - // preserve the sign of y for -0 - if (x > 0) return isNegativeZero(y) || y < 0 ? -0 : 0; return y < 0 || isNegativeZero(y) ? -PI : PI; } - // deno-coverage-ignore-stop if (x > 0) return atan(y / x); if (x < 0) return atan(y / x) + (y < 0 || isNegativeZero(y) ? -PI : PI); From 888ba21ce244caef212f5584b9f4485325104ca2 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Wed, 21 Jan 2026 17:47:26 -0800 Subject: [PATCH 123/132] config: update exclusions for linting, testing, formatting --- deno.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/deno.json b/deno.json index c932a1c..7b37f77 100644 --- a/deno.json +++ b/deno.json @@ -133,10 +133,14 @@ "rules": { "exclude": ["no-import-prefix", "no-explicit-any"], "tags": ["recommended"] - } + }, + "exclude": ["npm", "docs"] }, "fmt": { - "exclude": ["docs", "**/*.min.*"] + "exclude": ["**/*.min.*"] + }, + "test": { + "exclude": ["npm", "docs"] }, "publish": { "include": [ From 229ad1de8153d9cf828115bd0f2b688d67eceb1f Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Wed, 21 Jan 2026 18:04:26 -0800 Subject: [PATCH 124/132] fix: lint errors --- scripts/build.ts | 2 +- src/trigonometry.test.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/build.ts b/scripts/build.ts index 2d5da70..257141f 100755 --- a/scripts/build.ts +++ b/scripts/build.ts @@ -127,7 +127,7 @@ function isTTY(): boolean { return process.stdout.isTTY || env.CI == null; } -let registry = env.NPM_REGISTRY_URL || env.NPM_REGISTRY || +const registry = env.NPM_REGISTRY_URL || env.NPM_REGISTRY || env.NPM_CONFIG_REGISTRY || "https://registry.npmjs.org"; let tag = env.DIST_TAG || env.NPM_DIST_TAG || "latest"; diff --git a/src/trigonometry.test.ts b/src/trigonometry.test.ts index 550b70b..5e1ed6f 100644 --- a/src/trigonometry.test.ts +++ b/src/trigonometry.test.ts @@ -1,4 +1,3 @@ -import assert from "node:assert"; import { describe, it } from "node:test"; import { assertClose } from "./internal/_test_utils.ts"; import { From 2336ceef53c55ef5151dec6990ba902686c248b3 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Fri, 23 Jan 2026 06:06:27 -0800 Subject: [PATCH 125/132] fix(atanh): align behavior with native implementation --- src/atanh.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/atanh.ts b/src/atanh.ts index d10c072..e99f01f 100644 --- a/src/atanh.ts +++ b/src/atanh.ts @@ -6,7 +6,7 @@ */ import { isNaN, NAN } from "./guards/nan.ts"; import { POSITIVE_INFINITY } from "./constants/positive_infinity.ts"; -import { log } from "./log.ts"; +import { log1p } from "./log1p.ts"; /** * Calculates the inverse hyperbolic tangent of a number, returning a value in @@ -21,5 +21,6 @@ export function atanh(x: number): number { if (isNaN(x) || x < -1 || x > 1) return NAN; if (x === -1 || x === 1) return x * POSITIVE_INFINITY; if (x === 0) return x; - return 0.5 * log((1 + x) / (1 - x)); + // Use log1p for better precision near 0 and to match native behavior. + return 0.5 * log1p((2 * x) / (1 - x)); } From bb3e0613097e0b1d24801f8c2d894456a86decb9 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Fri, 23 Jan 2026 06:06:58 -0800 Subject: [PATCH 126/132] fix(log): ensure output matches Math.log --- src/log.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/log.ts b/src/log.ts index ab82df5..bffde54 100644 --- a/src/log.ts +++ b/src/log.ts @@ -23,6 +23,7 @@ export function log(x: number): number { if (x === 1) return 0; // 0 for x = 1 if (x === POSITIVE_INFINITY) return x; // Infinity for x = Infinity + const seriesEpsilon = EPSILON * 16; let n = 0; while (x > 2) x /= 2, n++; @@ -30,7 +31,7 @@ export function log(x: number): number { let sum = 0, term = z, i = 1; // series expansion for ln(1+z) converges faster when z is [-1, 1] - while (abs(term) >= EPSILON) { + while (abs(term) >= seriesEpsilon) { sum += term / i; term *= z2; i += 2; From d066b07b603cc4c33961fddf1368aedb97acef4b Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Fri, 23 Jan 2026 06:07:48 -0800 Subject: [PATCH 127/132] docs(readme): improve testable examples in readme --- README.md | 52 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index f6af3e2..0ef4683 100644 --- a/README.md +++ b/README.md @@ -380,9 +380,10 @@ Returns the arccosine of a number. ```ts import { acos } from "@nick/math/acos"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(acos(0.5) - 1.0471975511965979) < 1e-9); +assert.ok(abs(acos(0.5) - Math.acos(0.5)) < 1e-9); ``` #### `acosh` @@ -402,9 +403,10 @@ Returns the arcsine of a number. ```ts import { asin } from "@nick/math/asin"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(asin(0.5) - 0.5235987755982989) < 1e-9); +assert.ok(abs(asin(0.5) - Math.asin(0.5)) < 1e-9); ``` #### `asinh` @@ -413,9 +415,10 @@ Returns the inverse hyperbolic sine of a number. ```ts import { asinh } from "@nick/math/asinh"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(asinh(0.5) - 0.48121182505960347) < 1e-9); +assert.ok(abs(asinh(0.5) - Math.asinh(0.5)) < 1e-9); ``` #### `atan` @@ -424,9 +427,10 @@ Returns the arctangent of a number. ```ts import { atan } from "@nick/math/atan"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(atan(0.5) - 0.4636476090008061) < 1e-9); +assert.ok(abs(atan(0.5) - Math.atan(0.5)) < 1e-9); ``` #### `atan2` @@ -437,7 +441,7 @@ Returns the arctangent of the quotient of its arguments. import { atan2 } from "@nick/math/atan2"; import assert from "node:assert"; -assert.strictEqual(atan2(1, 1), 0.7853981633974483); +assert.strictEqual(atan2(1, 1), Math.atan2(1, 1)); ``` #### `atanh` @@ -448,7 +452,7 @@ Returns the inverse hyperbolic tangent of a number. import { atanh } from "@nick/math/atanh"; import assert from "node:assert"; -assert.strictEqual(atanh(0.5), 0.5493061443340549); +assert.strictEqual(atanh(0.5), Math.atanh(0.5)); ``` #### `cbrt` @@ -491,9 +495,10 @@ Returns the cosine of a number. ```ts import { cos } from "@nick/math/cos"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(cos(0.5) - 0.8775825618903728) < 1e-9); +assert.ok(abs(cos(0.5) - Math.cos(0.5)) < 1e-9); ``` #### `cosh` @@ -502,9 +507,10 @@ Returns the hyperbolic cosine of a number. ```ts import { cosh } from "@nick/math/cosh"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(cosh(0.5) - 1.1276259652063807) < 1e-9); +assert.ok(abs(cosh(0.5) - Math.cosh(0.5)) < 1e-9); ``` #### `exp` @@ -513,9 +519,10 @@ Returns `E` raised to the power of a number. ```ts import { exp } from "@nick/math/exp"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(exp(1) - 2.718281828459045) < 1e-9); +assert.ok(abs(exp(1) - Math.exp(1)) < 1e-9); ``` #### `expm1` @@ -524,9 +531,10 @@ Returns `E` raised to the power of a number, minus `1`. ```ts import { expm1 } from "@nick/math/expm1"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(expm1(1) - 1.718281828459045) < 1e-9); +assert.ok(abs(expm1(1) - Math.expm1(1)) < 1e-9); ``` #### `floor` @@ -595,9 +603,10 @@ Returns the natural logarithm of a number. ```ts import { log } from "@nick/math/log"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(log(9) - 2.1972245773362196) < 1e-9); +assert.ok(abs(log(9) - Math.log(9)) < 1e-9); ``` #### `log1p` @@ -606,9 +615,10 @@ Returns the natural logarithm of `1` plus a number. ```ts import { log1p } from "@nick/math/log1p"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(log1p(9) - 2.302585092994046) < 1e-9); +assert.ok(abs(log1p(9) - Math.log1p(9)) < 1e-9); ``` #### `log10` @@ -617,9 +627,10 @@ Returns the base 10 logarithm of a number. ```ts import { log10 } from "@nick/math/log10"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(log10(100) - 2) < 1e-9); +assert.ok(abs(log10(100) - Math.log10(100)) < 1e-9); ``` #### `log2` @@ -628,9 +639,10 @@ Returns the base 2 logarithm of a number. ```ts import { log2 } from "@nick/math/log2"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(log2(8) - 3) < 1e-9); +assert.ok(abs(log2(8) - Math.log2(8)) < 1e-9); ``` #### `max` @@ -708,9 +720,10 @@ Returns the sine of a number. ```ts import { sin } from "@nick/math/sin"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(sin(0.5) - 0.479425538604203) < 1e-9); +assert.ok(abs(sin(0.5) - Math.sin(0.5)) < 1e-9); ``` #### `sinh` @@ -719,9 +732,10 @@ Returns the hyperbolic sine of a number. ```ts import { sinh } from "@nick/math/sinh"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(sinh(0.5) - 0.5210953054937474) < 1e-9); +assert.ok(abs(sinh(0.5) - Math.sinh(0.5)) < 1e-9); ``` #### `sqrt` @@ -741,9 +755,10 @@ Returns the tangent of a number. ```ts import { tan } from "@nick/math/tan"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(tan(0.5) - 0.5463024898437905) < 1e-9); +assert.ok(abs(tan(0.5) - Math.tan(0.5)) < 1e-9); ``` #### `tanh` @@ -752,9 +767,10 @@ Returns the hyperbolic tangent of a number. ```ts import { tanh } from "@nick/math/tanh"; +import { abs } from "@nick/math/abs"; import assert from "node:assert"; -assert.ok(Math.abs(tanh(0.5) - 0.46211715726000974) < 1e-9); +assert.ok(abs(tanh(0.5) - Math.tanh(0.5)) < 1e-9); ``` #### `trunc` From cd01802ec84295c66c1fbb8fb09aac784d51118b Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Fri, 23 Jan 2026 06:08:20 -0800 Subject: [PATCH 128/132] config: use deno task instead of deno run --- deno.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deno.json b/deno.json index 7b37f77..cafda91 100644 --- a/deno.json +++ b/deno.json @@ -12,7 +12,7 @@ "tasks": { "build": "deno run -Aq scripts/build.ts", "test": "deno test -A --no-check=remote --coverage=.coverage --clean --parallel --doc", - "ok": "deno fmt --check && deno lint src && deno run test", + "ok": "deno fmt --check && deno lint src && deno task test", "fix": "deno fmt && deno lint --fix src" }, "exports": { From ff5378a7d4b979897d8bd6fbbdda74378e7f5f64 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Fri, 23 Jan 2026 06:08:35 -0800 Subject: [PATCH 129/132] chore: update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 947aa48..d46ffff 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ Thumbs.db coverage .cov npm +!deno.lock From 32576b154caf42bb4c6834c4ae2ce6f07d402976 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Fri, 23 Jan 2026 17:56:08 -0800 Subject: [PATCH 130/132] refactor(tests): move all .test.ts files into an isolated tests dir --- {src => tests}/abs.test.ts | 0 {src => tests}/acos.test.ts | 0 {src => tests}/acosh.test.ts | 0 {src => tests}/asin.test.ts | 0 {src => tests}/asinh.test.ts | 0 {src => tests}/atan.test.ts | 0 {src => tests}/atan2.test.ts | 0 {src => tests}/atanh.test.ts | 0 {src => tests}/cbrt.test.ts | 0 {src => tests}/ceil.test.ts | 0 {src => tests}/clamp.test.ts | 0 {src => tests}/clz32.test.ts | 0 {src => tests}/constants.test.ts | 0 {src => tests}/constants/e.test.ts | 0 {src => tests}/constants/epsilon.test.ts | 0 {src => tests}/constants/index.test.ts | 0 {src => tests}/constants/infinity.test.ts | 0 {src => tests}/constants/ln10.test.ts | 0 {src => tests}/constants/ln2.test.ts | 0 {src => tests}/constants/log10e.test.ts | 0 {src => tests}/constants/log2e.test.ts | 0 {src => tests}/constants/max_safe_integer.test.ts | 0 {src => tests}/constants/max_value.test.ts | 0 {src => tests}/constants/min_safe_integer.test.ts | 0 {src => tests}/constants/min_value.test.ts | 0 {src => tests}/constants/nan.test.ts | 0 {src => tests}/constants/negative_infinity.test.ts | 0 {src => tests}/constants/negative_zero.test.ts | 0 {src => tests}/constants/pi.test.ts | 0 {src => tests}/constants/positive_infinity.test.ts | 0 {src => tests}/constants/positive_zero.test.ts | 0 {src => tests}/constants/sqrt1_2.test.ts | 0 {src => tests}/constants/sqrt2.test.ts | 0 {src => tests}/cos.test.ts | 0 {src => tests}/cosh.test.ts | 0 {src => tests}/exp.test.ts | 0 {src => tests}/expm1.test.ts | 0 {src => tests}/f16round.test.ts | 0 {src => tests}/float16/constants.test.ts | 0 {src => tests}/float16/decode.test.ts | 0 {src => tests}/float16/encode.test.ts | 0 {src => tests}/float16/guards.test.ts | 0 {src => tests}/float16/index.test.ts | 0 {src => tests}/float16/round.test.ts | 0 {src => tests}/float32/constants.test.ts | 0 {src => tests}/float32/decode.test.ts | 0 {src => tests}/float32/encode.test.ts | 0 {src => tests}/float32/guards.test.ts | 0 {src => tests}/float32/index.test.ts | 0 {src => tests}/float32/round.test.ts | 0 {src => tests}/floor.test.ts | 0 {src => tests}/fround.test.ts | 0 {src => tests}/guards/finite.test.ts | 0 {src => tests}/guards/index.test.ts | 0 {src => tests}/guards/infinity.test.ts | 0 {src => tests}/guards/integer.test.ts | 0 {src => tests}/guards/nan.test.ts | 0 {src => tests}/guards/negative_infinity.test.ts | 0 {src => tests}/guards/negative_zero.test.ts | 0 {src => tests}/guards/positive_infinity.test.ts | 0 {src => tests}/guards/positive_zero.test.ts | 0 {src => tests}/guards/safe_integer.test.ts | 0 {src => tests}/hypot.test.ts | 0 {src => tests}/ieee754.test.ts | 0 {src => tests}/imul.test.ts | 0 {src => tests}/index.test.ts | 0 {src => tests}/log.test.ts | 0 {src => tests}/log10.test.ts | 0 {src => tests}/log1p.test.ts | 0 {src => tests}/log2.test.ts | 0 {src => tests}/max.test.ts | 0 {src => tests}/min.test.ts | 0 {src => tests}/pow.test.ts | 0 {src => tests}/random.test.ts | 0 {src => tests}/round.test.ts | 0 {src => tests}/sign.test.ts | 0 {src => tests}/sin.test.ts | 0 {src => tests}/sinh.test.ts | 0 {src => tests}/sqrt.test.ts | 0 {src => tests}/tan.test.ts | 0 {src => tests}/tanh.test.ts | 0 {src => tests}/trigonometry.test.ts | 0 {src => tests}/trunc.test.ts | 0 {src => tests}/types/finite.test.ts | 0 {src => tests}/types/float.test.ts | 0 {src => tests}/types/index.test.ts | 0 {src => tests}/types/integer.test.ts | 0 {src => tests}/types/precision.test.ts | 0 {src => tests}/types/safe_integer.test.ts | 0 89 files changed, 0 insertions(+), 0 deletions(-) rename {src => tests}/abs.test.ts (100%) rename {src => tests}/acos.test.ts (100%) rename {src => tests}/acosh.test.ts (100%) rename {src => tests}/asin.test.ts (100%) rename {src => tests}/asinh.test.ts (100%) rename {src => tests}/atan.test.ts (100%) rename {src => tests}/atan2.test.ts (100%) rename {src => tests}/atanh.test.ts (100%) rename {src => tests}/cbrt.test.ts (100%) rename {src => tests}/ceil.test.ts (100%) rename {src => tests}/clamp.test.ts (100%) rename {src => tests}/clz32.test.ts (100%) rename {src => tests}/constants.test.ts (100%) rename {src => tests}/constants/e.test.ts (100%) rename {src => tests}/constants/epsilon.test.ts (100%) rename {src => tests}/constants/index.test.ts (100%) rename {src => tests}/constants/infinity.test.ts (100%) rename {src => tests}/constants/ln10.test.ts (100%) rename {src => tests}/constants/ln2.test.ts (100%) rename {src => tests}/constants/log10e.test.ts (100%) rename {src => tests}/constants/log2e.test.ts (100%) rename {src => tests}/constants/max_safe_integer.test.ts (100%) rename {src => tests}/constants/max_value.test.ts (100%) rename {src => tests}/constants/min_safe_integer.test.ts (100%) rename {src => tests}/constants/min_value.test.ts (100%) rename {src => tests}/constants/nan.test.ts (100%) rename {src => tests}/constants/negative_infinity.test.ts (100%) rename {src => tests}/constants/negative_zero.test.ts (100%) rename {src => tests}/constants/pi.test.ts (100%) rename {src => tests}/constants/positive_infinity.test.ts (100%) rename {src => tests}/constants/positive_zero.test.ts (100%) rename {src => tests}/constants/sqrt1_2.test.ts (100%) rename {src => tests}/constants/sqrt2.test.ts (100%) rename {src => tests}/cos.test.ts (100%) rename {src => tests}/cosh.test.ts (100%) rename {src => tests}/exp.test.ts (100%) rename {src => tests}/expm1.test.ts (100%) rename {src => tests}/f16round.test.ts (100%) rename {src => tests}/float16/constants.test.ts (100%) rename {src => tests}/float16/decode.test.ts (100%) rename {src => tests}/float16/encode.test.ts (100%) rename {src => tests}/float16/guards.test.ts (100%) rename {src => tests}/float16/index.test.ts (100%) rename {src => tests}/float16/round.test.ts (100%) rename {src => tests}/float32/constants.test.ts (100%) rename {src => tests}/float32/decode.test.ts (100%) rename {src => tests}/float32/encode.test.ts (100%) rename {src => tests}/float32/guards.test.ts (100%) rename {src => tests}/float32/index.test.ts (100%) rename {src => tests}/float32/round.test.ts (100%) rename {src => tests}/floor.test.ts (100%) rename {src => tests}/fround.test.ts (100%) rename {src => tests}/guards/finite.test.ts (100%) rename {src => tests}/guards/index.test.ts (100%) rename {src => tests}/guards/infinity.test.ts (100%) rename {src => tests}/guards/integer.test.ts (100%) rename {src => tests}/guards/nan.test.ts (100%) rename {src => tests}/guards/negative_infinity.test.ts (100%) rename {src => tests}/guards/negative_zero.test.ts (100%) rename {src => tests}/guards/positive_infinity.test.ts (100%) rename {src => tests}/guards/positive_zero.test.ts (100%) rename {src => tests}/guards/safe_integer.test.ts (100%) rename {src => tests}/hypot.test.ts (100%) rename {src => tests}/ieee754.test.ts (100%) rename {src => tests}/imul.test.ts (100%) rename {src => tests}/index.test.ts (100%) rename {src => tests}/log.test.ts (100%) rename {src => tests}/log10.test.ts (100%) rename {src => tests}/log1p.test.ts (100%) rename {src => tests}/log2.test.ts (100%) rename {src => tests}/max.test.ts (100%) rename {src => tests}/min.test.ts (100%) rename {src => tests}/pow.test.ts (100%) rename {src => tests}/random.test.ts (100%) rename {src => tests}/round.test.ts (100%) rename {src => tests}/sign.test.ts (100%) rename {src => tests}/sin.test.ts (100%) rename {src => tests}/sinh.test.ts (100%) rename {src => tests}/sqrt.test.ts (100%) rename {src => tests}/tan.test.ts (100%) rename {src => tests}/tanh.test.ts (100%) rename {src => tests}/trigonometry.test.ts (100%) rename {src => tests}/trunc.test.ts (100%) rename {src => tests}/types/finite.test.ts (100%) rename {src => tests}/types/float.test.ts (100%) rename {src => tests}/types/index.test.ts (100%) rename {src => tests}/types/integer.test.ts (100%) rename {src => tests}/types/precision.test.ts (100%) rename {src => tests}/types/safe_integer.test.ts (100%) diff --git a/src/abs.test.ts b/tests/abs.test.ts similarity index 100% rename from src/abs.test.ts rename to tests/abs.test.ts diff --git a/src/acos.test.ts b/tests/acos.test.ts similarity index 100% rename from src/acos.test.ts rename to tests/acos.test.ts diff --git a/src/acosh.test.ts b/tests/acosh.test.ts similarity index 100% rename from src/acosh.test.ts rename to tests/acosh.test.ts diff --git a/src/asin.test.ts b/tests/asin.test.ts similarity index 100% rename from src/asin.test.ts rename to tests/asin.test.ts diff --git a/src/asinh.test.ts b/tests/asinh.test.ts similarity index 100% rename from src/asinh.test.ts rename to tests/asinh.test.ts diff --git a/src/atan.test.ts b/tests/atan.test.ts similarity index 100% rename from src/atan.test.ts rename to tests/atan.test.ts diff --git a/src/atan2.test.ts b/tests/atan2.test.ts similarity index 100% rename from src/atan2.test.ts rename to tests/atan2.test.ts diff --git a/src/atanh.test.ts b/tests/atanh.test.ts similarity index 100% rename from src/atanh.test.ts rename to tests/atanh.test.ts diff --git a/src/cbrt.test.ts b/tests/cbrt.test.ts similarity index 100% rename from src/cbrt.test.ts rename to tests/cbrt.test.ts diff --git a/src/ceil.test.ts b/tests/ceil.test.ts similarity index 100% rename from src/ceil.test.ts rename to tests/ceil.test.ts diff --git a/src/clamp.test.ts b/tests/clamp.test.ts similarity index 100% rename from src/clamp.test.ts rename to tests/clamp.test.ts diff --git a/src/clz32.test.ts b/tests/clz32.test.ts similarity index 100% rename from src/clz32.test.ts rename to tests/clz32.test.ts diff --git a/src/constants.test.ts b/tests/constants.test.ts similarity index 100% rename from src/constants.test.ts rename to tests/constants.test.ts diff --git a/src/constants/e.test.ts b/tests/constants/e.test.ts similarity index 100% rename from src/constants/e.test.ts rename to tests/constants/e.test.ts diff --git a/src/constants/epsilon.test.ts b/tests/constants/epsilon.test.ts similarity index 100% rename from src/constants/epsilon.test.ts rename to tests/constants/epsilon.test.ts diff --git a/src/constants/index.test.ts b/tests/constants/index.test.ts similarity index 100% rename from src/constants/index.test.ts rename to tests/constants/index.test.ts diff --git a/src/constants/infinity.test.ts b/tests/constants/infinity.test.ts similarity index 100% rename from src/constants/infinity.test.ts rename to tests/constants/infinity.test.ts diff --git a/src/constants/ln10.test.ts b/tests/constants/ln10.test.ts similarity index 100% rename from src/constants/ln10.test.ts rename to tests/constants/ln10.test.ts diff --git a/src/constants/ln2.test.ts b/tests/constants/ln2.test.ts similarity index 100% rename from src/constants/ln2.test.ts rename to tests/constants/ln2.test.ts diff --git a/src/constants/log10e.test.ts b/tests/constants/log10e.test.ts similarity index 100% rename from src/constants/log10e.test.ts rename to tests/constants/log10e.test.ts diff --git a/src/constants/log2e.test.ts b/tests/constants/log2e.test.ts similarity index 100% rename from src/constants/log2e.test.ts rename to tests/constants/log2e.test.ts diff --git a/src/constants/max_safe_integer.test.ts b/tests/constants/max_safe_integer.test.ts similarity index 100% rename from src/constants/max_safe_integer.test.ts rename to tests/constants/max_safe_integer.test.ts diff --git a/src/constants/max_value.test.ts b/tests/constants/max_value.test.ts similarity index 100% rename from src/constants/max_value.test.ts rename to tests/constants/max_value.test.ts diff --git a/src/constants/min_safe_integer.test.ts b/tests/constants/min_safe_integer.test.ts similarity index 100% rename from src/constants/min_safe_integer.test.ts rename to tests/constants/min_safe_integer.test.ts diff --git a/src/constants/min_value.test.ts b/tests/constants/min_value.test.ts similarity index 100% rename from src/constants/min_value.test.ts rename to tests/constants/min_value.test.ts diff --git a/src/constants/nan.test.ts b/tests/constants/nan.test.ts similarity index 100% rename from src/constants/nan.test.ts rename to tests/constants/nan.test.ts diff --git a/src/constants/negative_infinity.test.ts b/tests/constants/negative_infinity.test.ts similarity index 100% rename from src/constants/negative_infinity.test.ts rename to tests/constants/negative_infinity.test.ts diff --git a/src/constants/negative_zero.test.ts b/tests/constants/negative_zero.test.ts similarity index 100% rename from src/constants/negative_zero.test.ts rename to tests/constants/negative_zero.test.ts diff --git a/src/constants/pi.test.ts b/tests/constants/pi.test.ts similarity index 100% rename from src/constants/pi.test.ts rename to tests/constants/pi.test.ts diff --git a/src/constants/positive_infinity.test.ts b/tests/constants/positive_infinity.test.ts similarity index 100% rename from src/constants/positive_infinity.test.ts rename to tests/constants/positive_infinity.test.ts diff --git a/src/constants/positive_zero.test.ts b/tests/constants/positive_zero.test.ts similarity index 100% rename from src/constants/positive_zero.test.ts rename to tests/constants/positive_zero.test.ts diff --git a/src/constants/sqrt1_2.test.ts b/tests/constants/sqrt1_2.test.ts similarity index 100% rename from src/constants/sqrt1_2.test.ts rename to tests/constants/sqrt1_2.test.ts diff --git a/src/constants/sqrt2.test.ts b/tests/constants/sqrt2.test.ts similarity index 100% rename from src/constants/sqrt2.test.ts rename to tests/constants/sqrt2.test.ts diff --git a/src/cos.test.ts b/tests/cos.test.ts similarity index 100% rename from src/cos.test.ts rename to tests/cos.test.ts diff --git a/src/cosh.test.ts b/tests/cosh.test.ts similarity index 100% rename from src/cosh.test.ts rename to tests/cosh.test.ts diff --git a/src/exp.test.ts b/tests/exp.test.ts similarity index 100% rename from src/exp.test.ts rename to tests/exp.test.ts diff --git a/src/expm1.test.ts b/tests/expm1.test.ts similarity index 100% rename from src/expm1.test.ts rename to tests/expm1.test.ts diff --git a/src/f16round.test.ts b/tests/f16round.test.ts similarity index 100% rename from src/f16round.test.ts rename to tests/f16round.test.ts diff --git a/src/float16/constants.test.ts b/tests/float16/constants.test.ts similarity index 100% rename from src/float16/constants.test.ts rename to tests/float16/constants.test.ts diff --git a/src/float16/decode.test.ts b/tests/float16/decode.test.ts similarity index 100% rename from src/float16/decode.test.ts rename to tests/float16/decode.test.ts diff --git a/src/float16/encode.test.ts b/tests/float16/encode.test.ts similarity index 100% rename from src/float16/encode.test.ts rename to tests/float16/encode.test.ts diff --git a/src/float16/guards.test.ts b/tests/float16/guards.test.ts similarity index 100% rename from src/float16/guards.test.ts rename to tests/float16/guards.test.ts diff --git a/src/float16/index.test.ts b/tests/float16/index.test.ts similarity index 100% rename from src/float16/index.test.ts rename to tests/float16/index.test.ts diff --git a/src/float16/round.test.ts b/tests/float16/round.test.ts similarity index 100% rename from src/float16/round.test.ts rename to tests/float16/round.test.ts diff --git a/src/float32/constants.test.ts b/tests/float32/constants.test.ts similarity index 100% rename from src/float32/constants.test.ts rename to tests/float32/constants.test.ts diff --git a/src/float32/decode.test.ts b/tests/float32/decode.test.ts similarity index 100% rename from src/float32/decode.test.ts rename to tests/float32/decode.test.ts diff --git a/src/float32/encode.test.ts b/tests/float32/encode.test.ts similarity index 100% rename from src/float32/encode.test.ts rename to tests/float32/encode.test.ts diff --git a/src/float32/guards.test.ts b/tests/float32/guards.test.ts similarity index 100% rename from src/float32/guards.test.ts rename to tests/float32/guards.test.ts diff --git a/src/float32/index.test.ts b/tests/float32/index.test.ts similarity index 100% rename from src/float32/index.test.ts rename to tests/float32/index.test.ts diff --git a/src/float32/round.test.ts b/tests/float32/round.test.ts similarity index 100% rename from src/float32/round.test.ts rename to tests/float32/round.test.ts diff --git a/src/floor.test.ts b/tests/floor.test.ts similarity index 100% rename from src/floor.test.ts rename to tests/floor.test.ts diff --git a/src/fround.test.ts b/tests/fround.test.ts similarity index 100% rename from src/fround.test.ts rename to tests/fround.test.ts diff --git a/src/guards/finite.test.ts b/tests/guards/finite.test.ts similarity index 100% rename from src/guards/finite.test.ts rename to tests/guards/finite.test.ts diff --git a/src/guards/index.test.ts b/tests/guards/index.test.ts similarity index 100% rename from src/guards/index.test.ts rename to tests/guards/index.test.ts diff --git a/src/guards/infinity.test.ts b/tests/guards/infinity.test.ts similarity index 100% rename from src/guards/infinity.test.ts rename to tests/guards/infinity.test.ts diff --git a/src/guards/integer.test.ts b/tests/guards/integer.test.ts similarity index 100% rename from src/guards/integer.test.ts rename to tests/guards/integer.test.ts diff --git a/src/guards/nan.test.ts b/tests/guards/nan.test.ts similarity index 100% rename from src/guards/nan.test.ts rename to tests/guards/nan.test.ts diff --git a/src/guards/negative_infinity.test.ts b/tests/guards/negative_infinity.test.ts similarity index 100% rename from src/guards/negative_infinity.test.ts rename to tests/guards/negative_infinity.test.ts diff --git a/src/guards/negative_zero.test.ts b/tests/guards/negative_zero.test.ts similarity index 100% rename from src/guards/negative_zero.test.ts rename to tests/guards/negative_zero.test.ts diff --git a/src/guards/positive_infinity.test.ts b/tests/guards/positive_infinity.test.ts similarity index 100% rename from src/guards/positive_infinity.test.ts rename to tests/guards/positive_infinity.test.ts diff --git a/src/guards/positive_zero.test.ts b/tests/guards/positive_zero.test.ts similarity index 100% rename from src/guards/positive_zero.test.ts rename to tests/guards/positive_zero.test.ts diff --git a/src/guards/safe_integer.test.ts b/tests/guards/safe_integer.test.ts similarity index 100% rename from src/guards/safe_integer.test.ts rename to tests/guards/safe_integer.test.ts diff --git a/src/hypot.test.ts b/tests/hypot.test.ts similarity index 100% rename from src/hypot.test.ts rename to tests/hypot.test.ts diff --git a/src/ieee754.test.ts b/tests/ieee754.test.ts similarity index 100% rename from src/ieee754.test.ts rename to tests/ieee754.test.ts diff --git a/src/imul.test.ts b/tests/imul.test.ts similarity index 100% rename from src/imul.test.ts rename to tests/imul.test.ts diff --git a/src/index.test.ts b/tests/index.test.ts similarity index 100% rename from src/index.test.ts rename to tests/index.test.ts diff --git a/src/log.test.ts b/tests/log.test.ts similarity index 100% rename from src/log.test.ts rename to tests/log.test.ts diff --git a/src/log10.test.ts b/tests/log10.test.ts similarity index 100% rename from src/log10.test.ts rename to tests/log10.test.ts diff --git a/src/log1p.test.ts b/tests/log1p.test.ts similarity index 100% rename from src/log1p.test.ts rename to tests/log1p.test.ts diff --git a/src/log2.test.ts b/tests/log2.test.ts similarity index 100% rename from src/log2.test.ts rename to tests/log2.test.ts diff --git a/src/max.test.ts b/tests/max.test.ts similarity index 100% rename from src/max.test.ts rename to tests/max.test.ts diff --git a/src/min.test.ts b/tests/min.test.ts similarity index 100% rename from src/min.test.ts rename to tests/min.test.ts diff --git a/src/pow.test.ts b/tests/pow.test.ts similarity index 100% rename from src/pow.test.ts rename to tests/pow.test.ts diff --git a/src/random.test.ts b/tests/random.test.ts similarity index 100% rename from src/random.test.ts rename to tests/random.test.ts diff --git a/src/round.test.ts b/tests/round.test.ts similarity index 100% rename from src/round.test.ts rename to tests/round.test.ts diff --git a/src/sign.test.ts b/tests/sign.test.ts similarity index 100% rename from src/sign.test.ts rename to tests/sign.test.ts diff --git a/src/sin.test.ts b/tests/sin.test.ts similarity index 100% rename from src/sin.test.ts rename to tests/sin.test.ts diff --git a/src/sinh.test.ts b/tests/sinh.test.ts similarity index 100% rename from src/sinh.test.ts rename to tests/sinh.test.ts diff --git a/src/sqrt.test.ts b/tests/sqrt.test.ts similarity index 100% rename from src/sqrt.test.ts rename to tests/sqrt.test.ts diff --git a/src/tan.test.ts b/tests/tan.test.ts similarity index 100% rename from src/tan.test.ts rename to tests/tan.test.ts diff --git a/src/tanh.test.ts b/tests/tanh.test.ts similarity index 100% rename from src/tanh.test.ts rename to tests/tanh.test.ts diff --git a/src/trigonometry.test.ts b/tests/trigonometry.test.ts similarity index 100% rename from src/trigonometry.test.ts rename to tests/trigonometry.test.ts diff --git a/src/trunc.test.ts b/tests/trunc.test.ts similarity index 100% rename from src/trunc.test.ts rename to tests/trunc.test.ts diff --git a/src/types/finite.test.ts b/tests/types/finite.test.ts similarity index 100% rename from src/types/finite.test.ts rename to tests/types/finite.test.ts diff --git a/src/types/float.test.ts b/tests/types/float.test.ts similarity index 100% rename from src/types/float.test.ts rename to tests/types/float.test.ts diff --git a/src/types/index.test.ts b/tests/types/index.test.ts similarity index 100% rename from src/types/index.test.ts rename to tests/types/index.test.ts diff --git a/src/types/integer.test.ts b/tests/types/integer.test.ts similarity index 100% rename from src/types/integer.test.ts rename to tests/types/integer.test.ts diff --git a/src/types/precision.test.ts b/tests/types/precision.test.ts similarity index 100% rename from src/types/precision.test.ts rename to tests/types/precision.test.ts diff --git a/src/types/safe_integer.test.ts b/tests/types/safe_integer.test.ts similarity index 100% rename from src/types/safe_integer.test.ts rename to tests/types/safe_integer.test.ts From 904b5f4db9f371e72668dd6950272296e16cd53c Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Fri, 23 Jan 2026 17:57:58 -0800 Subject: [PATCH 131/132] fix(tests): update import paths for all test files --- tests/abs.test.ts | 4 ++-- tests/acos.test.ts | 4 ++-- tests/acosh.test.ts | 4 ++-- tests/asin.test.ts | 4 ++-- tests/asinh.test.ts | 4 ++-- tests/atan.test.ts | 4 ++-- tests/atan2.test.ts | 8 ++++---- tests/atanh.test.ts | 4 ++-- tests/cbrt.test.ts | 4 ++-- tests/ceil.test.ts | 4 ++-- tests/clamp.test.ts | 2 +- tests/clz32.test.ts | 4 ++-- tests/constants.test.ts | 4 ++-- tests/constants/e.test.ts | 2 +- tests/constants/epsilon.test.ts | 2 +- tests/constants/index.test.ts | 2 +- tests/constants/infinity.test.ts | 2 +- tests/constants/ln10.test.ts | 2 +- tests/constants/ln2.test.ts | 2 +- tests/constants/log10e.test.ts | 2 +- tests/constants/log2e.test.ts | 2 +- tests/constants/max_safe_integer.test.ts | 2 +- tests/constants/max_value.test.ts | 2 +- tests/constants/min_safe_integer.test.ts | 2 +- tests/constants/min_value.test.ts | 2 +- tests/constants/nan.test.ts | 2 +- tests/constants/negative_infinity.test.ts | 2 +- tests/constants/negative_zero.test.ts | 2 +- tests/constants/pi.test.ts | 2 +- tests/constants/positive_infinity.test.ts | 2 +- tests/constants/positive_zero.test.ts | 2 +- tests/constants/sqrt1_2.test.ts | 2 +- tests/constants/sqrt2.test.ts | 2 +- tests/cos.test.ts | 4 ++-- tests/cosh.test.ts | 4 ++-- tests/exp.test.ts | 4 ++-- tests/expm1.test.ts | 4 ++-- tests/f16round.test.ts | 4 ++-- tests/float16/constants.test.ts | 2 +- tests/float16/decode.test.ts | 2 +- tests/float16/encode.test.ts | 2 +- tests/float16/guards.test.ts | 4 ++-- tests/float16/index.test.ts | 2 +- tests/float16/round.test.ts | 2 +- tests/float32/constants.test.ts | 2 +- tests/float32/decode.test.ts | 2 +- tests/float32/encode.test.ts | 2 +- tests/float32/guards.test.ts | 4 ++-- tests/float32/index.test.ts | 2 +- tests/float32/round.test.ts | 2 +- tests/floor.test.ts | 4 ++-- tests/fround.test.ts | 4 ++-- tests/guards/finite.test.ts | 2 +- tests/guards/index.test.ts | 2 +- tests/guards/infinity.test.ts | 2 +- tests/guards/integer.test.ts | 2 +- tests/guards/nan.test.ts | 2 +- tests/guards/negative_infinity.test.ts | 2 +- tests/guards/negative_zero.test.ts | 2 +- tests/guards/positive_infinity.test.ts | 2 +- tests/guards/positive_zero.test.ts | 2 +- tests/guards/safe_integer.test.ts | 2 +- tests/hypot.test.ts | 4 ++-- tests/ieee754.test.ts | 2 +- tests/imul.test.ts | 4 ++-- tests/index.test.ts | 6 +++--- tests/log.test.ts | 4 ++-- tests/log10.test.ts | 4 ++-- tests/log1p.test.ts | 4 ++-- tests/log2.test.ts | 4 ++-- tests/max.test.ts | 4 ++-- tests/min.test.ts | 4 ++-- tests/pow.test.ts | 4 ++-- tests/random.test.ts | 2 +- tests/round.test.ts | 4 ++-- tests/sign.test.ts | 4 ++-- tests/sin.test.ts | 4 ++-- tests/sinh.test.ts | 4 ++-- tests/sqrt.test.ts | 4 ++-- tests/tan.test.ts | 4 ++-- tests/tanh.test.ts | 4 ++-- tests/trigonometry.test.ts | 4 ++-- tests/trunc.test.ts | 4 ++-- tests/types/finite.test.ts | 2 +- tests/types/float.test.ts | 2 +- tests/types/index.test.ts | 2 +- tests/types/integer.test.ts | 2 +- tests/types/precision.test.ts | 2 +- tests/types/safe_integer.test.ts | 2 +- 89 files changed, 132 insertions(+), 132 deletions(-) diff --git a/tests/abs.test.ts b/tests/abs.test.ts index ccf668a..f0707a6 100644 --- a/tests/abs.test.ts +++ b/tests/abs.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertSameValue } from "./internal/_test_utils.ts"; -import { abs } from "./abs.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; +import { abs } from "../src/abs.ts"; const cases: number[] = [ -2.5, diff --git a/tests/acos.test.ts b/tests/acos.test.ts index 8fc681c..f590b22 100644 --- a/tests/acos.test.ts +++ b/tests/acos.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { acos } from "./acos.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { acos } from "../src/acos.ts"; const cases: number[] = [ -2.5, diff --git a/tests/acosh.test.ts b/tests/acosh.test.ts index 5e2f4e1..3f065aa 100644 --- a/tests/acosh.test.ts +++ b/tests/acosh.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { acosh } from "./acosh.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { acosh } from "../src/acosh.ts"; const cases: number[] = [ -2.5, diff --git a/tests/asin.test.ts b/tests/asin.test.ts index 90cbf2e..fe181ab 100644 --- a/tests/asin.test.ts +++ b/tests/asin.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { asin } from "./asin.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { asin } from "../src/asin.ts"; const cases: number[] = [ -2.5, diff --git a/tests/asinh.test.ts b/tests/asinh.test.ts index 7253df6..7869adc 100644 --- a/tests/asinh.test.ts +++ b/tests/asinh.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { asinh } from "./asinh.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { asinh } from "../src/asinh.ts"; const cases: number[] = [ -2.5, diff --git a/tests/atan.test.ts b/tests/atan.test.ts index 208073b..dd7c53f 100644 --- a/tests/atan.test.ts +++ b/tests/atan.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { atan } from "./atan.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { atan } from "../src/atan.ts"; const cases: number[] = [ -2.5, diff --git a/tests/atan2.test.ts b/tests/atan2.test.ts index 12980ed..2446276 100644 --- a/tests/atan2.test.ts +++ b/tests/atan2.test.ts @@ -1,9 +1,9 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose, assertSameValue } from "./internal/_test_utils.ts"; -import { atan2 } from "./atan2.ts"; -import { PI } from "./constants/pi.ts"; -import { isNegativeZero } from "./guards/negative_zero.ts"; +import { assertClose, assertSameValue } from "../src/internal/_test_utils.ts"; +import { atan2 } from "../src/atan2.ts"; +import { PI } from "../src/constants/pi.ts"; +import { isNegativeZero } from "../src/guards/negative_zero.ts"; const PI_OVER_2 = PI / 2, PI_OVER_4 = PI / 4; diff --git a/tests/atanh.test.ts b/tests/atanh.test.ts index 2edac01..fef0a6b 100644 --- a/tests/atanh.test.ts +++ b/tests/atanh.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { atanh } from "./atanh.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { atanh } from "../src/atanh.ts"; const cases: number[] = [ -2.5, diff --git a/tests/cbrt.test.ts b/tests/cbrt.test.ts index 6a4df7f..7f9433e 100644 --- a/tests/cbrt.test.ts +++ b/tests/cbrt.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { cbrt } from "./cbrt.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { cbrt } from "../src/cbrt.ts"; const cases: number[] = [ -2.5, diff --git a/tests/ceil.test.ts b/tests/ceil.test.ts index b42e98f..41c0d6c 100644 --- a/tests/ceil.test.ts +++ b/tests/ceil.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertSameValue } from "./internal/_test_utils.ts"; -import { ceil } from "./ceil.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; +import { ceil } from "../src/ceil.ts"; const cases: number[] = [ -2.5, diff --git a/tests/clamp.test.ts b/tests/clamp.test.ts index e37307b..2b9beef 100644 --- a/tests/clamp.test.ts +++ b/tests/clamp.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { clamp } from "./clamp.ts"; +import { clamp } from "../src/clamp.ts"; const cases: Array<[number, number, number]> = [ [-1, 0, 1], diff --git a/tests/clz32.test.ts b/tests/clz32.test.ts index badbdd4..456d5a6 100644 --- a/tests/clz32.test.ts +++ b/tests/clz32.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertSameValue } from "./internal/_test_utils.ts"; -import { clz32 } from "./clz32.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; +import { clz32 } from "../src/clz32.ts"; const cases: number[] = [ -2.5, diff --git a/tests/constants.test.ts b/tests/constants.test.ts index 48cf8db..7470807 100644 --- a/tests/constants.test.ts +++ b/tests/constants.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import * as constants from "./constants/index.ts"; -import { assertSameValue } from "./internal/_test_utils.ts"; +import * as constants from "../src/constants/index.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; const cases = { Math: [ diff --git a/tests/constants/e.test.ts b/tests/constants/e.test.ts index bacce9e..ef4e6a5 100644 --- a/tests/constants/e.test.ts +++ b/tests/constants/e.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { E } from "./e.ts"; +import { E } from "../../src/constants/e.ts"; describe("E", () => { it("is a number", () => { diff --git a/tests/constants/epsilon.test.ts b/tests/constants/epsilon.test.ts index 88d274c..96634ef 100644 --- a/tests/constants/epsilon.test.ts +++ b/tests/constants/epsilon.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { EPSILON } from "./epsilon.ts"; +import { EPSILON } from "../../src/constants/epsilon.ts"; describe("EPSILON", () => { it("is a number", () => { diff --git a/tests/constants/index.test.ts b/tests/constants/index.test.ts index 541f600..12433ea 100644 --- a/tests/constants/index.test.ts +++ b/tests/constants/index.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import * as constants from "./index.ts"; +import * as constants from "../../src/constants/index.ts"; const mathKeys = [ "E", diff --git a/tests/constants/infinity.test.ts b/tests/constants/infinity.test.ts index 5922ebe..ded67cc 100644 --- a/tests/constants/infinity.test.ts +++ b/tests/constants/infinity.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { NEGATIVE_INFINITY, POSITIVE_INFINITY } from "./infinity.ts"; +import { NEGATIVE_INFINITY, POSITIVE_INFINITY } from "../../src/constants/infinity.ts"; describe("constants/infinity", () => { it("exports positive and negative infinity", () => { diff --git a/tests/constants/ln10.test.ts b/tests/constants/ln10.test.ts index c3afc1d..5f84c2f 100644 --- a/tests/constants/ln10.test.ts +++ b/tests/constants/ln10.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { LN10 } from "./ln10.ts"; +import { LN10 } from "../../src/constants/ln10.ts"; describe("LN10", () => { it("is a number", () => { diff --git a/tests/constants/ln2.test.ts b/tests/constants/ln2.test.ts index c16b4b5..03d50d0 100644 --- a/tests/constants/ln2.test.ts +++ b/tests/constants/ln2.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { LN2 } from "./ln2.ts"; +import { LN2 } from "../../src/constants/ln2.ts"; describe("LN2", () => { it("is a number", () => { diff --git a/tests/constants/log10e.test.ts b/tests/constants/log10e.test.ts index 1a0a71f..08c7238 100644 --- a/tests/constants/log10e.test.ts +++ b/tests/constants/log10e.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { LOG10E } from "./log10e.ts"; +import { LOG10E } from "../../src/constants/log10e.ts"; describe("LOG10E", () => { it("is a number", () => { diff --git a/tests/constants/log2e.test.ts b/tests/constants/log2e.test.ts index 5c26a7d..c7fdf5f 100644 --- a/tests/constants/log2e.test.ts +++ b/tests/constants/log2e.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { LOG2E } from "./log2e.ts"; +import { LOG2E } from "../../src/constants/log2e.ts"; describe("LOG2E", () => { it("is a number", () => { diff --git a/tests/constants/max_safe_integer.test.ts b/tests/constants/max_safe_integer.test.ts index 7d0905b..3145086 100644 --- a/tests/constants/max_safe_integer.test.ts +++ b/tests/constants/max_safe_integer.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { MAX_SAFE_INTEGER } from "./max_safe_integer.ts"; +import { MAX_SAFE_INTEGER } from "../../src/constants/max_safe_integer.ts"; describe("MAX_SAFE_INTEGER", () => { it("is a number", () => { diff --git a/tests/constants/max_value.test.ts b/tests/constants/max_value.test.ts index c092cc0..40b8a79 100644 --- a/tests/constants/max_value.test.ts +++ b/tests/constants/max_value.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { MAX_VALUE } from "./max_value.ts"; +import { MAX_VALUE } from "../../src/constants/max_value.ts"; describe("MAX_VALUE", () => { it("is a number", () => { diff --git a/tests/constants/min_safe_integer.test.ts b/tests/constants/min_safe_integer.test.ts index b1eb40c..15dd469 100644 --- a/tests/constants/min_safe_integer.test.ts +++ b/tests/constants/min_safe_integer.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { MIN_SAFE_INTEGER } from "./min_safe_integer.ts"; +import { MIN_SAFE_INTEGER } from "../../src/constants/min_safe_integer.ts"; describe("MIN_SAFE_INTEGER", () => { it("is a number", () => { diff --git a/tests/constants/min_value.test.ts b/tests/constants/min_value.test.ts index 56dd8f1..8649665 100644 --- a/tests/constants/min_value.test.ts +++ b/tests/constants/min_value.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { MIN_VALUE } from "./min_value.ts"; +import { MIN_VALUE } from "../../src/constants/min_value.ts"; describe("MIN_VALUE", () => { it("is a number", () => { diff --git a/tests/constants/nan.test.ts b/tests/constants/nan.test.ts index 93604a8..cb4df14 100644 --- a/tests/constants/nan.test.ts +++ b/tests/constants/nan.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { NAN, NaN as NaNValue } from "./nan.ts"; +import { NAN, NaN as NaNValue } from "../../src/constants/nan.ts"; describe("NAN", () => { it("is a number", () => { diff --git a/tests/constants/negative_infinity.test.ts b/tests/constants/negative_infinity.test.ts index 8e23b04..5040bb7 100644 --- a/tests/constants/negative_infinity.test.ts +++ b/tests/constants/negative_infinity.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { NEGATIVE_INFINITY } from "./negative_infinity.ts"; +import { NEGATIVE_INFINITY } from "../../src/constants/negative_infinity.ts"; describe("NEGATIVE_INFINITY", () => { it("is a number", () => { diff --git a/tests/constants/negative_zero.test.ts b/tests/constants/negative_zero.test.ts index 1a15721..ddd0c5a 100644 --- a/tests/constants/negative_zero.test.ts +++ b/tests/constants/negative_zero.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { NEGATIVE_ZERO } from "./negative_zero.ts"; +import { NEGATIVE_ZERO } from "../../src/constants/negative_zero.ts"; describe("NEGATIVE_ZERO", () => { it("is -0", () => { diff --git a/tests/constants/pi.test.ts b/tests/constants/pi.test.ts index 722de99..4f7cdcc 100644 --- a/tests/constants/pi.test.ts +++ b/tests/constants/pi.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { PI } from "./pi.ts"; +import { PI } from "../../src/constants/pi.ts"; describe("PI", () => { it("is a number", () => { diff --git a/tests/constants/positive_infinity.test.ts b/tests/constants/positive_infinity.test.ts index 7ce6cdf..f2e45a1 100644 --- a/tests/constants/positive_infinity.test.ts +++ b/tests/constants/positive_infinity.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { POSITIVE_INFINITY } from "./positive_infinity.ts"; +import { POSITIVE_INFINITY } from "../../src/constants/positive_infinity.ts"; describe("POSITIVE_INFINITY", () => { it("is a number", () => { diff --git a/tests/constants/positive_zero.test.ts b/tests/constants/positive_zero.test.ts index f5689af..677adb4 100644 --- a/tests/constants/positive_zero.test.ts +++ b/tests/constants/positive_zero.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { POSITIVE_ZERO } from "./positive_zero.ts"; +import { POSITIVE_ZERO } from "../../src/constants/positive_zero.ts"; describe("POSITIVE_ZERO", () => { it("is +0", () => { diff --git a/tests/constants/sqrt1_2.test.ts b/tests/constants/sqrt1_2.test.ts index 359967d..743ef8f 100644 --- a/tests/constants/sqrt1_2.test.ts +++ b/tests/constants/sqrt1_2.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { SQRT1_2 } from "./sqrt1_2.ts"; +import { SQRT1_2 } from "../../src/constants/sqrt1_2.ts"; describe("SQRT1_2", () => { it("is a number", () => { diff --git a/tests/constants/sqrt2.test.ts b/tests/constants/sqrt2.test.ts index 3ee5fe9..92517b9 100644 --- a/tests/constants/sqrt2.test.ts +++ b/tests/constants/sqrt2.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { SQRT2 } from "./sqrt2.ts"; +import { SQRT2 } from "../../src/constants/sqrt2.ts"; describe("SQRT2", () => { it("is a number", () => { diff --git a/tests/cos.test.ts b/tests/cos.test.ts index df6b893..77ebc6f 100644 --- a/tests/cos.test.ts +++ b/tests/cos.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { cos } from "./cos.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { cos } from "../src/cos.ts"; const cases: number[] = [ -2.5, diff --git a/tests/cosh.test.ts b/tests/cosh.test.ts index 507ad11..24d6b0e 100644 --- a/tests/cosh.test.ts +++ b/tests/cosh.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { cosh } from "./cosh.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { cosh } from "../src/cosh.ts"; const cases: number[] = [ -2.5, diff --git a/tests/exp.test.ts b/tests/exp.test.ts index aab293d..c1a31ae 100644 --- a/tests/exp.test.ts +++ b/tests/exp.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { exp } from "./exp.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { exp } from "../src/exp.ts"; const cases: number[] = [ -2.5, diff --git a/tests/expm1.test.ts b/tests/expm1.test.ts index 96e6d93..5dfd8c4 100644 --- a/tests/expm1.test.ts +++ b/tests/expm1.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { expm1 } from "./expm1.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { expm1 } from "../src/expm1.ts"; const cases: number[] = [ -2.5, diff --git a/tests/f16round.test.ts b/tests/f16round.test.ts index 880ae83..ec7f2e7 100644 --- a/tests/f16round.test.ts +++ b/tests/f16round.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertSameValue } from "./internal/_test_utils.ts"; -import { f16round } from "./f16round.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; +import { f16round } from "../src/f16round.ts"; const cases: number[] = [ -2.5, diff --git a/tests/float16/constants.test.ts b/tests/float16/constants.test.ts index 0cc855c..8c577fc 100644 --- a/tests/float16/constants.test.ts +++ b/tests/float16/constants.test.ts @@ -9,7 +9,7 @@ import float16, { FLOAT16_NEGATIVE_ZERO, FLOAT16_POSITIVE_INFINITY, FLOAT16_POSITIVE_ZERO, -} from "./constants.ts"; +} from "../../src/float16/constants.ts"; describe("float16/constants", () => { it("exposes expected numeric constants", () => { diff --git a/tests/float16/decode.test.ts b/tests/float16/decode.test.ts index 93c24f0..6fa4607 100644 --- a/tests/float16/decode.test.ts +++ b/tests/float16/decode.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { decodeFloat16 } from "./decode.ts"; +import { decodeFloat16 } from "../../src/float16/decode.ts"; const cases = [0x0000, 0x8000, 0x3C00, 0xBC00, 0x7C00, 0xFC00, 0x7E00, 0x4248]; diff --git a/tests/float16/encode.test.ts b/tests/float16/encode.test.ts index d1400e6..8edce17 100644 --- a/tests/float16/encode.test.ts +++ b/tests/float16/encode.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { encodeFloat16 } from "./encode.ts"; +import { encodeFloat16 } from "../../src/float16/encode.ts"; const cases = [0, -0, 1, -1, 3.14, 42, Infinity, -Infinity]; diff --git a/tests/float16/guards.test.ts b/tests/float16/guards.test.ts index 87f7c47..b994bc6 100644 --- a/tests/float16/guards.test.ts +++ b/tests/float16/guards.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { isFloat16 } from "./guards.ts"; -import { roundFloat16 } from "./round.ts"; +import { isFloat16 } from "../../src/float16/guards.ts"; +import { roundFloat16 } from "../../src/float16/round.ts"; const cases = [0, -0, 1, -1, 0.1, 0.5, 3.14, 42, Infinity, -Infinity, NaN]; diff --git a/tests/float16/index.test.ts b/tests/float16/index.test.ts index 897253b..9e40428 100644 --- a/tests/float16/index.test.ts +++ b/tests/float16/index.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import * as float16 from "./index.ts"; +import * as float16 from "../../src/float16/index.ts"; describe("float16/index", () => { it("exports float16 utilities", () => { diff --git a/tests/float16/round.test.ts b/tests/float16/round.test.ts index 5a1e1bc..688099e 100644 --- a/tests/float16/round.test.ts +++ b/tests/float16/round.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { roundFloat16 } from "./round.ts"; +import { roundFloat16 } from "../../src/float16/round.ts"; const cases = [0, -0, 1, -1, 3.14, 42, Infinity, -Infinity, NaN]; diff --git a/tests/float32/constants.test.ts b/tests/float32/constants.test.ts index 5797b9e..8ae5e15 100644 --- a/tests/float32/constants.test.ts +++ b/tests/float32/constants.test.ts @@ -9,7 +9,7 @@ import float32, { FLOAT32_NEGATIVE_ZERO, FLOAT32_POSITIVE_INFINITY, FLOAT32_POSITIVE_ZERO, -} from "./constants.ts"; +} from "../../src/float32/constants.ts"; describe("float32/constants", () => { it("exposes expected numeric constants", () => { diff --git a/tests/float32/decode.test.ts b/tests/float32/decode.test.ts index 6ad391c..39f20d9 100644 --- a/tests/float32/decode.test.ts +++ b/tests/float32/decode.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { decodeFloat32 } from "./decode.ts"; +import { decodeFloat32 } from "../../src/float32/decode.ts"; const cases = [ 0x00000000, diff --git a/tests/float32/encode.test.ts b/tests/float32/encode.test.ts index a09c992..294a247 100644 --- a/tests/float32/encode.test.ts +++ b/tests/float32/encode.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { encodeFloat32 } from "./encode.ts"; +import { encodeFloat32 } from "../../src/float32/encode.ts"; const cases = [0, -0, 1, -1, 3.14, 42, Infinity, -Infinity]; diff --git a/tests/float32/guards.test.ts b/tests/float32/guards.test.ts index f8eca69..642041d 100644 --- a/tests/float32/guards.test.ts +++ b/tests/float32/guards.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { isFiniteFloat32, isFloat32 } from "./guards.ts"; -import { roundFloat32 } from "./round.ts"; +import { isFiniteFloat32, isFloat32 } from "../../src/float32/guards.ts"; +import { roundFloat32 } from "../../src/float32/round.ts"; const cases = [0, -0, 1, -1, 0.1, 0.5, 3.14, 42, Infinity, -Infinity, NaN]; diff --git a/tests/float32/index.test.ts b/tests/float32/index.test.ts index 424b7ce..26e2893 100644 --- a/tests/float32/index.test.ts +++ b/tests/float32/index.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import * as float32 from "./index.ts"; +import * as float32 from "../../src/float32/index.ts"; describe("float32/index", () => { it("exports float32 utilities", () => { diff --git a/tests/float32/round.test.ts b/tests/float32/round.test.ts index f163415..86932cc 100644 --- a/tests/float32/round.test.ts +++ b/tests/float32/round.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { roundFloat32 } from "./round.ts"; +import { roundFloat32 } from "../../src/float32/round.ts"; const cases = [0, -0, 1, -1, 3.14, 42, Infinity, -Infinity, NaN]; diff --git a/tests/floor.test.ts b/tests/floor.test.ts index 266e459..d19d34a 100644 --- a/tests/floor.test.ts +++ b/tests/floor.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertSameValue } from "./internal/_test_utils.ts"; -import { floor } from "./floor.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; +import { floor } from "../src/floor.ts"; const cases: number[] = [ -2.5, diff --git a/tests/fround.test.ts b/tests/fround.test.ts index a7a1c0e..8138c76 100644 --- a/tests/fround.test.ts +++ b/tests/fround.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertSameValue } from "./internal/_test_utils.ts"; -import { fround } from "./fround.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; +import { fround } from "../src/fround.ts"; const cases: number[] = [ -2.5, diff --git a/tests/guards/finite.test.ts b/tests/guards/finite.test.ts index 433e42b..b628654 100644 --- a/tests/guards/finite.test.ts +++ b/tests/guards/finite.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { isFinite } from "./finite.ts"; +import { isFinite } from "../../src/guards/finite.ts"; const cases: unknown[] = [ 0, diff --git a/tests/guards/index.test.ts b/tests/guards/index.test.ts index d52bd17..f0593e1 100644 --- a/tests/guards/index.test.ts +++ b/tests/guards/index.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import * as guards from "./index.ts"; +import * as guards from "../../src/guards/index.ts"; describe("guards/index", () => { it("exposes guard functions", () => { diff --git a/tests/guards/infinity.test.ts b/tests/guards/infinity.test.ts index 04f9852..78563dc 100644 --- a/tests/guards/infinity.test.ts +++ b/tests/guards/infinity.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { isNegativeInfinity, isPositiveInfinity } from "./infinity.ts"; +import { isNegativeInfinity, isPositiveInfinity } from "../../src/guards/infinity.ts"; describe("guards/infinity", () => { it("re-exports positive/negative infinity checks", () => { diff --git a/tests/guards/integer.test.ts b/tests/guards/integer.test.ts index a8b0dd3..e3c2cad 100644 --- a/tests/guards/integer.test.ts +++ b/tests/guards/integer.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { isInteger, isNumberInteger } from "./integer.ts"; +import { isInteger, isNumberInteger } from "../../src/guards/integer.ts"; const cases = [0, 1, -1, 1.2, -2.5, NaN, Infinity, -Infinity, "3"]; diff --git a/tests/guards/nan.test.ts b/tests/guards/nan.test.ts index a5a8b3d..957b8e8 100644 --- a/tests/guards/nan.test.ts +++ b/tests/guards/nan.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { isNaN, NAN, NaN as NaNValue } from "./nan.ts"; +import { isNaN, NAN, NaN as NaNValue } from "../../src/guards/nan.ts"; const cases: unknown[] = [0, 1, NaN, "foo", "42", null, undefined]; diff --git a/tests/guards/negative_infinity.test.ts b/tests/guards/negative_infinity.test.ts index dd83d0d..97c997b 100644 --- a/tests/guards/negative_infinity.test.ts +++ b/tests/guards/negative_infinity.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { isNegativeInfinity } from "./negative_infinity.ts"; +import { isNegativeInfinity } from "../../src/guards/negative_infinity.ts"; const cases = [0, 1, -1, Infinity, -Infinity, NaN]; diff --git a/tests/guards/negative_zero.test.ts b/tests/guards/negative_zero.test.ts index 8a0df28..273a054 100644 --- a/tests/guards/negative_zero.test.ts +++ b/tests/guards/negative_zero.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { isNegativeZero } from "./negative_zero.ts"; +import { isNegativeZero } from "../../src/guards/negative_zero.ts"; const cases = [0, -0, 1, -1, NaN, Infinity, -Infinity]; diff --git a/tests/guards/positive_infinity.test.ts b/tests/guards/positive_infinity.test.ts index 2e85245..1416fb8 100644 --- a/tests/guards/positive_infinity.test.ts +++ b/tests/guards/positive_infinity.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { isPositiveInfinity } from "./positive_infinity.ts"; +import { isPositiveInfinity } from "../../src/guards/positive_infinity.ts"; const cases = [0, 1, -1, Infinity, -Infinity, NaN]; diff --git a/tests/guards/positive_zero.test.ts b/tests/guards/positive_zero.test.ts index 0a5396d..cd320d1 100644 --- a/tests/guards/positive_zero.test.ts +++ b/tests/guards/positive_zero.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { isPositiveZero } from "./positive_zero.ts"; +import { isPositiveZero } from "../../src/guards/positive_zero.ts"; const cases = [0, -0, 1, -1, NaN, Infinity, -Infinity]; diff --git a/tests/guards/safe_integer.test.ts b/tests/guards/safe_integer.test.ts index 75179f6..ddd33ec 100644 --- a/tests/guards/safe_integer.test.ts +++ b/tests/guards/safe_integer.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { isSafeInteger } from "./safe_integer.ts"; +import { isSafeInteger } from "../../src/guards/safe_integer.ts"; const cases = [ 0, diff --git a/tests/hypot.test.ts b/tests/hypot.test.ts index 0bd3246..9285331 100644 --- a/tests/hypot.test.ts +++ b/tests/hypot.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { hypot } from "./hypot.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { hypot } from "../src/hypot.ts"; const cases: Array = [[3, 4], [0, 0], [1, 2, 3], [Infinity, 1], [ NaN, diff --git a/tests/ieee754.test.ts b/tests/ieee754.test.ts index 68cc47a..e8b895c 100644 --- a/tests/ieee754.test.ts +++ b/tests/ieee754.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import * as ieee754 from "./ieee754.ts"; +import * as ieee754 from "../src/ieee754.ts"; describe("ieee754", () => { it("re-exports float16 utilities", () => { diff --git a/tests/imul.test.ts b/tests/imul.test.ts index 3df361f..76fb804 100644 --- a/tests/imul.test.ts +++ b/tests/imul.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertSameValue } from "./internal/_test_utils.ts"; -import { imul } from "./imul.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; +import { imul } from "../src/imul.ts"; const cases: Array<[number, number]> = [[2, 3], [-1, 8], [4294967295, 5], [ 0, diff --git a/tests/index.test.ts b/tests/index.test.ts index 320fda7..e31b909 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -1,8 +1,8 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import * as math from "./index.ts"; -import mathDefault from "./index.ts"; -import { assertClose, assertSameValue } from "./internal/_test_utils.ts"; +import * as math from "../src/index.ts"; +import mathDefault from "../src/index.ts"; +import { assertClose, assertSameValue } from "../src/internal/_test_utils.ts"; describe("index", () => { it("exports a default namespace", () => { diff --git a/tests/log.test.ts b/tests/log.test.ts index 94769a4..b869454 100644 --- a/tests/log.test.ts +++ b/tests/log.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { log } from "./log.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { log } from "../src/log.ts"; const cases: number[] = [ -2.5, diff --git a/tests/log10.test.ts b/tests/log10.test.ts index b2d3da4..bf86119 100644 --- a/tests/log10.test.ts +++ b/tests/log10.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { log10 } from "./log10.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { log10 } from "../src/log10.ts"; const cases: number[] = [ -2.5, diff --git a/tests/log1p.test.ts b/tests/log1p.test.ts index da1c971..c944ba8 100644 --- a/tests/log1p.test.ts +++ b/tests/log1p.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { log1p } from "./log1p.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { log1p } from "../src/log1p.ts"; const cases: number[] = [ -2.5, diff --git a/tests/log2.test.ts b/tests/log2.test.ts index e66f034..997bac7 100644 --- a/tests/log2.test.ts +++ b/tests/log2.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { log2 } from "./log2.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { log2 } from "../src/log2.ts"; const cases: number[] = [ -2.5, diff --git a/tests/max.test.ts b/tests/max.test.ts index 08a6de8..2d07e5e 100644 --- a/tests/max.test.ts +++ b/tests/max.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertSameValue } from "./internal/_test_utils.ts"; -import { max } from "./max.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; +import { max } from "../src/max.ts"; const cases: Array = [ [1, 2, 3], diff --git a/tests/min.test.ts b/tests/min.test.ts index 5c4cbb6..c51e0b8 100644 --- a/tests/min.test.ts +++ b/tests/min.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertSameValue } from "./internal/_test_utils.ts"; -import { min } from "./min.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; +import { min } from "../src/min.ts"; const cases: Array = [ [1, 2, 3], diff --git a/tests/pow.test.ts b/tests/pow.test.ts index cf39bab..b6463e7 100644 --- a/tests/pow.test.ts +++ b/tests/pow.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { pow } from "./pow.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { pow } from "../src/pow.ts"; const cases: Array<[number, number]> = [ [2, 3], diff --git a/tests/random.test.ts b/tests/random.test.ts index 934ba46..027e5b1 100644 --- a/tests/random.test.ts +++ b/tests/random.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { MT19937, random } from "./random.ts"; +import { MT19937, random } from "../src/random.ts"; const seed = 42; diff --git a/tests/round.test.ts b/tests/round.test.ts index bf8fc80..610e408 100644 --- a/tests/round.test.ts +++ b/tests/round.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertSameValue } from "./internal/_test_utils.ts"; -import { round } from "./round.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; +import { round } from "../src/round.ts"; const cases: number[] = [ -2.5, diff --git a/tests/sign.test.ts b/tests/sign.test.ts index e873882..4271cf1 100644 --- a/tests/sign.test.ts +++ b/tests/sign.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertSameValue } from "./internal/_test_utils.ts"; -import { sign } from "./sign.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; +import { sign } from "../src/sign.ts"; const cases: number[] = [ -2.5, diff --git a/tests/sin.test.ts b/tests/sin.test.ts index c80405e..eeacdd0 100644 --- a/tests/sin.test.ts +++ b/tests/sin.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { sin } from "./sin.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { sin } from "../src/sin.ts"; const cases: number[] = [ -2.5, diff --git a/tests/sinh.test.ts b/tests/sinh.test.ts index 4275a5e..29ef23a 100644 --- a/tests/sinh.test.ts +++ b/tests/sinh.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { sinh } from "./sinh.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { sinh } from "../src/sinh.ts"; const cases: number[] = [ -2.5, diff --git a/tests/sqrt.test.ts b/tests/sqrt.test.ts index a0c0090..e9114c5 100644 --- a/tests/sqrt.test.ts +++ b/tests/sqrt.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { sqrt } from "./sqrt.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { sqrt } from "../src/sqrt.ts"; const cases: number[] = [ -2.5, diff --git a/tests/tan.test.ts b/tests/tan.test.ts index f711ecd..80b7dc3 100644 --- a/tests/tan.test.ts +++ b/tests/tan.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { tan } from "./tan.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { tan } from "../src/tan.ts"; const cases: number[] = [ -2.5, diff --git a/tests/tanh.test.ts b/tests/tanh.test.ts index 7384e05..23d3b2b 100644 --- a/tests/tanh.test.ts +++ b/tests/tanh.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; -import { tanh } from "./tanh.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; +import { tanh } from "../src/tanh.ts"; const cases: number[] = [ -2.5, diff --git a/tests/trigonometry.test.ts b/tests/trigonometry.test.ts index 5e1ed6f..fe93e55 100644 --- a/tests/trigonometry.test.ts +++ b/tests/trigonometry.test.ts @@ -1,5 +1,5 @@ import { describe, it } from "node:test"; -import { assertClose } from "./internal/_test_utils.ts"; +import { assertClose } from "../src/internal/_test_utils.ts"; import { acos, acosh, @@ -12,7 +12,7 @@ import { sin, tan, tanh, -} from "./index.ts"; +} from "../src/index.ts"; const unaryCases = [0, 0.5, -0.5, 1, -1, Math.PI / 2, Math.PI, NaN]; diff --git a/tests/trunc.test.ts b/tests/trunc.test.ts index f4f37fe..c817116 100644 --- a/tests/trunc.test.ts +++ b/tests/trunc.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { assertSameValue } from "./internal/_test_utils.ts"; -import { trunc } from "./trunc.ts"; +import { assertSameValue } from "../src/internal/_test_utils.ts"; +import { trunc } from "../src/trunc.ts"; const cases: number[] = [ -2.5, diff --git a/tests/types/finite.test.ts b/tests/types/finite.test.ts index fefd760..c2a893f 100644 --- a/tests/types/finite.test.ts +++ b/tests/types/finite.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import type { Finite } from "./finite.ts"; +import type { Finite } from "../../src/types/finite.ts"; const finiteValue = 1 as Finite; diff --git a/tests/types/float.test.ts b/tests/types/float.test.ts index 0c65695..27d2f12 100644 --- a/tests/types/float.test.ts +++ b/tests/types/float.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import type { Double, Float, Float16, Float32, Float64 } from "./float.ts"; +import type { Double, Float, Float16, Float32, Float64 } from "../../src/types/float.ts"; const floatValue = 1 as Float; const float16Value = 1 as Float16; diff --git a/tests/types/index.test.ts b/tests/types/index.test.ts index 06009af..8568aa5 100644 --- a/tests/types/index.test.ts +++ b/tests/types/index.test.ts @@ -6,7 +6,7 @@ import type { Integer, Precision, SafeInteger, -} from "./index.ts"; +} from "../../src/types/index.ts"; const finiteValue = 1 as Finite; const floatValue = 1 as Float; diff --git a/tests/types/integer.test.ts b/tests/types/integer.test.ts index d91b921..bbab084 100644 --- a/tests/types/integer.test.ts +++ b/tests/types/integer.test.ts @@ -13,7 +13,7 @@ import type { Uint64, Uint8, Unsigned, -} from "./integer.ts"; +} from "../../src/types/integer.ts"; const intValue = 1 as Integer; const uintValue = 1 as Unsigned; diff --git a/tests/types/precision.test.ts b/tests/types/precision.test.ts index 7d90c99..492fce3 100644 --- a/tests/types/precision.test.ts +++ b/tests/types/precision.test.ts @@ -7,7 +7,7 @@ import type { P64, P8, Precision, -} from "./precision.ts"; +} from "../../src/types/precision.ts"; const p8Value = 8 as P8; const p16Value = 16 as P16; diff --git a/tests/types/safe_integer.test.ts b/tests/types/safe_integer.test.ts index 6672704..097a878 100644 --- a/tests/types/safe_integer.test.ts +++ b/tests/types/safe_integer.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import type { SafeInteger } from "./safe_integer.ts"; +import type { SafeInteger } from "../../src/types/safe_integer.ts"; const safeValue = 1 as SafeInteger; From e3f2daa65ae9150e92329928df9560735d4ec908 Mon Sep 17 00:00:00 2001 From: Nicholas Berlette Date: Fri, 23 Jan 2026 17:58:07 -0800 Subject: [PATCH 132/132] chore: fmt --- tests/constants/infinity.test.ts | 5 ++++- tests/guards/infinity.test.ts | 5 ++++- tests/types/float.test.ts | 8 +++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/constants/infinity.test.ts b/tests/constants/infinity.test.ts index ded67cc..fd09466 100644 --- a/tests/constants/infinity.test.ts +++ b/tests/constants/infinity.test.ts @@ -1,6 +1,9 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { NEGATIVE_INFINITY, POSITIVE_INFINITY } from "../../src/constants/infinity.ts"; +import { + NEGATIVE_INFINITY, + POSITIVE_INFINITY, +} from "../../src/constants/infinity.ts"; describe("constants/infinity", () => { it("exports positive and negative infinity", () => { diff --git a/tests/guards/infinity.test.ts b/tests/guards/infinity.test.ts index 78563dc..539d843 100644 --- a/tests/guards/infinity.test.ts +++ b/tests/guards/infinity.test.ts @@ -1,6 +1,9 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import { isNegativeInfinity, isPositiveInfinity } from "../../src/guards/infinity.ts"; +import { + isNegativeInfinity, + isPositiveInfinity, +} from "../../src/guards/infinity.ts"; describe("guards/infinity", () => { it("re-exports positive/negative infinity checks", () => { diff --git a/tests/types/float.test.ts b/tests/types/float.test.ts index 27d2f12..2d756f3 100644 --- a/tests/types/float.test.ts +++ b/tests/types/float.test.ts @@ -1,6 +1,12 @@ import assert from "node:assert"; import { describe, it } from "node:test"; -import type { Double, Float, Float16, Float32, Float64 } from "../../src/types/float.ts"; +import type { + Double, + Float, + Float16, + Float32, + Float64, +} from "../../src/types/float.ts"; const floatValue = 1 as Float; const float16Value = 1 as Float16;