Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
import { describe, expect, it } from "@suaveplan/testing/runner";
import { PseudoRandomError } from "../errors/pseudo-random-error.js";
import { Sfc32Rng } from "./sfc32.js";
describe("Sfc32Rng", () => {
it("is deterministic", { timeout: 5000 }, () => {
const a = new Sfc32Rng("abc");
const b = new Sfc32Rng("abc");
for (let i = 0; i < 100; i += 1) {
expect(a.nextUint32()).toBe(b.nextUint32());
}
});
it("produces uint32 in range", { timeout: 5000 }, () => {
const r = new Sfc32Rng(1);
for (let i = 0; i < 1000; i += 1) {
const v = r.nextUint32();
expect(v).toBeGreaterThanOrEqual(0);
expect(v).toBeLessThan(2 ** 32);
}
});
it("skip === repeated nextUint32", { timeout: 5000 }, () => {
const a = new Sfc32Rng(2);
const b = new Sfc32Rng(2);
a.skip(50);
for (let i = 0; i < 50; i += 1) b.nextUint32();
expect(a.nextUint32()).toBe(b.nextUint32());
});
it("at doesn't mutate self", { timeout: 5000 }, () => {
const a = new Sfc32Rng(3);
const ahead = a.at(10);
expect(a.position).toBe(0);
expect(ahead.position).toBe(10);
});
it("checkpoint/restore round-trip", { timeout: 5000 }, () => {
const r = new Sfc32Rng(4);
r.skip(7);
const cp = r.checkpoint();
const exp = [r.nextUint32(), r.nextUint32()];
r.restore(cp);
expect([r.nextUint32(), r.nextUint32()]).toEqual(exp);
});
it("restore rejects foreign algorithm", { timeout: 5000 }, () => {
const r = new Sfc32Rng(5);
expect(() =>
r.restore({ algorithm: "mulberry32", state: [0], counter: 0 })
).toThrow(PseudoRandomError);
});
it("restore rejects bad state length or non-finite words", {
timeout: 5000,
}, () => {
const r = new Sfc32Rng(6);
expect(() =>
r.restore({ algorithm: "sfc32", state: [1, 2], counter: 0 })
).toThrow(PseudoRandomError);
expect(() =>
r.restore({
algorithm: "sfc32",
state: [1, 2, 3, Number.NaN],
counter: 0,
})
).toThrow(PseudoRandomError);
});
it("rejects invalid skip/at", { timeout: 5000 }, () => {
const r = new Sfc32Rng(7);
expect(() => r.skip(-1)).toThrow(PseudoRandomError);
expect(() => r.at(-1)).toThrow(PseudoRandomError);
});
it("fork yields distinct stream", { timeout: 5000 }, () => {
const parent = new Sfc32Rng(8);
const child = parent.fork("x");
const a = [parent.nextUint32(), parent.nextUint32()];
const b = [child.nextUint32(), child.nextUint32()];
expect(a).not.toEqual(b);
});
it("nextFloat is in [0,1)", { timeout: 5000 }, () => {
const r = new Sfc32Rng(9);
for (let i = 0; i < 200; i += 1) {
const f = r.nextFloat();
expect(f).toBeGreaterThanOrEqual(0);
expect(f).toBeLessThan(1);
}
});
});