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}