Completes ticket 0001 started in27f468c. All three impls now carry bit-identical xoshiro256**; portal state round-trips across process boundaries in every producer x consumer cell (Python <-> C <-> asm). asm impl: - 4 new builtins: random-seed!, random-int, random-state, random-state! - g_rng_state in BSS (4 x u64); rng_splitmix64_step, rng_seed, rng_next - Binary portal header bumped LUMBDAB1/48 -> LUMBDAB2/80; carries 32 bytes of rng state at offsets 40..64, reserved moved to 72 - No float support in asm, so (random) intentionally omitted there - _start seeds with 0 so the stream is deterministic from startup Python + C (supplements27f468c): - rng_seed(0) auto-invoked at module load / register_portal_builtins so (random) without explicit (random-seed!) returns a real value instead of the all-zero xoshiro fixed point Tests: - tests/functional.lsp: 7 new shared assertions (Python + C) - asm/test.sh: 5 new asm-local assertions (142 -> 147) - tests/portal-rng-save.lsp / portal-rng-load.lsp: portable S-expression portal that captures both state AND next-5 baseline so loader self- verifies without a separate harness - tests/portal-cross-test.sh: 9 new producer x consumer RNG cells; all 18 cells pass end-to-end Verified: seed=42, (random-int 1000000) draws 1..10 = 558742 543102 559009 124193 317476 750584 200754 814407 344958 929085 identical in Python, C, and asm. unmoad scan: zero new findings in added code.
30 lines
1.2 KiB
Text
30 lines
1.2 KiB
Text
;;; portal-rng-save.lsp — seed, advance, capture state AND next-5 baseline
|
|
;;; to /tmp/cross-rng.sexp so another impl can resume and self-verify.
|
|
;;;
|
|
;;; Uses S-expression portal (portable across Python, C, asm) rather than
|
|
;;; impl-specific JSON/binary format. Proves: (random-state) + (random-state!)
|
|
;;; preserves xoshiro256** state across processes AND implementations.
|
|
|
|
(random-seed! 42)
|
|
|
|
;; Advance the stream by 5 draws.
|
|
(define (advance n)
|
|
(if (= n 0) 'done (begin (random-int 1000000) (advance (- n 1)))))
|
|
(advance 5)
|
|
|
|
;; Snapshot state *before* drawing the 5 baseline values.
|
|
(define rng-snapshot (random-state))
|
|
|
|
;; Compute next 5 draws — these are the baseline the loader must reproduce.
|
|
(define baseline
|
|
(list (random-int 1000000) (random-int 1000000) (random-int 1000000)
|
|
(random-int 1000000) (random-int 1000000)))
|
|
|
|
;; Write a portable portal file. Any impl can (load) it.
|
|
(define port (open-output-file "/tmp/cross-rng.sexp"))
|
|
(display ";; lumbda cross-impl RNG portal (S-expression)\n" port)
|
|
(display "(random-state! '" port) (write rng-snapshot port) (display ")\n" port)
|
|
(display "(define expected-baseline '" port) (write baseline port) (display ")\n" port)
|
|
(close-port port)
|
|
|
|
(display "saved baseline: ") (display baseline) (newline)
|