code wiki / _hdl_build / nx_vmotion_gate.nx
nx_vmotion_gate.nx source
↩ module page · 91 lines · 5288 B
1// nx_vmotion_gate.nx -- proves + MEASURES sovereign motion compensation (nx_vmotion), the rung that beats plain
2// tile-delta the way VP8/H.264 do. Native nx_cc->nxasm, no node.
3// 1) PAN exceed: a frame shifted by (3,2) -> tile-delta sees the block as fully changed (huge SAD), motion
4// search finds the shift (MV) with ~0 residual -> measured: motion-comp << tile-delta on motion
5// 2) MV correctness: the found vector equals the true shift (negated)
6// 3) lossless reconstruct: predicted-at-MV + residual == the cur block
7// 4) static block: cur==prev -> MV=(0,0), SAD=0
8// 5) honest limit (neg): a noisy block with no match -> SAD stays high (motion comp isn't magic -> intra fallback)
9// license_tier: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_vmotion.nx"
12
13func g_puts(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
14func g_pn(v: i64) -> i64 {
15 let b: *u8 = sys_mmap(28); var x: i64 = v
16 if x < 0 { b[0]=45; sys_write(1,b,1); x = 0 - x }
17 if x == 0 { b[0]=48; sys_write(1,b,1); return 0 }
18 var d: i64=0; var y: i64=x
19 while y>0 { d=d+1; y=y/10 }
20 var i: i64=d-1; y=x
21 while i>=0 { b[i]=(48+(y%10)) as u8; y=y/10; i=i-1 }
22 sys_write(1,b,d); return 0
23}
24func g_check(name: *u8, cond: i64) -> i64 {
25 if cond==1 { g_puts(" PASS " as *u8) } else { g_puts(" FAIL " as *u8) }
26 g_puts(name); g_puts("\n" as *u8); return cond
27}
28func tex(x: i64, y: i64) -> i64 { return (x*7 + y*13 + x*y*3) & 0xff } // deterministic textured content
29func block_eq(a: *u8, b: *u8, W: i64, bx: i64, by: i64, T: i64) -> i64 {
30 let cx: i64 = bx*T; let cy: i64 = by*T
31 var yy: i64=0; while yy<T { var xx: i64=0; while xx<T { if a[(cy+yy)*W+(cx+xx)] != b[(cy+yy)*W+(cx+xx)] { return 0 } xx=xx+1 } yy=yy+1 }
32 return 1
33}
34
35func main() -> i64 {
36 let vmscr3: *i64 = sys_mmap(32) as *i64 // vm_search scratch (2026-07-29: hoisted ONE alloc; the per-call sys_mmap inside vm_search was the wasm 0-stub + native map-leak class)
37 g_puts("nx_vmotion gate (sovereign motion compensation -- beats tile-delta on motion, MEASURED)\n" as *u8)
38 var pass: i64 = 0; var total: i64 = 0
39
40 let W: i64 = 160; let H: i64 = 96; let T: i64 = 16; let R: i64 = 8
41 let A: *u8 = sys_mmap(W*H) // previous frame
42 let B: *u8 = sys_mmap(W*H) // current frame = A panned by (3,2)
43 let dst: *u8 = sys_mmap(W*H)
44 let mv: *i64 = sys_mmap(2*8) as *i64
45 let res: *i64 = sys_mmap(T*T*8) as *i64
46
47 var y: i64 = 0
48 while y < H { var x: i64 = 0; while x < W { A[y*W+x] = tex(x,y) as u8; x=x+1 } y=y+1 }
49 // B = A shifted right 3, down 2 (a camera pan)
50 y = 0
51 while y < H { var x: i64 = 0
52 while x < W {
53 if y >= 2 { if x >= 3 { B[y*W+x] = A[(y-2)*W + (x-3)] } else { B[y*W+x] = tex(x,y) as u8 } } else { B[y*W+x] = tex(x,y) as u8 }
54 x=x+1
55 } y=y+1 }
56
57 let BX: i64 = 5; let BY: i64 = 3 // a center block, clear of the edges
58
59 // 1) PAN exceed: tile-delta SAD (zero MV) vs motion-comp SAD
60 let sad_tile: i64 = vm_sad_zero(B, A, W, BX, BY, T)
61 let sad_mc: i64 = vm_search(B, A, W, H, BX, BY, T, R, mv, vmscr3)
62 g_puts(" [measure] panned block: tile-delta SAD=" as *u8); g_pn(sad_tile); g_puts(" motion-comp SAD=" as *u8); g_pn(sad_mc)
63 g_puts(" MV=(" as *u8); g_pn(mv[0]); g_puts("," as *u8); g_pn(mv[1]); g_puts(")\n" as *u8)
64 pass = pass + g_check("PAN: motion-comp residual << tile-delta change (the H.264 win)" as *u8, (sad_mc * 20 < sad_tile) & (sad_mc <= 4)); total=total+1
65
66 // 2) MV correctness (true shift was +3,+2 -> best match is at -3,-2)
67 pass = pass + g_check("motion vector equals the true shift (negated)" as *u8, (mv[0] == (0-3)) & (mv[1] == (0-2))); total=total+1
68
69 // 3) lossless reconstruct: predicted-at-MV + residual == cur block
70 vm_residual(B, A, res, W, BX, BY, T, mv)
71 var i: i64 = 0
72 while i < W*H { dst[i] = 0 as u8; i = i + 1 }
73 vm_reconstruct(dst, A, res, W, BX, BY, T, mv)
74 pass = pass + g_check("reconstruct exact: predicted@MV + residual == cur block" as *u8, block_eq(dst, B, W, BX, BY, T)); total=total+1
75
76 // 4) static block: A vs A -> no motion
77 let sad_static: i64 = vm_search(A, A, W, H, BX, BY, T, R, mv, vmscr3)
78 pass = pass + g_check("static block: MV=(0,0), SAD=0" as *u8, (sad_static == 0) & (mv[0]==0) & (mv[1]==0)); total=total+1
79
80 // 5) honest limit (neg): a noisy block with no match -> SAD stays high (fall back to intra/tile)
81 let NX: i64 = 8; let NY: i64 = 1
82 var ny: i64 = 0
83 while ny < T { var nx: i64 = 0; while nx < T { B[(NY*T+ny)*W + (NX*T+nx)] = ((nx*131 + ny*197 + 99) & 0xff) as u8; nx=nx+1 } ny=ny+1 }
84 let sad_noise: i64 = vm_search(B, A, W, H, NX, NY, T, R, mv, vmscr3)
85 g_puts(" [measure] unmatched noisy block: best SAD=" as *u8); g_pn(sad_noise); g_puts(" (stays high -> intra fallback, not faked)\n" as *u8)
86 pass = pass + g_check("honest: no-match block keeps high residual (motion comp not magic, neg)" as *u8, sad_noise > 200); total=total+1
87
88 g_puts("---- vmotion gate: passed " as *u8); g_pn(pass); g_puts(" / " as *u8); g_pn(total); g_puts(" ----\n" as *u8)
89 if pass == total { g_puts("verdict=GREEN\n" as *u8); sys_exit(0); return 0 }
90 g_puts("verdict=RED\n" as *u8); sys_exit(1); return 1
91}