code wiki / (root) / nx_kubelka_gate.nx

nx_kubelka_gate.nx source

↩ module page · 150 lines · 7487 B

1// nx_kubelka_gate.nx -- THE GATE FOR THE KUBELKA-MUNK CHROMOPHORE SUBSTRATE, 2026-09-03. 2// 3// SUBJECT: km_r_from_ks / km_ks_from_r / km_ks_mix / km_r_of_mix in-process (the lib has no main). 4// 5// WHAT MAKES THESE TEETH NON-VACUOUS. This model needs no external table to be falsifiable: it carries its 6// own oracle. The forward and the inverse are independent closed forms, so a ROUND TRIP over a ladder of 7// reflectances convicts either one of them being wrong -- a mistyped forward cannot invert back to where it 8// started. The physical checks are the ones that matter for skin: more melanin must be DARKER, more 9// haemoglobin must be DARKER, and reflectance must stay inside [0,1] for every input on the ladder. 10// 11// Teeth, in order: 12// T1 zero absorption is unit reflectance, EXACTLY (not within a tolerance -- the algebra is exact there). 13// T2 the ladder is NON-DEGENERATE: it spans real range. Without this, T3 and T4 could pass on a constant. 14// T3 ROUND TRIP r -> K/S -> r over the whole ladder, every rung, no sampling. 15// T4 monotone: reflectance falls as K/S rises, strictly, across every adjacent pair. 16// T5 bounds: every reflectance on the ladder lies in [0,1]. 17// T6 PHYSICAL: more melanin is strictly darker. 18// T7 PHYSICAL: more haemoglobin is strictly darker. 19// T8 NEG-CONTROL: a non-positive scattering coefficient REFUSES rather than dividing by zero. 20// T9 NEG-CONTROL: inverting a reflectance of zero REFUSES rather than returning an infinity as a number. 21// T10 NEG-CONTROL: inverting a reflectance above one REFUSES (outside the model's domain). 22// PROVEN 10/10 GREEN on the laptop build farm 2026-09-03 while the NAS build lane was storm-refused. 23// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 24import "nx_syscalls.nx" 25import "nx_gate_verdict.nx" 26import "nx_kubelka_lib.nx" 27 28const KG_SLOT: i64 = 8 29const KG_N: i64 = 9 30const KG_MICRO: i64 = 1000000 31const KG_RT_TOL_MICRO: i64 = 300 32const KG_SPAN_MIN_MICRO: i64 = 400000 33const KG_BAD_R_HIGH_MICRO: i64 = 1500000 34 35func kg_q(micro: i64) -> i64 { return fq_div(fq_from_int(micro), fq_from_int(KG_MICRO)) } 36func kg_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 37 38func main(argc: i64, argv: *i64) -> i64 { 39 let ctr: *i64 = gv_ctr() 40 gv_head("nx_kubelka gate -- two-flux reflectance, its closed-form inverse, and the chromophore mix that makes skin relightable" as *u8) 41 42 // ---- T1 exact at zero absorption ---- 43 let r0: i64 = km_r_from_ks(0) 44 gv_puts(" [T1] ks=0 -> r_micro=" as *u8); gv_num(fq_to_micro(r0)); gv_puts(" want=1000000\n" as *u8) 45 gv_check("zero-absorption-is-unit-reflectance-exactly" as *u8, (r0 == FQ_ONE) as i64, ctr) 46 47 // ---- the ladder ---- 48 let ksm: *i64 = sys_mmap(KG_N * KG_SLOT) as *i64 49 ksm[0] = 0 50 ksm[1] = 10000 51 ksm[2] = 50000 52 ksm[3] = 100000 53 ksm[4] = 250000 54 ksm[5] = 500000 55 ksm[6] = 1000000 56 ksm[7] = 2000000 57 ksm[8] = 4000000 58 let rr: *i64 = sys_mmap(KG_N * KG_SLOT) as *i64 59 var i: i64 = 0 60 gv_puts(" [ladder] ks_micro -> r_micro -> ks_back_micro\n" as *u8) 61 while i < KG_N { 62 let ks: i64 = kg_q(ksm[i]) 63 let r: i64 = km_r_from_ks(ks) 64 rr[i] = r 65 var backm: i64 = 0 - 1 66 if r > 0 { 67 let back: i64 = km_ks_from_r(r) 68 if back != KM_REFUSED { backm = fq_to_micro(back) } 69 } 70 gv_puts(" " as *u8); gv_num(ksm[i]) 71 gv_puts(" -> " as *u8); gv_num(fq_to_micro(r)) 72 gv_puts(" -> " as *u8); gv_num(backm) 73 gv_puts("\n" as *u8) 74 i = i + 1 75 } 76 77 // ---- T2 the ladder is non-degenerate ---- 78 let span: i64 = fq_to_micro(rr[0]) - fq_to_micro(rr[KG_N - 1]) 79 gv_puts(" [T2] reflectance_span_micro=" as *u8); gv_num(span); gv_puts(" floor=" as *u8); gv_num(KG_SPAN_MIN_MICRO); gv_puts("\n" as *u8) 80 gv_check("the-ladder-spans-real-range-so-monotonicity-and-bounds-cannot-pass-on-a-constant" as *u8, (span >= KG_SPAN_MIN_MICRO) as i64, ctr) 81 82 // ---- T3 round trip over EVERY rung ---- 83 var rt: i64 = 0 84 var j: i64 = 0 85 while j < KG_N { 86 let back: i64 = km_ks_from_r(rr[j]) 87 if back != KM_REFUSED { 88 if kg_abs(fq_to_micro(back) - ksm[j]) <= KG_RT_TOL_MICRO { rt = rt + 1 } 89 } 90 j = j + 1 91 } 92 gv_puts(" [T3] roundtrip_ok=" as *u8); gv_num(rt); gv_puts("/" as *u8); gv_num(KG_N); gv_puts("\n" as *u8) 93 gv_check("forward-and-inverse-round-trip-on-every-rung-of-the-ladder" as *u8, (rt == KG_N) as i64, ctr) 94 95 // ---- T4 strict monotonicity ---- 96 var mono: i64 = 1 97 var k: i64 = 1 98 while k < KG_N { 99 if rr[k] >= rr[k - 1] { mono = 0 } 100 k = k + 1 101 } 102 gv_check("reflectance-falls-strictly-as-absorption-rises" as *u8, mono, ctr) 103 104 // ---- T5 bounds ---- 105 var bnd: i64 = 1 106 var b: i64 = 0 107 while b < KG_N { 108 if rr[b] < 0 { bnd = 0 } 109 if rr[b] > FQ_ONE { bnd = 0 } 110 b = b + 1 111 } 112 gv_check("every-reflectance-on-the-ladder-lies-inside-zero-to-one" as *u8, bnd, ctr) 113 114 // ---- T6/T7 the physical checks. Coefficients are ARGUMENTS: this gate supplies plausible probe values 115 // to exercise the arithmetic, and asserts only the DIRECTION, which is true for any positive coefficients. 116 let kbase: i64 = kg_q(50000) 117 let kmel: i64 = kg_q(2000000) 118 let khem: i64 = kg_q(1500000) 119 let s: i64 = kg_q(1000000) 120 let rlow: i64 = km_r_of_mix(kbase, kmel, kg_q(50000), khem, kg_q(20000), s) 121 let rhigh: i64 = km_r_of_mix(kbase, kmel, kg_q(400000), khem, kg_q(20000), s) 122 gv_puts(" [T6] r(mel=0.05)=" as *u8); gv_num(fq_to_micro(rlow)) 123 gv_puts(" r(mel=0.40)=" as *u8); gv_num(fq_to_micro(rhigh)); gv_puts("\n" as *u8) 124 var t6: i64 = 0 125 if rlow != KM_REFUSED { if rhigh != KM_REFUSED { if rhigh < rlow { t6 = 1 } } } 126 gv_check("more-melanin-is-strictly-darker" as *u8, t6, ctr) 127 128 let hlow: i64 = km_r_of_mix(kbase, kmel, kg_q(50000), khem, kg_q(20000), s) 129 let hhigh: i64 = km_r_of_mix(kbase, kmel, kg_q(50000), khem, kg_q(300000), s) 130 gv_puts(" [T7] r(hem=0.02)=" as *u8); gv_num(fq_to_micro(hlow)) 131 gv_puts(" r(hem=0.30)=" as *u8); gv_num(fq_to_micro(hhigh)); gv_puts("\n" as *u8) 132 var t7: i64 = 0 133 if hlow != KM_REFUSED { if hhigh != KM_REFUSED { if hhigh < hlow { t7 = 1 } } } 134 gv_check("more-haemoglobin-is-strictly-darker" as *u8, t7, ctr) 135 136 // ---- T8..T10 neg-controls ---- 137 let bad_s: i64 = km_ks_mix(kbase, kmel, kg_q(50000), khem, kg_q(20000), 0) 138 gv_puts(" [T8] s=0 -> " as *u8); gv_num(bad_s); gv_puts(" want=" as *u8); gv_num(KM_REFUSED); gv_puts("\n" as *u8) 139 gv_check("neg-control-non-positive-scattering-refuses-instead-of-dividing-by-zero" as *u8, (bad_s == KM_REFUSED) as i64, ctr) 140 141 let bad_r0: i64 = km_ks_from_r(0) 142 gv_puts(" [T9] invert r=0 -> " as *u8); gv_num(bad_r0); gv_puts("\n" as *u8) 143 gv_check("neg-control-inverting-zero-reflectance-refuses-instead-of-returning-an-infinity" as *u8, (bad_r0 == KM_REFUSED) as i64, ctr) 144 145 let bad_rhi: i64 = km_ks_from_r(kg_q(KG_BAD_R_HIGH_MICRO)) 146 gv_puts(" [T10] invert r=1.5 -> " as *u8); gv_num(bad_rhi); gv_puts("\n" as *u8) 147 gv_check("neg-control-inverting-a-reflectance-above-one-refuses-as-outside-the-model-domain" as *u8, (bad_rhi == KM_REFUSED) as i64, ctr) 148 149 return gv_verdict("kubelka" as *u8, ctr, "two-flux reflectance proven by its own closed-form inverse over a non-degenerate ladder, with the melanin and haemoglobin directions and three refusals" as *u8) 150}