2.3 KiB
algorithms/mulberry32
Purpose
Mulberry32Rng implements the Mulberry32 PRNG — a compact 32-bit linear-congruential-plus-mix generator with a period of roughly 2^32. It is the smallest SeededRng in the package (one 32-bit word of state) and is ideal for UI seedings, per-card shuffles, procedural decorations and any workload where replayability matters but cryptographic strength does not.
The implementation is byte-identical to the inline generator shipped inside @suaveplan/testing's seededRng, so code migrated between the two produces the same draws.
Features
- Single uint32 of state; ~1-cycle nextUint32 cost
- Implements the full
SeededRngcontract (skip,at,fork,checkpoint,restore) - Algorithm-tagged checkpoint prevents cross-algorithm restore bugs
- Typed errors on malformed state or invalid arguments
Usage: Basic Example
import { Mulberry32Rng } from "@suaveplan/pseudo-random";
const rng = new Mulberry32Rng("level-1");
console.log(rng.nextFloat());
console.log(rng.nextUint32());
Usage: Advanced Example
import { Mulberry32Rng } from "@suaveplan/pseudo-random";
const parent = new Mulberry32Rng("game-42");
const encounterRng = parent.fork("encounter");
const lootRng = parent.fork("loot");
const save = parent.checkpoint();
// ... simulate many turns ...
parent.restore(save); // back to the turn-0 state
API Reference
new Mulberry32Rng(seed: string | number)— normalises the seed throughnormalizeSeed.nextUint32()/nextFloat()— uniform draws.skip(n)— advance the stream bynuint32 draws;nmust be a non-negative integer.at(offset)— clone the generator and skipoffsetdraws on the clone. Does not mutatethis.fork(id)— derive a child generator keyed on(state, position, id).checkpoint()/restore(cp)— snapshot and reinstate state; restore validates thealgorithmtag.
Implementation Notes
The generator advances by state = (state + 0x6d2b79f5) | 0, then runs two Math.imul mixing rounds before returning the high-entropy output. at(offset) is O(offset) because Mulberry32 has no closed-form jump; if you need O(1) seek use CounterRng instead. Fork keys include the parent's current position so repeated forks at different moments yield independent streams.