Skip to content

[M0-CORE-06] Deterministic PRNG: xorshift128+ + splitmix64 seeding, per-substream derivation, period proof - #6

Merged
offdev merged 1 commit into
masterfrom
m0-core-06-prng
Sep 11, 2026
Merged

offdev merged 1 commit into
masterfrom
m0-core-06-prng

Conversation

@offdev

@offdev offdev commented Sep 11, 2026

Copy link
Copy Markdown
Owner

Implements roadmap step M0-CORE-06 (PRD §10.3 "seeded, per-substream" randomness, AGENTS ARCH-010): laige::Prng in a new header-only src/laige-core/include/laige/prng.h, with the committed period proof in the test suite.

What

  • Core algorithm — xorshift128+ (Johnson 2009), transcribed from and verified against the reference implementation (lemire/SIMDxorshift xorshift128plus.c): state (part1, part2), step part1 = o1; t = o0 ^ (o0 << 23); part2 = t ^ o1 ^ (t >> 18) ^ (o1 >> 5); out = part2 + o1 (unsigned wrap); the all-zero state is excluded and unreachable. The algorithm is the determinism contract — the golden vectors intentionally fail if it changes (ARCH-010, ADR 0002).
  • Seeding — first two splitmix64 (Stafford 2018) outputs from seed + K (K = 0x9E3779B97F4A7C15 = kSplitmix64Increment; named mix constants). splitmix64 is a bijection with two inputs differing by nonzero K, so no 64-bit seed reaches the zero state.
  • Substreams — documented derivation deriveSubstream(seed, id) == Prng(seed + id * K) (id 0 = master stream; composes: derive(derive(s, i), j) == derive(s, i + j)). substream(id) derives from the seed, not from the current position.
  • API — next_u64(), next_range(min, max) (Lemire unbiased reduction; min >= max is a debug assert / documented UB), next_float01() (next_u64() >> 40 * 2^-24 — exactly k * 2^-24, 24-bit resolution, [0, 1), bit-exact), seed(), substream(id), deriveSubstream(seed, id), and public statics seedState / stepState for determinism verification and M1 save/replay (a saved stream is (seed, part1, part2)). Value type (copy = shared stream position, documented), single-owner, not thread-safe (CONC-001), no allocation, NFR-8.10 policy.
  • Determinism scope (ARCH-010/ADR 0002) — pure unsigned integer arithmetic plus one multiply by the exactly representable 2^-24: cross-platform bit-exact. Golden KATs on seed 0x1234567890ABCDEF: 32 draws + FNV-1a-of-first-4096 replay hash 0xB64E76173859B6D8.
  • Period — proven, not sampled: every nonzero state has period exactly 2^128 − 1. The PrngPeriod suite reconstructs the state map's characteristic polynomial over GF(2) from a 512-bit probe orbit via Berlekamp-Massey (the BM connection polynomial is the reciprocal of the characteristic polynomial — the recurrence relates p[t] to lower indices), checks P(A) = 0 on all 128 basis states, then verifies P irreducible (Ruffini: x^(2^128) ≡ x (mod P) and gcd(x^(2^d) − x, P) = 1 for d ∈ {1,2,4,8,16,32,64}) and primitive (P | x^(2^128−1) − 1 with no q-th root for the nine prime factors of 2^128 − 1 = 3·5·17·257·641·65537·6700417·274177·67280421310721; primality by Miller-Rabin, factorization by portable 128-bit multiply — no __int128/builtins, MSVC-compatible). A primitive characteristic polynomial of an invertible linear map over GF(2) is exactly maximal period for every nonzero state.
  • Docs — docs/api/prng.md (API contracts, Performance per DOC-004, misuse warnings, save/replay).
  • Roadmap step recorded with Decision/Verify/Size.

Verification (local, 2026-09-11)

  • ctest -R prng: 18 GTest cases green — PrngGolden (32-draw KAT, FNV-1a replay hash, 10^4-step reference transcription check, zero-state seeding spot check over 100k seeds), PrngRange (5 KATs incl. the power-of-two fast path, span-1 identity, 110k in-bounds draws over 10 spans, unbiasedness: 2^18 draws over 8-way and 3-way spans within ~10 sigma), PrngFloat01 (8-draw KAT, 2^16 draws: dyadic exactness, [0, 1) bounds, mean 0.5 ± 14 sigma), PrngSubstreams (8 id KATs, id-0 = master, derivation composition, same-id determinism, 2^16-draw cross-substream overlap check), PrngPeriod (the characteristic-polynomial proof above + empirical screen: no duplicate in 4M draws, no period-q window pattern for the eight small prime factors of 2^128 − 1).
  • Full suite 12/12 on GCC 16.2.1 (build static, build-shared, build-asan ASan+UBSan fatal, build-tsan TSan halt_on_error=1) and Clang 22.1.8 (build-clang) — the KAT constants are identical across the two compilers (local two-compiler run; CI hookup lands in M1-DET-04), zero warnings under the NFR-8.10 policy (-Wall -Werror -fno-exceptions -fno-rtti), incl. the real-tree include-lint.

The CI lane will additionally cover the P0 Windows job (MSVC compile of the new header and the portable GF(2) test machinery) and macOS.

…ubstreams, period proof

laige::Prng (header-only): xorshift128+ (reference-transcribed and
verified), splitmix64 seeding (zero state unreachable), documented
substream derivation (Prng(seed + id*K), id 0 = master, composes),
next_u64 / next_range (Lemire unbiased) / next_float01 (exact 24-bit
dyadic). Public seedState/stepState for determinism verification and
M1 save/replay. Determinism scope: cross-platform bit-exact (pure
unsigned integer arithmetic + one exact power-of-two scale, ADR 0002).

Tests (ctest -R prng, 18 cases): golden KATs on seed 0x1234567890ABCDEF
(32 draws + FNV-1a-of-4096 replay hash; intentionally algorithm-
sensitive), 10^4-step reference transcription check, zero-state
seeding spot check, next_range KATs + unbiasedness, next_float01
dyadic exactness, substream derivation KATs + composition + overlap
sanity, and the committed period proof: the state map's
characteristic polynomial over GF(2) (reconstructed via
Berlekamp-Massey on a probe orbit, as the reciprocal of the BM
connection polynomial) is checked to annihilate the map on all 128
basis states, irreducible (Ruffini), and primitive (full factorization
of 2^128-1, Miller-Rabin, portable 128-bit multiply) => every nonzero
state has period exactly 2^128 - 1; plus an empirical short-cycle
screen of the output stream. GF(2)/BM/MR machinery is self-contained
and portable (no __int128/builtins).

Verified locally 2026-09-11: 12/12 ctest on GCC 16.2.1 (static, shared,
ASan+UBSan, TSan halt_on_error=1) and Clang 22.1.8; KAT constants
identical across the two compilers (CI hookup M1-DET-04); zero
warnings under the NFR-8.10 policy.
@offdev
offdev merged commit a82de8e into master Sep 11, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant