code wiki / _hdl_build / nx_interp_gate.nx

nx_interp_gate.nx source

↩ module page · 111 lines · 5899 B

1// nx_interp_gate.nx -- proves + MEASURES the sovereign snapshot interpolation buffer (nx_interp): 2// under packet LOSS + REORDERING, render-in-the-past interpolation reconstructs the peer's true path 3// (loss becomes invisible) while naive snap-to-latest (zero-order hold) staircases. This is what keeps 4// the bad-mobile-network player smooth. 5// 1) reorder-safe + correct: out-of-order pushes -> time-sorted history; interp ~= truth (loss invisible) 6// 2) EXCEED vs naive (neg-control = zero-order hold): interp max error << naive max error (measured) 7// 3) SMOOTHNESS: interp max per-step jump < naive max per-step jump (measured) 8// 4) yaw shortest-arc: 350deg -> 10deg interpolates through 0 (not the long way) 9// 5) no-data (neg): empty history -> sample returns 0 (no fabricated pose) 10// 6) clamp: before-first -> status 2, at/after-last -> status 3 (hold; extrapolate = NET-R2) 11// Built nx_cc_sovereign -> nxasm_x86 (no gcc, no .sh). license_tier: ORIGINAL 12import "nx_syscalls.nx" 13import "nx_gate_emit_lib.nx" 14import "nx_interp.nx" 15 16func g_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v } 17// build a snapshot with x=val (other fields fixed) for the path proof 18func mkf(f: *i64, x: i64) -> i64 { var i: i64=0; while i<10 { f[i]=0; i=i+1 } f[0]=x; return 0 } 19// naive zero-order hold: value of the newest RECEIVED sample with time <= rt; val(t)=t/2 20func naive_x(times: *i64, nr: i64, rt: i64) -> i64 { 21 var best: i64 = times[0] 22 var i: i64 = 0 23 while i < nr { if times[i] <= rt { best = times[i] } i = i + 1 } 24 return best / 2 25} 26 27func main() -> i64 { 28 g_puts("nx_interp gate (sovereign snapshot interpolation: smooth under loss+jitter+reorder)\n" as *u8) 29 var pass: i64 = 0; var total: i64 = 0 30 31 let K: i64 = 16 32 let hist: *i64 = sys_mmap((1 + K*IP_STRIDE) * 8) as *i64 33 ip_init(hist) 34 let f: *i64 = sys_mmap(10*8) as *i64 35 let out: *i64 = sys_mmap(10*8) as *i64 36 37 // ground truth path val(t)=t/2 sampled at 0,100,...,1000; DROP 300/600/900 (loss); push 500 BEFORE 400 (reorder) 38 let times: *i64 = sys_mmap(8*8) as *i64 39 times[0]=0; times[1]=100; times[2]=200; times[3]=400; times[4]=500; times[5]=700; times[6]=800; times[7]=1000 40 // push in a deliberately out-of-order sequence 41 mkf(f, 0); ip_push(hist, K, 0, f) 42 mkf(f, 50); ip_push(hist, K, 100, f) 43 mkf(f, 100); ip_push(hist, K, 200, f) 44 mkf(f, 250); ip_push(hist, K, 500, f) // 500 pushed BEFORE 400 (reorder) 45 mkf(f, 200); ip_push(hist, K, 400, f) 46 mkf(f, 350); ip_push(hist, K, 700, f) 47 mkf(f, 400); ip_push(hist, K, 800, f) 48 mkf(f, 500); ip_push(hist, K, 1000, f) 49 50 // 1) reorder-safe (sorted) + correct (interp ~= truth despite the 3 drops) 51 var sorted: i64 = 1 52 var i: i64 = 1 53 while i < ip_count(hist) { if ip_time(hist, i-1) > ip_time(hist, i) { sorted = 0 } i = i + 1 } 54 var ei_max: i64 = 0; var en_max: i64 = 0 55 var si_max: i64 = 0; var sn_max: i64 = 0 56 var prev_i: i64 = 0 - 1; var prev_n: i64 = 0 - 1 57 var rt: i64 = 150 58 while rt <= 850 { 59 ip_sample(hist, rt, out) 60 let ix: i64 = out[0] 61 let truev: i64 = rt / 2 62 let ei: i64 = g_abs(ix - truev); if ei > ei_max { ei_max = ei } 63 let nxv: i64 = naive_x(times, 8, rt) 64 let en: i64 = g_abs(nxv - truev); if en > en_max { en_max = en } 65 if prev_i >= 0 { let s: i64 = g_abs(ix - prev_i); if s > si_max { si_max = s } } 66 if prev_n >= 0 { let s: i64 = g_abs(nxv - prev_n); if s > sn_max { sn_max = s } } 67 prev_i = ix; prev_n = nxv 68 rt = rt + 50 69 } 70 g_puts(" [measure] over a lossy(3 drops)+reordered stream: interp_max_err=" as *u8); g_pn(ei_max) 71 g_puts(" naive_max_err=" as *u8); g_pn(en_max); g_puts("\n" as *u8) 72 g_puts(" [measure] per-step jump: interp_max=" as *u8); g_pn(si_max); g_puts(" naive_max=" as *u8); g_pn(sn_max); g_puts("\n" as *u8) 73 var r1: i64 = 1 74 if sorted != 1 { r1 = 0 } 75 if ei_max > 2 { r1 = 0 } // interp reconstructs truth within 2 voxels (loss invisible) 76 pass = pass + g_check("reorder-safe + interp reconstructs truth under loss" as *u8, r1); total=total+1 77 78 // 2) EXCEED vs naive ZOH (measured) 79 pass = pass + g_check("interp_max_err < naive_max_err (smoother than snap-to-latest)" as *u8, ei_max < en_max); total=total+1 80 81 // 3) SMOOTHNESS (measured): interp never jumps as hard as naive 82 pass = pass + g_check("interp per-step jump < naive per-step jump" as *u8, si_max < sn_max); total=total+1 83 84 // 4) yaw shortest-arc 85 let hy: *i64 = sys_mmap((1 + 4*IP_STRIDE) * 8) as *i64 86 ip_init(hy) 87 mkf(f, 0); f[3] = 350; ip_push(hy, 4, 0, f) 88 mkf(f, 0); f[3] = 10; ip_push(hy, 4, 100, f) 89 ip_sample(hy, 50, out) 90 let yv: i64 = out[3] 91 var r4: i64 = 0 92 if yv <= 5 { r4 = 1 } 93 if yv >= 355 { r4 = 1 } // ~0deg (== 360) the short way, NOT ~180 94 g_puts(" [measure] yaw lerp 350->10 at half = " as *u8); g_pn(yv); g_puts(" deg (expect ~0/360, not ~180)\n" as *u8) 95 pass = pass + g_check("yaw interpolates shortest-arc through 0" as *u8, r4); total=total+1 96 97 // 5) no-data neg-control 98 let he: *i64 = sys_mmap((1 + 4*IP_STRIDE) * 8) as *i64 99 ip_init(he) 100 let st0: i64 = ip_sample(he, 500, out) 101 pass = pass + g_check("empty history -> no fabricated pose (status 0)" as *u8, st0 == 0); total=total+1 102 103 // 6) clamp before-first / at-after-last 104 let sbefore: i64 = ip_sample(hist, 0 - 50, out) 105 let safter: i64 = ip_sample(hist, 5000, out) 106 pass = pass + g_check("clamp: before-first=2, after-last=3" as *u8, (sbefore == 2) & (safter == 3)); total=total+1 107 108 g_puts("---- interp gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8) 109 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 } 110 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1 111}