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}