code wiki / _hdl_build / nx_random_gate.nx
nx_random_gate.nx source
↩ module page · 91 lines · 3999 B
1// nx_random_gate.nx -- GATE for nx_random (xoshiro256++ PRNG). Flagged by the HONESTY SYSTEM 2026-07-16:
2// reach=554 organs (fuzzing, sampling, hash-key randomization) with ZERO direct validation. A PRNG is
3// deterministic BY CONTRACT -- so the gate proves: same-seed reproducibility, seed sensitivity, bound
4// respect, bit balance (stuck-stream killer), fill correctness. license_tier: ORIGINAL expect_exit:0
5import "nx_syscalls.nx"
6import "nx_random.nx"
7
8func qw(s: *u8) -> i64 { var n:i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
9func qn(v: i64) -> i64 { let b:*u8=sys_mmap(24); var m:i64=v; if m<0{sys_write(1,"-" as *u8,1);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} var j:i64=0; while j<k{b[j]=t[k-1-j];j=j+1} sys_write(1,b,k); return 0 }
10// popcount of an i64 via masked 32-bit halves (avoids negative-shift ambiguity)
11func pop64(v: i64) -> i64 {
12 var lo: i64 = v & 0xffffffff
13 var hi: i64 = (v >> 32) & 0xffffffff
14 var c: i64 = 0
15 var i: i64 = 0
16 while i < 32 { c = c + (lo & 1) + (hi & 1); lo = lo >> 1; hi = hi >> 1; i = i + 1 }
17 return c
18}
19
20func main() -> i64 {
21 var pass: i64 = 0
22
23 // T1: determinism -- same seed, same first 8 outputs
24 let ra: *NxRng = nx_rng_new(12345)
25 let rb: *NxRng = nx_rng_new(12345)
26 var same: i64 = 1
27 var i: i64 = 0
28 while i < 8 { if nx_rng_next(ra) != nx_rng_next(rb) { same = 0 } i = i + 1 }
29 if same == 1 { pass = pass + 1; qw("T1 determinism PASS\n" as *u8) } else { qw("T1 FAIL same-seed divergence\n" as *u8) }
30
31 // T2: seed sensitivity -- adjacent seeds diverge within 8 outputs
32 let rc: *NxRng = nx_rng_new(12345)
33 let rd: *NxRng = nx_rng_new(12346)
34 var dif: i64 = 0
35 i = 0
36 while i < 8 { if nx_rng_next(rc) != nx_rng_next(rd) { dif = 1 } i = i + 1 }
37 if dif == 1 { pass = pass + 1; qw("T2 seed-sensitivity PASS\n" as *u8) } else { qw("T2 FAIL adjacent seeds identical\n" as *u8) }
38
39 // T3: bounded draws stay in [0,100) over 1000
40 let re: *NxRng = nx_rng_new(777)
41 var ok3: i64 = 1
42 i = 0
43 while i < 1000 {
44 let v: i64 = nx_rng_below(re, 100)
45 if v < 0 { ok3 = 0 }
46 if v >= 100 { ok3 = 0 }
47 i = i + 1
48 }
49 if ok3 == 1 { pass = pass + 1; qw("T3 bounded PASS\n" as *u8) } else { qw("T3 FAIL out-of-bounds\n" as *u8) }
50
51 // T4: bit balance over 4096 draws (262144 bits, expect ~131072 ones, tolerate +-5%)
52 let rf: *NxRng = nx_rng_new(424242)
53 var ones: i64 = 0
54 i = 0
55 while i < 4096 { ones = ones + pop64(nx_rng_next(rf)); i = i + 1 }
56 if ones > 124517 { if ones < 137627 { pass = pass + 1; qw("T4 bit-balance PASS ones=" as *u8); qn(ones); qw("\n" as *u8) } else { qw("T4 FAIL ones=" as *u8); qn(ones); qw("\n" as *u8) } } else { qw("T4 FAIL ones=" as *u8); qn(ones); qw("\n" as *u8) }
57
58 // T5: fill fills, and two fills differ
59 let ba: *u8 = sys_mmap(256)
60 let bb: *u8 = sys_mmap(256)
61 let rg: *NxRng = nx_rng_new(99)
62 nx_rng_fill(rg, ba, 128)
63 nx_rng_fill(rg, bb, 128)
64 var d5: i64 = 0
65 var nz5: i64 = 0
66 i = 0
67 while i < 128 {
68 if ba[i] != bb[i] { d5 = 1 }
69 if ba[i] != (0 as u8) { nz5 = 1 }
70 i = i + 1
71 }
72 if d5 == 1 { if nz5 == 1 { pass = pass + 1; qw("T5 fill PASS\n" as *u8) } else { qw("T5 FAIL zero fill\n" as *u8) } } else { qw("T5 FAIL fills identical\n" as *u8) }
73
74 // T6: no stuck stream -- 1000 consecutive outputs are not all equal
75 let rh: *NxRng = nx_rng_new(31337)
76 var prev: i64 = nx_rng_next(rh)
77 var moved: i64 = 0
78 i = 0
79 while i < 1000 {
80 let nv: i64 = nx_rng_next(rh)
81 if nv != prev { moved = 1 }
82 prev = nv
83 i = i + 1
84 }
85 if moved == 1 { pass = pass + 1; qw("T6 not-stuck PASS\n" as *u8) } else { qw("T6 FAIL stuck stream\n" as *u8) }
86
87 qw("NX-RANDOM GATE " as *u8); qn(pass); qw("/6" as *u8)
88 if pass == 6 { qw(" GREEN\n" as *u8); return 0 }
89 qw(" RED\n" as *u8)
90 return 1
91}