code wiki / _hdl_build / nx_interp_ex_gate.nx

nx_interp_ex_gate.nx source

↩ module page · 81 lines · 4546 B

1// nx_interp_ex_gate.nx -- proves + MEASURES sovereign dead-reckoning extrapolation (nx_interp ip_sample_ex): 2// during a LOSS BURST (rt runs past the newest snapshot) the peer keeps MOVING from estimated velocity 3// instead of freezing, capped at a safe horizon so long loss holds (bounded) rather than diverging. 4// 1) extrapolation tracks truth during a loss burst (measured err ~0 on steady motion) 5// 2) EXCEED vs hold (neg-control = NET-R1 freeze): extrap_max_err << hold_max_err (measured) 6// 3) horizon cap (neg): beyond max_extrap_ms it HOLDS (status 3, bounded) -- no runaway divergence 7// 4) interior unchanged: ip_sample_ex delegates to ip_sample for in-bracket rt (regression) 8// 5) no-data (neg): empty history -> 0 9// Built nx_cc_sovereign -> nxasm_x86 (no gcc, no .sh). license_tier: ORIGINAL 10import "nx_syscalls.nx" 11import "nx_gate_emit_lib.nx" 12import "nx_interp.nx" 13import "nx_gate_verdict.nx" 14 15func g_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 16func mkf(f: *i64, x: i64) -> i64 { var i: i64=0; while i<10 { f[i]=0; i=i+1 } f[0]=x; return 0 } 17 18func main() -> i64 { 19 g_puts("nx_interp_ex gate (sovereign dead-reckoning: keep moving during loss, no freeze, bounded)\n" as *u8) 20 var pass: i64 = 0; var total: i64 = 0 21 22 let K: i64 = 16 23 let hist: *i64 = sys_mmap((1 + K*IP_STRIDE) * 8) as *i64 24 ip_init(hist) 25 let f: *i64 = sys_mmap(10*8) as *i64 26 let out: *i64 = sys_mmap(10*8) as *i64 27 28 // steady motion val(t)=t/2, samples 0..500 received; then 600/700/800 LOST (newest = 500) 29 var t: i64 = 0 30 while t <= 500 { mkf(f, t/2); ip_push(hist, K, t, f); t = t + 100 } 31 let MAXEX: i64 = 400 32 33 // 1)+2) during the loss burst rt=600..800: extrapolate vs hold 34 var ex_max: i64 = 0; var hold_max: i64 = 0 35 var rt: i64 = 600 36 while rt <= 800 { 37 ip_sample_ex(hist, rt, MAXEX, out) 38 let ex: i64 = g_abs(out[0] - rt/2); if ex > ex_max { ex_max = ex } 39 ip_sample(hist, rt, out) // NET-R1 (holds last = freeze) 40 let hd: i64 = g_abs(out[0] - rt/2); if hd > hold_max { hold_max = hd } 41 rt = rt + 50 42 } 43 g_puts(" [measure] loss burst rt=600..800: extrap_max_err=" as *u8); g_pn(ex_max) 44 g_puts(" hold(freeze)_max_err=" as *u8); g_pn(hold_max); g_puts("\n" as *u8) 45 pass = pass + g_check("extrapolation tracks truth during loss burst (err ~0)" as *u8, ex_max <= 2); total=total+1 46 pass = pass + g_check("extrap_max_err < hold/freeze_max_err (no freeze)" as *u8, ex_max < hold_max); total=total+1 47 48 // 3) horizon cap (neg): far beyond newest -> HOLD bounded (status 3), not a runaway extrapolation 49 let st_far: i64 = ip_sample_ex(hist, 500 + MAXEX + 300, MAXEX, out) 50 var r3: i64 = 1 51 if st_far != 3 { r3 = 0 } // held, not extrapolated 52 if out[0] != 250 { r3 = 0 } // == last sample value (bounded), not 250+big 53 g_puts(" [measure] beyond horizon (dt=700>cap400): status=" as *u8); g_pn(st_far); g_puts(" held x=" as *u8); g_pn(out[0]); g_puts("\n" as *u8) 54 pass = pass + g_check("horizon cap: long loss HOLDS bounded (no runaway)" as *u8, r3); total=total+1 55 56 // 4) interior unchanged (regression): ex delegates to interp for in-bracket rt 57 let stex: i64 = ip_sample_ex(hist, 250, MAXEX, out) 58 let ix: i64 = out[0] 59 let sti: i64 = ip_sample(hist, 250, out) 60 var r4: i64 = 1 61 if stex != 1 { r4 = 0 } 62 if sti != 1 { r4 = 0 } 63 if ix != out[0] { r4 = 0 } // same value as plain interp 64 pass = pass + g_check("interior rt unchanged (delegates to interp)" as *u8, r4); total=total+1 65 66 // 5) no-data neg 67 let he: *i64 = sys_mmap((1 + 4*IP_STRIDE) * 8) as *i64 68 ip_init(he) 69 pass = pass + g_check("empty history -> 0 (no fabrication)" as *u8, ip_sample_ex(he, 999, MAXEX, out) == 0); total=total+1 70 71 g_puts("---- interp_ex gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 72 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check 73 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled 74 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify. 75 let ctr__dry: *i64 = gv_ctr() 76 ctr__dry[0] = pass 77 ctr__dry[1] = total 78 let rc__dry: i64 = gv_verdict("INTERP-EX-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8) 79 sys_exit(rc__dry) 80 return rc__dry 81}