code wiki / _hdl_build / nx_refbench_gate.nx
nx_refbench_gate.nx source
↩ module page · 169 lines · 8638 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"
23
24func gw(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
25func gn(v: i64) -> i64 {
26 let b: *u8 = sys_mmap(28)
27 var m: i64 = v
28 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
29 let t: *u8 = sys_mmap(28)
30 var k: i64 = 0
31 if m == 0 { t[0] = (48 as u8); k = 1 }
32 while m > 0 { t[k] = ((48 + (m % 10)) as u8); m = m / 10; k = k + 1 }
33 var i: i64 = 0
34 while i < k { b[i] = t[k - 1 - i]; i = i + 1 }
35 sys_write(1, b, k)
36 return 0
37}
38
39// A deterministic structured field: coarse blocks + a diagonal ramp, so SSIM has real
40// local variance to work with. A flat field would score 1000 vacuously and prove nothing.
41func g_make(side: i64) -> *u8 {
42 let p: *u8 = sys_mmap(side * side)
43 var y: i64 = 0
44 while y < side {
45 var x: i64 = 0
46 while x < side {
47 let blk: i64 = (((x * 8 / side) + (y * 8 / side)) % 2) * 90
48 let ramp: i64 = ((x + y) * 160) / (side * 2)
49 p[y * side + x] = (((blk + ramp) % 256) as u8)
50 x = x + 1
51 }
52 y = y + 1
53 }
54 return p
55}
56
57// Knuth MMIX linear-congruential constants. Named because rule 11 is right: a reader
58// must be able to ask "why this number?" and get an answer other than "it was there".
59const RB_LCG_MULT: i64 = 6364136223846793005
60const RB_LCG_INC: i64 = 1442695040888963407
61// Fixed corruption seed: the gate must be REPRODUCIBLE, so the noise pattern is pinned
62// rather than drawn from a clock. Any fixed value works; it is pinned, not tuned.
63const RB_GATE_SEED: i64 = 12345
64
65// deterministic LCG -- no clock, no /dev/urandom, so gate runs are reproducible
66func g_rnd(st: *i64) -> i64 {
67 st[0] = (st[0] * RB_LCG_MULT + RB_LCG_INC)
68 var v: i64 = st[0] >> 33
69 if v < 0 { v = 0 - v }
70 return v
71}
72
73// corrupt `pct` percent of pixels to a pseudo-random value (deterministic given seed)
74func g_corrupt(src: *u8, side: i64, pct: i64, seed: i64) -> *u8 {
75 let d: *u8 = sys_mmap(side * side)
76 let st: *i64 = sys_mmap(8)
77 st[0] = seed
78 var i: i64 = 0
79 while i < side * side {
80 d[i] = src[i]
81 if (g_rnd(st) % 100) < pct { d[i] = ((g_rnd(st) % 256) as u8) }
82 i = i + 1
83 }
84 return d
85}
86
87func main() -> i64 {
88 gw("=== nx_refbench_gate: is the reference-retention ruler actually a ruler? ===\n" as *u8)
89 var pass: i64 = 0
90 var total: i64 = 0
91 let side: i64 = 128
92 let base: *u8 = g_make(side)
93 let sp: *i64 = sys_mmap(8)
94 let pp: *i64 = sys_mmap(8)
95
96 // ---- T1 IDENTITY ----
97 rb_compare(base, side, side, base, side, side, sp, pp)
98 let t1s: i64 = sp[0]
99 let t1p: i64 = pp[0]
100 total = total + 1
101 if t1s >= 995 { if t1p >= 995 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
102 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)
103
104 // ---- T2 DISCRIMINATION (mirror: same histogram, different structure) ----
105 let mir: *u8 = sys_mmap(side * side)
106 var y: i64 = 0
107 while y < side {
108 var x: i64 = 0
109 while x < side { mir[y * side + x] = base[y * side + (side - 1 - x)]; x = x + 1 }
110 y = y + 1
111 }
112 rb_compare(base, side, side, mir, side, side, sp, pp)
113 let t2s: i64 = sp[0]
114 let t2r: i64 = rb_retention(sp[0], pp[0])
115 total = total + 1
116 if t2s < 900 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
117 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)
118
119 // ---- T3 SCALE INVARIANCE (the production case: big ref vs small render) ----
120 let small: *u8 = sys_mmap(64 * 64)
121 nx_phash_downscale(base, side, side, small, 64, 64)
122 rb_compare(base, side, side, small, 64, 64, sp, pp)
123 let t3s: i64 = sp[0]
124 let t3r: i64 = rb_retention(sp[0], pp[0])
125 total = total + 1
126 if t3r >= 700 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
127 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)
128
129 // ---- T4 MONOTONICITY (licenses reading the L3 curve as a curve) ----
130 let c10: *u8 = g_corrupt(base, side, 10, RB_GATE_SEED)
131 let c30: *u8 = g_corrupt(base, side, 30, RB_GATE_SEED)
132 let c60: *u8 = g_corrupt(base, side, 60, RB_GATE_SEED)
133 rb_compare(base, side, side, c10, side, side, sp, pp)
134 let r10: i64 = rb_retention(sp[0], pp[0])
135 rb_compare(base, side, side, c30, side, side, sp, pp)
136 let r30: i64 = rb_retention(sp[0], pp[0])
137 rb_compare(base, side, side, c60, side, side, sp, pp)
138 let r60: i64 = rb_retention(sp[0], pp[0])
139 total = total + 1
140 if r10 > r30 { if r30 > r60 { pass = pass + 1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
141 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)
142
143 // ---- T5 MIN-HEADLINE (a strong channel may never flatter a weak one) ----
144 let m1: i64 = rb_retention(900, 300)
145 let m2: i64 = rb_retention(300, 900)
146 let m3: i64 = rb_retention(500, 500)
147 total = total + 1
148 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) }
149 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)
150
151 // ---- T6 FAIL-CLOSED (the blank-decoy trap) ----
152 let bw: *i64 = sys_mmap(8)
153 let bh: *i64 = sys_mmap(8)
154 let miss: *u8 = rb_load_gray("/nonexistent/nx_refbench_gate_absent.png" as *u8, bw, bh)
155 let notpng: *u8 = rb_load_gray("/etc/hostname" as *u8, bw, bh)
156 total = total + 1
157 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) }
158 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)
159
160 gw("\n=== nx_refbench_gate " as *u8); gn(pass); gw("/" as *u8); gn(total)
161 if pass == total {
162 gw(" verdict=GREEN -- 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 trusted as MEASUREMENTS.\n" as *u8)
163 sys_exit(0)
164 return 0
165 }
166 gw(" verdict=RED\n" as *u8)
167 sys_exit(1)
168 return 1
169}