nx_fieldfit_gate.nx source
↩ module page · 193 lines · 10255 B
1// nx_fieldfit_gate.nx -- THE FIELD-FIT MACHINERY (nx_fieldfit_lib) ON A SYNTHETIC ORACLE WITH A KNOWN ANSWER
2// (anatomy AN17, 2026-09-19). The oracle is a point sphere of radius FG_R centred (FG_CX, FG_CY, FG_CZ), sampled on a
3// 10-degree lattice; the field is a sphere whose centre and radius are stations 0..3 of a five-station vector, with
4// station 4 a DECOY the field never reads and the live mask retires. Started from a wrong vector, the descent must
5// recover the centre and the radius to FG_TOL mm, must leave the decoy untouched, and must not move from the true
6// vector (a move accepted at the optimum is a broken accept rule). The fit file's prefix contract and the spatial
7// hash are held to exact answers. NEG-CONTROL: the two-sided objective must charge a shrunken sphere MORE than the
8// true one (a one-sided objective is gamed by deleting geometry; this is the tooth that cannot pass on one side).
9// license_tier: ORIGINAL. No hw writes (Rule 26).
10import "nx_syscalls.nx"
11import "nx_gate_verdict.nx"
12import "nx_sdfprim_lib.nx"
13import "nx_fieldfit_lib.nx"
14
15const FG_NP: i64 = 5
16const FG_NREG: i64 = 8 // the octants
17const FG_CAP: i64 = 4096
18const FG_EXT: i64 = 60 // the sphere (centre 8, radius 40) fits in +/- 60
19const FG_DIM: i64 = 12
20const FG_LAT: i64 = 6
21const FG_R: i64 = 40
22const FG_CX: i64 = 5
23const FG_CY: i64 = 0-3
24const FG_CZ: i64 = 8
25const FG_DECOY: i64 = 777
26const FG_WRONG_DX: i64 = 12 // the wrong start: centre x shifted, radius shrunk
27const FG_WRONG_R: i64 = 25
28const FG_SHRUNK_R: i64 = 20 // the neg-control's deleted geometry
29const FG_PASSES: i64 = 6
30const FG_STEP0: i64 = 8
31const FG_TOL: i64 = 2 // mm: the reverse lattice at 6 mm bounds the placement
32const FG_STEP_DEG: i64 = 10
33const FG_FILE: *u8 = "/tmp/nx_fieldfit_gate.fit"
34const FG_FILE3: *u8 = "/tmp/nx_fieldfit_gate.fit3"
35const FG_FILE2: *u8 = "/tmp/nx_fieldfit_gate.fit2"
36const FG_ABSENT: *u8 = "/tmp/nx_fieldfit_gate.absent"
37const FG_MODE644: i64 = 420
38
39func fg_field(px: i64, py: i64, pz: i64, a: i64, b: i64, P: *i64) -> i64 {
40 let dx: i64 = px - P[0]
41 let dy: i64 = py - P[1]
42 let dz: i64 = pz - P[2]
43 return (sp_isqrt(dx*dx + dy*dy + dz*dz) - P[3])*SP_FQ
44}
45func fg_region(x: i64, y: i64, z: i64) -> i64 {
46 var r: i64 = 0
47 if x >= 0 { r = r + 1 }
48 if y >= 0 { r = r + 2 }
49 if z >= 0 { r = r + 4 }
50 return r
51}
52func fg_live(k: i64) -> i64 { if k == 4 { return 0 } return 1 }
53const FG_EXTRA: i64 = 900
54func fg_extra(P: *i64) -> i64 { return FG_EXTRA }
55func fg_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
56// the oracle: points on the sphere at every 10 degrees of polar and azimuthal angle
57func fg_oracle(c: *FfCtx) -> i64 {
58 var n: i64 = 0
59 var th: i64 = 0
60 while th <= 180 {
61 var ph: i64 = 0
62 while ph < 360 {
63 let s: i64 = sp_isin(th)
64 let cth: i64 = sp_icos(th)
65 var cph: i64 = sp_icos(ph)
66 var sph: i64 = sp_isin(ph)
67 if ph > 180 { cph = 0 - sp_icos(ph - 180); sph = 0 - sp_isin(ph - 180) }
68 c.RX[n] = FG_CX + FG_R*s/SP_PERMILLE*cph/SP_PERMILLE
69 c.RY[n] = FG_CY + FG_R*s/SP_PERMILLE*sph/SP_PERMILLE
70 c.RZ[n] = FG_CZ + FG_R*cth/SP_PERMILLE
71 n = n + 1
72 ph = ph + FG_STEP_DEG
73 }
74 th = th + FG_STEP_DEG
75 }
76 c.n = n
77 return n
78}
79func fg_write(path: *u8, s: *u8) -> i64 {
80 var n: i64 = 0
81 while s[n] != (0 as u8) { n = n + 1 }
82 let fd: i64 = sys_openat_wr(path, FG_MODE644)
83 if fd < 0 { return 0 - 1 }
84 sys_write(fd, s, n)
85 sys_close(fd)
86 return n
87}
88
89func main(argc: i64, argv: *i64) -> i64 {
90 gv_head("nx_fieldfit_gate: the field-fit machinery recovers a known sphere from a wrong start, honours the live mask, and keeps the fit-file prefix contract" as *u8)
91 let ctr: *i64 = gv_ctr()
92 let C: *FfCtx = ff_ctx_new(FG_NP, FG_NREG, FG_CAP, FG_EXT, FG_DIM, FG_LAT, SP_FQ)
93 C.field = fg_field
94 C.region = fg_region
95 C.live = fg_live
96 let n: i64 = fg_oracle(C)
97 gv_check("oracle-sampled-a-nonempty-sphere" as *u8, (n > 100) as i64, ctr)
98 ff_bin(C)
99 ff_regions(C)
100 // every octant is populated: the balance has eight regions to balance
101 var reg_ok: i64 = 1
102 var r: i64 = 0
103 while r < FG_NREG {
104 var seen: i64 = 0
105 var i: i64 = 0
106 while i < n { if C.RG[i] == r { seen = 1 } i = i + 1 }
107 if seen == 0 { reg_ok = 0 }
108 r = r + 1
109 }
110 gv_check("every-region-holds-oracle-samples" as *u8, reg_ok, ctr)
111 // ---- the spatial hash ----
112 gv_check_eq("nearest-oracle-sample-to-a-sample-is-itself" as *u8, ff_near(C, C.RX[0], C.RY[0], C.RZ[0]), 0, ctr)
113 gv_check_eq("nearest-sample-7mm-radially-outside-the-pole-reads-7" as *u8, ff_near(C, FG_CX, FG_CY, FG_CZ + FG_R + 7), 7, ctr)
114 gv_check_eq("live-count-excludes-the-decoy" as *u8, ff_live_count(C), FG_NP - 1, ctr)
115 // ---- the objective ----
116 let T: *i64 = sys_mmap(FG_NP*FF_I64) as *i64
117 T[0] = FG_CX; T[1] = FG_CY; T[2] = FG_CZ; T[3] = FG_R; T[4] = FG_DECOY
118 let s_true: i64 = ff_score2(C, T)
119 let W: *i64 = sys_mmap(FG_NP*FF_I64) as *i64
120 W[0] = FG_CX; W[1] = FG_CY; W[2] = FG_CZ; W[3] = FG_SHRUNK_R; W[4] = FG_DECOY
121 let s_shrunk: i64 = ff_score2(C, W)
122 gv_check("true-vector-scores-under-one-lattice-step" as *u8, (s_true < FG_LAT*FF_CENTI) as i64, ctr)
123 gv_bite("neg-control-a-shrunken-sphere-is-charged-more-than-the-true-one" as *u8, (s_shrunk > s_true) as i64, (s_true > s_true) as i64, ctr)
124 // the forward side alone reads the shrink as its whole depth: the two-sided mean must exceed the forward side of the truth
125 // the fixture's own radius, MEASURED: integer point generation lands the samples a few mm inside the nominal sphere,
126 // so the shrink is read against the mean radius the points actually have, never against the number typed above
127 var rsum: i64 = 0
128 var ri: i64 = 0
129 while ri < n {
130 let ddx: i64 = C.RX[ri] - FG_CX
131 let ddy: i64 = C.RY[ri] - FG_CY
132 let ddz: i64 = C.RZ[ri] - FG_CZ
133 rsum = rsum + sp_isqrt(ddx*ddx + ddy*ddy + ddz*ddz)
134 ri = ri + 1
135 }
136 let mean_r: i64 = rsum / n
137 let fwd_shrunk: i64 = ff_score_fwd(C, W)
138 gv_check_near("shrunken-forward-term-reads-the-measured-shrink-in-centi-mm" as *u8, fwd_shrunk, (mean_r - FG_SHRUNK_R)*FF_CENTI, FF_CENTI, ctr)
139 // ---- the descent from a wrong start ----
140 let P: *i64 = sys_mmap(FG_NP*FF_I64) as *i64
141 P[0] = FG_CX + FG_WRONG_DX; P[1] = FG_CY; P[2] = FG_CZ; P[3] = FG_WRONG_R; P[4] = FG_DECOY
142 let s_start: i64 = ff_score2(C, P)
143 let best: i64 = ff_descend(C, P, FG_PASSES, FG_STEP0, 0)
144 gv_check("descent-lowered-the-measured-objective" as *u8, (best < s_start) as i64, ctr)
145 gv_check_near("descent-recovered-the-centre-x" as *u8, P[0], FG_CX, FG_TOL, ctr)
146 gv_check_near("descent-recovered-the-centre-y" as *u8, P[1], FG_CY, FG_TOL, ctr)
147 gv_check_near("descent-recovered-the-centre-z" as *u8, P[2], FG_CZ, FG_TOL, ctr)
148 gv_check_near("descent-recovered-the-radius" as *u8, P[3], FG_R, FG_TOL, ctr)
149 gv_check_eq("descent-left-the-retired-decoy-untouched" as *u8, P[4], FG_DECOY, ctr)
150 gv_check_eq("best-is-the-objective-of-the-vector-returned" as *u8, ff_score2(C, P) - best, 0, ctr)
151 // ---- neg-control: from the truth, nothing moves ----
152 let Q: *i64 = sys_mmap(FG_NP*FF_I64) as *i64
153 Q[0] = FG_CX; Q[1] = FG_CY; Q[2] = FG_CZ; Q[3] = FG_R; Q[4] = FG_DECOY
154 let b2: i64 = ff_descend(C, Q, 2, FG_STEP0, 0)
155 gv_check("neg-control-descent-from-the-truth-stays-within-a-millimetre" as *u8, ((fg_abs(Q[0]-FG_CX) <= 1) * (fg_abs(Q[3]-FG_R) <= 1)) as i64, ctr)
156 gv_check("neg-control-descent-from-the-truth-does-not-raise-the-objective" as *u8, (b2 <= s_true) as i64, ctr)
157 // ---- the optional third term: a constant extra of 900 centi folds in as the three-way mean ----
158 C.extra = fg_extra
159 C.has_extra = 1
160 let s3: i64 = ff_score2(C, T)
161 let f3: i64 = ff_score_fwd(C, T)
162 let r3: i64 = ff_score_rev(C, T)
163 gv_check_eq("extra-term-folds-in-as-the-three-way-mean" as *u8, s3, (f3 + r3 + FG_EXTRA)/3, ctr)
164 C.has_extra = 0
165 gv_check_eq("extra-term-off-restores-the-two-way-mean" as *u8, ff_score2(C, T), (f3 + r3)/2, ctr)
166 // ---- the fit file ----
167 gv_check_eq("absent-fit-file-applies-nothing" as *u8, ff_load_prefix(FG_ABSENT, Q, FG_NP, 3), 0, ctr)
168 let wrote: i64 = ff_save(FG_FILE, P, FG_NP)
169 gv_check("save-wrote-bytes" as *u8, (wrote > 0) as i64, ctr)
170 let R: *i64 = sys_mmap(FG_NP*FF_I64) as *i64
171 R[0] = 1; R[1] = 2; R[2] = 3; R[3] = 4; R[4] = 5
172 gv_check_eq("save-then-load-applies-the-whole-vector" as *u8, ff_load_prefix(FG_FILE, R, FG_NP, 3), FG_NP, ctr)
173 gv_check_eq("save-then-load-round-trips-every-station" as *u8, (R[0]-P[0]) + (R[1]-P[1]) + (R[2]-P[2]) + (R[3]-P[3]) + (R[4]-P[4]), 0, ctr)
174 fg_write(FG_FILE3, "11\n-22\n33\n" as *u8)
175 R[0] = 0; R[1] = 0; R[2] = 0; R[3] = 4; R[4] = 5
176 gv_check_eq("a-three-int-file-applies-a-prefix-of-three" as *u8, ff_load_prefix(FG_FILE3, R, FG_NP, 3), 3, ctr)
177 gv_check_eq("the-prefix-lands-with-its-sign" as *u8, R[1], 0-22, ctr)
178 gv_check_eq("stations-past-the-prefix-keep-their-defaults" as *u8, R[3] + R[4], 9, ctr)
179 fg_write(FG_FILE2, "11\n22\n" as *u8)
180 R[0] = 0; R[1] = 0
181 gv_check_eq("a-file-shorter-than-minlen-applies-nothing" as *u8, ff_load_prefix(FG_FILE2, R, FG_NP, 3), 0, ctr)
182 gv_check_eq("a-refused-short-file-leaves-the-vector-unchanged" as *u8, R[0] + R[1], 0, ctr)
183 gv_values_head()
184 gv_kv("oracle_samples" as *u8, n)
185 gv_kv("score_true_centi" as *u8, s_true)
186 gv_kv("score_shrunk_centi" as *u8, s_shrunk)
187 gv_kv("score_shrunk_fwd_centi" as *u8, fwd_shrunk)
188 gv_kv("fixture_mean_radius_mm" as *u8, mean_r)
189 gv_kv("score_start_centi" as *u8, s_start)
190 gv_kv("score_best_centi" as *u8, best)
191 gv_kv("recovered_cx" as *u8, P[0]); gv_kv("recovered_cy" as *u8, P[1]); gv_kv("recovered_cz" as *u8, P[2]); gv_kv("recovered_r" as *u8, P[3])
192 return gv_verdict("nx_fieldfit_gate" as *u8, ctr, "one optimiser and one two-sided region-balanced objective for every anatomy field, proven on a sphere with a known answer" as *u8)
193}