code wiki / _hdl_build / nx_refbench.nx

nx_refbench.nx source

↩ module page · 126 lines · 5073 B

1// nx_refbench.nx -- CLI/MCP surface for the reference-retention ruler. 2// All measurement lives in nx_refbench_lib.nx, which the GATE imports too, so the thing 3// that ships and the thing that is graded are the same code. 4// 5// VERBS 6// compare <ref.png> <gen.png> -> JSON {ref/gen dims, plane, structure, perceptual, retention} 7// selftest -> the anti-vacuity pair (identity must be 1000, mirror must not be) 8// 9// The full teeth live in nx_refbench_gate.nx; `selftest` is the fast in-tool smoke so an 10// agent calling this over MCP can confirm the instrument is sane before trusting a number. 11// expect_exit: 0 license_tier: ORIGINAL 12import "nx_refbench_lib.nx" 13import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 14 15func rb_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 16 17// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 18// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 19// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 20// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 21func rb_num(v: i64) -> i64 { nxi_out(v); return 0 } 22 23func rb_report(label: *u8, sp: i64, pp: i64) -> i64 { 24 rb_puts("{\"pair\":\"" as *u8); rb_puts(label) 25 rb_puts("\",\"structure_permil\":" as *u8); rb_num(sp) 26 rb_puts(",\"perceptual_permil\":" as *u8); rb_num(pp) 27 rb_puts(",\"retention_permil\":" as *u8); rb_num(rb_retention(sp, pp)) 28 rb_puts(",\"headline\":\"MIN-of-channels\"}\n" as *u8) 29 return 0 30} 31 32// Fast in-tool smoke: the same two poles the gate proves at depth. 33func rb_selftest() -> i64 { 34 let side: i64 = 64 35 let a: *u8 = sys_mmap(side * side) 36 let b: *u8 = sys_mmap(side * side) 37 var y: i64 = 0 38 while y < side { 39 var x: i64 = 0 40 while x < side { 41 a[y * side + x] = (((x * 3 + y * 5) % 256) as u8) 42 // horizontally MIRRORED: identical histogram, different structure -- the case 43 // a naive mean/histogram comparator would wrongly call identical 44 b[y * side + x] = (((((side - 1 - x) * 3 + y * 5) % 256)) as u8) 45 x = x + 1 46 } 47 y = y + 1 48 } 49 let s1: *i64 = sys_mmap(8) 50 let p1: *i64 = sys_mmap(8) 51 rb_compare(a, side, side, a, side, side, s1, p1) 52 let t1s: i64 = s1[0] 53 let t1p: i64 = p1[0] 54 rb_puts("T1 identity " as *u8); rb_report("self-vs-self" as *u8, t1s, t1p) 55 56 let s2: *i64 = sys_mmap(8) 57 let p2: *i64 = sys_mmap(8) 58 rb_compare(a, side, side, b, side, side, s2, p2) 59 let t2s: i64 = s2[0] 60 let t2p: i64 = p2[0] 61 rb_puts("T2 mirrored " as *u8); rb_report("self-vs-mirror" as *u8, t2s, t2p) 62 63 var pass: i64 = 0 64 var fail: i64 = 0 65 if t1s >= 995 { pass = pass + 1 } else { fail = fail + 1 } 66 if t1p >= 995 { pass = pass + 1 } else { fail = fail + 1 } 67 if t2s < 900 { pass = pass + 1 } else { fail = fail + 1 } 68 rb_puts("SELFTEST pass=" as *u8); rb_num(pass) 69 rb_puts(" fail=" as *u8); rb_num(fail) 70 if fail == 0 { rb_puts(" verdict=GREEN\n" as *u8) } else { rb_puts(" verdict=RED\n" as *u8) } 71 return fail 72} 73 74func rb_streq(a: *u8, b: *u8) -> i64 { 75 var i: i64 = 0 76 while a[i] != (0 as u8) { 77 if a[i] != b[i] { return 0 } 78 i = i + 1 79 } 80 if b[i] != (0 as u8) { return 0 } 81 return 1 82} 83 84func main(argc: i64, argv: *i64) -> i64 { 85 if argc < 2 { 86 rb_puts("usage: nx_refbench selftest | nx_refbench compare <ref.png> <gen.png>\n" as *u8) 87 return 2 88 } 89 let verb: *u8 = argv[1] as *u8 90 if rb_streq(verb, "selftest" as *u8) == 1 { return rb_selftest() } 91 if rb_streq(verb, "compare" as *u8) == 1 { 92 if argc < 4 { 93 rb_puts("{\"error\":\"compare needs <ref.png> <gen.png>\"}\n" as *u8) 94 return 2 95 } 96 let pa: *u8 = argv[2] as *u8 97 let pb: *u8 = argv[3] as *u8 98 let wa: *i64 = sys_mmap(8) 99 let ha: *i64 = sys_mmap(8) 100 let wb: *i64 = sys_mmap(8) 101 let hb: *i64 = sys_mmap(8) 102 let ga: *u8 = rb_load_gray(pa, wa, ha) 103 if ga == (0 as *u8) { 104 rb_puts("{\"error\":\"cannot decode reference PNG\"}\n" as *u8) 105 return 3 106 } 107 let gb: *u8 = rb_load_gray(pb, wb, hb) 108 if gb == (0 as *u8) { 109 rb_puts("{\"error\":\"cannot decode generated PNG\"}\n" as *u8) 110 return 3 111 } 112 let sp: *i64 = sys_mmap(8) 113 let pp: *i64 = sys_mmap(8) 114 rb_compare(ga, wa[0], ha[0], gb, wb[0], hb[0], sp, pp) 115 rb_puts("{\"ref_w\":" as *u8); rb_num(wa[0]) 116 rb_puts(",\"ref_h\":" as *u8); rb_num(ha[0]) 117 rb_puts(",\"gen_w\":" as *u8); rb_num(wb[0]) 118 rb_puts(",\"gen_h\":" as *u8); rb_num(hb[0]) 119 rb_puts(",\"plane\":" as *u8); rb_num(RB_PLANE) 120 rb_puts("}\n" as *u8) 121 rb_report("ref-vs-gen" as *u8, sp[0], pp[0]) 122 return 0 123 } 124 rb_puts("{\"error\":\"unknown verb\"}\n" as *u8) 125 return 2 126}