code wiki / _hdl_build / nx_refbench_gate.nx

nx_refbench_gate.nx source

↩ module page · 171 lines · 8954 B

1// nx_refbench_gate.nx -- proves the reference-retention ruler is a RULER and not a rubber stamp. 2// It imports the SAME lib the shipping tool imports, so it grades the code that ships. 3// 4// T1 IDENTITY : an image against ITSELF must score 1000 on BOTH channels. 5// T2 DISCRIMINATION : a MIRRORED copy (identical histogram, different structure) must score 6// materially LOWER. This is the anti-vacuity tooth -- a ruler that has never 7// been seen to say NO is not a ruler. 8// T3 SCALE INVARIANCE: the same content at a DIFFERENT SIZE must still score high. This is the 9// real production case (2550x3300 reference vs 768x1024 render); if it failed, 10// every retention number would be measuring resolution, not content. 11// T4 MONOTONICITY : increasing corruption must produce MONOTONICALLY FALLING retention. The 12// whole L3 denoise curve is worthless if the ruler does not ORDER correctly -- 13// this tooth is what licenses reading the curve as a curve. 14// T5 MIN-HEADLINE : retention must equal the WEAKEST channel, never the mean. Proven with a 15// planted split (strong one side, weak the other) so a good channel can never 16// flatter a bad one. 17// T6 FAIL-CLOSED : an unreadable/absent image must return an ERROR, never a score. Two failed 18// decodes must NOT both become zeroed planes and score a perfect 1000 against 19// each other -- the blank-decoy trap that already fooled an artifact tooth in 20// this ecosystem (a failing producer wrote a valid PNG of an empty render). 21// expect_exit: 0 license_tier: ORIGINAL 22import "nx_refbench_lib.nx" 23import "nx_gate_verdict.nx" 24 25func gw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 26func gn(v: i64) -> i64 { 27 let b: *u8 = sys_mmap(28) 28 var m: i64 = v 29 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m } 30 let t: *u8 = sys_mmap(28) 31 var k: i64 = 0 32 if m == 0 { t[0] = (48 as u8); k = 1 } 33 while m > 0 { t[k] = ((48 + (m % 10)) as u8); m = m / 10; k = k + 1 } 34 var i: i64 = 0 35 while i < k { b[i] = t[k - 1 - i]; i = i + 1 } 36 sys_write(1, b, k) 37 return 0 38} 39 40// A deterministic structured field: coarse blocks + a diagonal ramp, so SSIM has real 41// local variance to work with. A flat field would score 1000 vacuously and prove nothing. 42func g_make(side: i64) -> *u8 { 43 let p: *u8 = sys_mmap(side * side) 44 var y: i64 = 0 45 while y < side { 46 var x: i64 = 0 47 while x < side { 48 let blk: i64 = (((x * 8 / side) + (y * 8 / side)) % 2) * 90 49 let ramp: i64 = ((x + y) * 160) / (side * 2) 50 p[y * side + x] = (((blk + ramp) % 256) as u8) 51 x = x + 1 52 } 53 y = y + 1 54 } 55 return p 56} 57 58// Knuth MMIX linear-congruential constants. Named because rule 11 is right: a reader 59// must be able to ask "why this number?" and get an answer other than "it was there". 60const RB_LCG_MULT: i64 = 6364136223846793005 61const RB_LCG_INC: i64 = 1442695040888963407 62// Fixed corruption seed: the gate must be REPRODUCIBLE, so the noise pattern is pinned 63// rather than drawn from a clock. Any fixed value works; it is pinned, not tuned. 64const RB_GATE_SEED: i64 = 12345 65 66// deterministic LCG -- no clock, no /dev/urandom, so gate runs are reproducible 67func g_rnd(st: *i64) -> i64 { 68 st[0] = (st[0] * RB_LCG_MULT + RB_LCG_INC) 69 var v: i64 = st[0] >> 33 70 if v < 0 { v = 0 - v } 71 return v 72} 73 74// corrupt `pct` percent of pixels to a pseudo-random value (deterministic given seed) 75func g_corrupt(src: *u8, side: i64, pct: i64, seed: i64) -> *u8 { 76 let d: *u8 = sys_mmap(side * side) 77 let st: *i64 = sys_mmap(8) 78 st[0] = seed 79 var i: i64 = 0 80 while i < side * side { 81 d[i] = src[i] 82 if (g_rnd(st) % 100) < pct { d[i] = ((g_rnd(st) % 256) as u8) } 83 i = i + 1 84 } 85 return d 86} 87 88func main() -> i64 { 89 gw("=== nx_refbench_gate: is the reference-retention ruler actually a ruler? ===\n" as *u8) 90 var pass: i64 = 0 91 var total: i64 = 0 92 let side: i64 = 128 93 let base: *u8 = g_make(side) 94 let sp: *i64 = sys_mmap(8) 95 let pp: *i64 = sys_mmap(8) 96 97 // ---- T1 IDENTITY ---- 98 rb_compare(base, side, side, base, side, side, sp, pp) 99 let t1s: i64 = sp[0] 100 let t1p: i64 = pp[0] 101 total = total + 1 102 if t1s >= 995 { if t1p >= 995 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) } 103 gw("T1 IDENTITY: self-vs-self structure=" as *u8); gn(t1s); gw(" perceptual=" as *u8); gn(t1p); gw(" (both must be >=995)\n" as *u8) 104 105 // ---- T2 DISCRIMINATION (mirror: same histogram, different structure) ---- 106 let mir: *u8 = sys_mmap(side * side) 107 var y: i64 = 0 108 while y < side { 109 var x: i64 = 0 110 while x < side { mir[y * side + x] = base[y * side + (side - 1 - x)]; x = x + 1 } 111 y = y + 1 112 } 113 rb_compare(base, side, side, mir, side, side, sp, pp) 114 let t2s: i64 = sp[0] 115 let t2r: i64 = rb_retention(sp[0], pp[0]) 116 total = total + 1 117 if t2s < 900 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 118 gw("T2 DISCRIMINATION: mirrored copy structure=" as *u8); gn(t2s); gw(" retention=" as *u8); gn(t2r); gw(" (must be <900 -- the ruler can say NO)\n" as *u8) 119 120 // ---- T3 SCALE INVARIANCE (the production case: big ref vs small render) ---- 121 let small: *u8 = sys_mmap(64 * 64) 122 nx_phash_downscale(base, side, side, small, 64, 64) 123 rb_compare(base, side, side, small, 64, 64, sp, pp) 124 let t3s: i64 = sp[0] 125 let t3r: i64 = rb_retention(sp[0], pp[0]) 126 total = total + 1 127 if t3r >= 700 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } 128 gw("T3 SCALE INVARIANCE: 128x128 vs its own 64x64 downscale retention=" as *u8); gn(t3r); gw(" (>=700: size must not read as content)\n" as *u8) 129 130 // ---- T4 MONOTONICITY (licenses reading the L3 curve as a curve) ---- 131 let c10: *u8 = g_corrupt(base, side, 10, RB_GATE_SEED) 132 let c30: *u8 = g_corrupt(base, side, 30, RB_GATE_SEED) 133 let c60: *u8 = g_corrupt(base, side, 60, RB_GATE_SEED) 134 rb_compare(base, side, side, c10, side, side, sp, pp) 135 let r10: i64 = rb_retention(sp[0], pp[0]) 136 rb_compare(base, side, side, c30, side, side, sp, pp) 137 let r30: i64 = rb_retention(sp[0], pp[0]) 138 rb_compare(base, side, side, c60, side, side, sp, pp) 139 let r60: i64 = rb_retention(sp[0], pp[0]) 140 total = total + 1 141 if r10 > r30 { if r30 > r60 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) } 142 gw("T4 MONOTONICITY: corruption 10%->" as *u8); gn(r10); gw(" 30%->" as *u8); gn(r30); gw(" 60%->" as *u8); gn(r60); gw(" (must strictly fall)\n" as *u8) 143 144 // ---- T5 MIN-HEADLINE (a strong channel may never flatter a weak one) ---- 145 let m1: i64 = rb_retention(900, 300) 146 let m2: i64 = rb_retention(300, 900) 147 let m3: i64 = rb_retention(500, 500) 148 total = total + 1 149 if m1 == 300 { if m2 == 300 { if m3 == 500 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) } 150 gw("T5 MIN-HEADLINE: (900,300)->" as *u8); gn(m1); gw(" (300,900)->" as *u8); gn(m2); gw(" (500,500)->" as *u8); gn(m3); gw(" (never the mean=600)\n" as *u8) 151 152 // ---- T6 FAIL-CLOSED (the blank-decoy trap) ---- 153 let bw: *i64 = sys_mmap(8) 154 let bh: *i64 = sys_mmap(8) 155 let miss: *u8 = rb_load_gray("/nonexistent/nx_refbench_gate_absent.png" as *u8, bw, bh) 156 let notpng: *u8 = rb_load_gray("/etc/hostname" as *u8, bw, bh) 157 total = total + 1 158 if miss == (0 as *u8) { if notpng == (0 as *u8) { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) } 159 gw("T6 FAIL-CLOSED: absent file and non-PNG both refuse (null, not a zeroed plane that would score 1000 vs another)\n" as *u8) 160 161 gw("\n=== nx_refbench_gate " as *u8); gn(pass); gw("/" as *u8); gn(total) 162 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 163 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 164 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 165 let ctr__dry: *i64 = gv_ctr() 166 ctr__dry[0] = pass 167 ctr__dry[1] = total 168 let rc__dry: i64 = gv_verdict("REFBENCH-GATE" as *u8, ctr__dry, "identity is perfect, a mirror is rejected, size does not read as content, corruption orders monotonically, the headline is the weakest channel, and an unreadable image refuses instead of scoring. Retention numbers from this ruler can be" as *u8) 169 sys_exit(rc__dry) 170 return rc__dry 171}