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,85 @@
import { describe, expect, it } from "@suaveplan/testing/runner";
import { PseudoRandomError } from "../errors/pseudo-random-error.js";
import { Xoshiro256PlusPlusRng } from "./xoshiro256.js";
describe("Xoshiro256PlusPlusRng", () => {
it("is deterministic", { timeout: 5000 }, () => {
const a = new Xoshiro256PlusPlusRng(123);
const b = new Xoshiro256PlusPlusRng(123);
for (let i = 0; i < 64; i += 1) {
expect(a.nextUint32()).toBe(b.nextUint32());
}
});
it("produces uint32 in range", { timeout: 5000 }, () => {
const r = new Xoshiro256PlusPlusRng("x");
for (let i = 0; i < 500; i += 1) {
const v = r.nextUint32();
expect(v).toBeGreaterThanOrEqual(0);
expect(v).toBeLessThan(2 ** 32);
}
});
it("nextFloat in [0,1)", { timeout: 5000 }, () => {
const r = new Xoshiro256PlusPlusRng("y");
for (let i = 0; i < 200; i += 1) {
const f = r.nextFloat();
expect(f).toBeGreaterThanOrEqual(0);
expect(f).toBeLessThan(1);
}
});
it("jump decorrelates streams", { timeout: 5000 }, () => {
const a = new Xoshiro256PlusPlusRng(1);
const b = new Xoshiro256PlusPlusRng(1);
b.jump();
const av = [a.nextUint32(), a.nextUint32()];
const bv = [b.nextUint32(), b.nextUint32()];
expect(av).not.toEqual(bv);
});
it("checkpoint/restore round-trip", { timeout: 5000 }, () => {
const r = new Xoshiro256PlusPlusRng(7);
r.skip(5);
const cp = r.checkpoint();
const exp = [r.nextUint32(), r.nextUint32(), r.nextUint32()];
r.restore(cp);
expect([r.nextUint32(), r.nextUint32(), r.nextUint32()]).toEqual(exp);
});
it("at doesn't mutate self", { timeout: 5000 }, () => {
const r = new Xoshiro256PlusPlusRng(8);
const ahead = r.at(5);
expect(r.position).toBe(0);
expect(ahead.position).toBe(5);
});
it("fork is independent", { timeout: 5000 }, () => {
const r = new Xoshiro256PlusPlusRng(9);
const c = r.fork("a");
expect(r.nextUint32()).not.toBe(c.nextUint32());
});
it("restore validates algorithm and state", { timeout: 5000 }, () => {
const r = new Xoshiro256PlusPlusRng(10);
expect(() =>
r.restore({ algorithm: "sfc32", state: [0, 0, 0, 0], counter: 0 })
).toThrow(PseudoRandomError);
expect(() =>
r.restore({ algorithm: "xoshiro256++", state: [], counter: 0 })
).toThrow(PseudoRandomError);
expect(() =>
r.restore({
algorithm: "xoshiro256++",
state: [0, 0, 0, 0, 0, 0, 0, Number.NaN],
counter: 0,
})
).toThrow(PseudoRandomError);
});
it("rejects bad skip/at args", { timeout: 5000 }, () => {
const r = new Xoshiro256PlusPlusRng(11);
expect(() => r.skip(-1)).toThrow(PseudoRandomError);
expect(() => r.at(-1)).toThrow(PseudoRandomError);
});
});