nx_f32_upsample_bilinear_gate.nx source
↩ module page · 48 lines · 2585 B
1// nx_f32_upsample_bilinear_gate.nx -- exact proof of bilinear upsample (align_corners=False) vs hand-computed
2// PyTorch values. Input 2x2 = [0,40,80,120], scale 2 -> 4x4. expect_exit: 0
3import "nx_syscalls.nx"
4import "nx_f32_cvt.nx"
5import "nx_f32_upsample_bilinear.nx"
6
7func gp(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return sys_write(1, s, n) }
8func gn(v: i64) -> i64 {
9 let bb: *u8 = sys_mmap(28); var m: i64 = v
10 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
11 let t: *u8 = sys_mmap(28); var k: i64 = 0
12 if m == 0 { t[0] = 48 as u8; k = 1 }
13 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
14 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
15 return sys_write(1, bb, k)
16}
17
18func main(argc: i64, argv: *i64) -> i64 {
19 var pass: i64 = 0
20 let inp: *i64 = sys_mmap(8 * 4) as *i64
21 let out: *i64 = sys_mmap(8 * 32) as *i64
22 // 2x2 input a=0 b=40 c=80 d=120
23 inp[0]=nx_i32_to_f32(0); inp[1]=nx_i32_to_f32(40); inp[2]=nx_i32_to_f32(80); inp[3]=nx_i32_to_f32(120)
24
25 var r1: i64 = nx_f32_upsample_bilinear(inp, 1, 1, 2, 2, 2, out)
26 // 4x4 out. U1 corner out[0,0]=idx0 clamps to a=0. U2 out[1,1]=idx5=(9a+3b+3c+d)/16=30.
27 // U3 out[1,2]=idx6=(3a+9b+c+3d)/16=50. U4 corner out[3,3]=idx15 clamps to d=120.
28 if out[0]==nx_i32_to_f32(0) { pass = pass + 1; gp("U1 corner (0,0)=0 (clamped) OK\n" as *u8) }
29 if out[0]!=nx_i32_to_f32(0) { gp("U1 FAIL o0=" as *u8); gn(out[0]); gp("\n" as *u8) }
30
31 if out[5]==nx_i32_to_f32(30) { pass = pass + 1; gp("U2 (1,1)=(9a+3b+3c+d)/16=30 OK\n" as *u8) }
32 if out[5]!=nx_i32_to_f32(30) { gp("U2 FAIL o5=" as *u8); gn(out[5]); gp(" want30=" as *u8); gn(nx_i32_to_f32(30)); gp("\n" as *u8) }
33
34 if out[6]==nx_i32_to_f32(50) { pass = pass + 1; gp("U3 (1,2)=(3a+9b+c+3d)/16=50 OK\n" as *u8) }
35 if out[6]!=nx_i32_to_f32(50) { gp("U3 FAIL o6=" as *u8); gn(out[6]); gp("\n" as *u8) }
36
37 if out[15]==nx_i32_to_f32(120) { pass = pass + 1; gp("U4 corner (3,3)=120 (clamped) OK\n" as *u8) }
38 if out[15]!=nx_i32_to_f32(120) { gp("U4 FAIL o15=" as *u8); gn(out[15]); gp("\n" as *u8) }
39
40 var r2: i64 = nx_f32_upsample_bilinear(inp, 1, 1, 2, 2, 0, out)
41 if r1==0 { if r2==4 { pass = pass + 1; gp("U5 rc ok (valid=0, scale0=ERR) OK\n" as *u8) } }
42 if r2 != 4 { gp("U5 FAIL r2=" as *u8); gn(r2); gp("\n" as *u8) }
43
44 gp("BILINEAR-GATE pass=" as *u8); gn(pass); gp("/5\n" as *u8)
45 if pass == 5 { gp("BILINEAR-GATE verdict=GREEN 5/5 (align_corners=False, exact vs PyTorch)\n" as *u8); sys_exit(0) }
46 sys_exit(1)
47 return 0
48}