Files
skills/docs/foundation/random/pseudo-random/src/seed/normalize.md
2026-05-29 08:20:56 +01:00

2.4 KiB

seed/normalize

(no submodules)

Purpose

The normalize module turns a user-supplied seed (number or string) into a uniformly distributed 32-bit unsigned integer suitable for seeding any of the PRNG algorithms in this package. It also exposes the underlying splitmix32/splitmix64 bit-mixers that each algorithm uses internally for seed expansion.

Seed normalisation is the only officially supported way to derive a deterministic starting state; passing the same input twice always returns the same uint32, and distinct inputs are decorrelated by the splitmix64 mixing step.

Features

  • Accepts string | number seeds; rejects NaN, infinities and non-safe integers with a typed PseudoRandomError
  • Deterministic: same input ⇒ same output
  • Fast 32-bit bit-mixer (splitmix32) for scalar mixing
  • Full 64-bit splitmix state step (splitmix64) returning { next, out }
  • expandSeed(seed, n) produces n decorrelated uint32 sub-seeds — used by SFC32 (4 words) and Xoshiro256++ (8 words)

Usage: Basic Example

import { normalizeSeed } from "@suaveplan/pseudo-random/seed";

const seed = normalizeSeed("my-game-state"); // stable uint32

Usage: Advanced Example

import { expandSeed, splitmix64 } from "@suaveplan/pseudo-random/seed";

// Derive 4 sub-seeds for SFC32's 128-bit state from a user key:
const [a, b, c, d] = expandSeed(normalizeSeed("run-7"), 4);

// Or drive the raw bigint stream yourself:
let state = 1n;
for (let i = 0; i < 8; i += 1) {
  const { next, out } = splitmix64(state);
  state = next;
  console.log(out);
}

API Reference

  • normalizeSeed(seed: string | number): number — returns a uint32.
  • splitmix32(seed: number): number — single mix round, returns a uint32.
  • splitmix64(state: bigint): { next: bigint; out: bigint } — one step of the splitmix64 generator, returned unmasked but kept within the low 64 bits.
  • expandSeed(seed: number, n: number): Uint32Array — n decorrelated sub-seeds.

Implementation Notes

The 32-bit mixer is the classic splitmix avalanche. String inputs are folded into a 32-bit FNV-1a accumulator and then run through splitmix32 to destroy any structural correlation in the input alphabet. Number inputs are converted straight to uint32 (via >>> 0) before mixing — so seed -1 and seed 0xFFFFFFFF are intentionally equivalent. Non-safe integers are rejected because >>> 0 would silently truncate them and lose user intent.