code wiki / (root) / nx_f32_upsample_bilinear_gate.nx

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}