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}