nx_f32_conv2d_grouped_gate.nx source
↩ module page · 63 lines · 3856 B
1// nx_f32_conv2d_grouped_gate.nx -- exact proof of grouped conv: depthwise (groups=C_in), a 2-group case, dense
2// equivalence (groups=1 == nx_f32_conv2d_forward), and the divisibility guard. expect_exit: 0
3import "nx_syscalls.nx"
4import "nx_f32_cvt.nx"
5import "nx_f32_conv2d.nx"
6import "nx_f32_conv2d_grouped.nx"
7
8func gp(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return sys_write(1, s, n) }
9func gn(v: i64) -> i64 {
10 let bb: *u8 = sys_mmap(28); var m: i64 = v
11 if m < 0 { sys_write(1, "-" as *u8, 1); m = 0 - m }
12 let t: *u8 = sys_mmap(28); var k: i64 = 0
13 if m == 0 { t[0] = 48 as u8; k = 1 }
14 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
15 var i: i64 = 0; while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
16 return sys_write(1, bb, k)
17}
18
19func main(argc: i64, argv: *i64) -> i64 {
20 var pass: i64 = 0
21 let inp: *i64 = sys_mmap(8 * 16) as *i64
22 let wt: *i64 = sys_mmap(8 * 16) as *i64
23 let out: *i64 = sys_mmap(8 * 16) as *i64
24 let od: *i64 = sys_mmap(8 * 16) as *i64
25
26 // G1 DEPTHWISE: C_in=C_out=2, groups=2, H=W=2, 1x1. ch0=[1,2,3,4]*10, ch1=[5,6,7,8]*100
27 inp[0]=nx_i32_to_f32(1); inp[1]=nx_i32_to_f32(2); inp[2]=nx_i32_to_f32(3); inp[3]=nx_i32_to_f32(4)
28 inp[4]=nx_i32_to_f32(5); inp[5]=nx_i32_to_f32(6); inp[6]=nx_i32_to_f32(7); inp[7]=nx_i32_to_f32(8)
29 wt[0]=nx_i32_to_f32(10); wt[1]=nx_i32_to_f32(100) // [C_out=2, cig=1, 1,1]
30 var g1: i64 = nx_f32_conv2d_grouped(inp, 1, 2, 2, 2, wt, 2, 1, 1, 1, 0, 2, 0 as *i64, out)
31 // out ch0 = [10,20,30,40], ch1 = [500,600,700,800]
32 if out[0]==nx_i32_to_f32(10) { if out[3]==nx_i32_to_f32(40) { if out[4]==nx_i32_to_f32(500) { if out[7]==nx_i32_to_f32(800) {
33 pass = pass + 1; gp("G1 depthwise per-channel scale OK\n" as *u8)
34 } } } }
35 if out[4]!=nx_i32_to_f32(500) { gp("G1 FAIL o0=" as *u8); gn(out[0]); gp(" o4=" as *u8); gn(out[4]); gp("\n" as *u8) }
36
37 // G2 GROUPED g=2: C_in=4 -> C_out=2, H=W=1, 1x1. in=[1,2,3,4]; co0 uses ch0,ch1; co1 uses ch2,ch3; weights all 1
38 inp[0]=nx_i32_to_f32(1); inp[1]=nx_i32_to_f32(2); inp[2]=nx_i32_to_f32(3); inp[3]=nx_i32_to_f32(4)
39 var j: i64 = 0; while j < 4 { wt[j]=nx_i32_to_f32(1); j = j + 1 } // [C_out=2, cig=2, 1,1]
40 var g2: i64 = nx_f32_conv2d_grouped(inp, 1, 4, 1, 1, wt, 2, 1, 1, 1, 0, 2, 0 as *i64, out)
41 // co0 = 1+2 = 3 ; co1 = 3+4 = 7
42 if out[0]==nx_i32_to_f32(3) { if out[1]==nx_i32_to_f32(7) {
43 pass = pass + 1; gp("G2 grouped(2) co0=3 co1=7 OK\n" as *u8)
44 } }
45 if out[0]!=nx_i32_to_f32(3) { gp("G2 FAIL o0=" as *u8); gn(out[0]); gp(" o1=" as *u8); gn(out[1]); gp("\n" as *u8) }
46
47 // G3 DENSE EQUIVALENCE: groups=1 must equal nx_f32_conv2d_forward. C_in=1,C_out=1,3x3,in=1..9, weight=1..9, pad0 -> 1x1
48 var i: i64 = 0; while i < 9 { inp[i]=nx_i32_to_f32(i+1); wt[i]=nx_i32_to_f32(i+1); i = i + 1 }
49 nx_f32_conv2d_forward(inp, 1, 1, 3, 3, wt, 1, 3, 3, 1, 0, 0 as *i64, od)
50 var g3: i64 = nx_f32_conv2d_grouped(inp, 1, 1, 3, 3, wt, 1, 3, 3, 1, 0, 1, 0 as *i64, out)
51 if out[0] == od[0] { pass = pass + 1; gp("G3 groups=1 == dense conv (out=" as *u8); gn(out[0]); gp(") OK\n" as *u8) }
52 if out[0] != od[0] { gp("G3 FAIL grouped=" as *u8); gn(out[0]); gp(" dense=" as *u8); gn(od[0]); gp("\n" as *u8) }
53
54 // G4 guard: C_in=3, groups=2 -> not divisible -> ERR
55 var g4: i64 = nx_f32_conv2d_grouped(inp, 1, 3, 1, 1, wt, 2, 1, 1, 1, 0, 2, 0 as *i64, out)
56 if g1==0 { if g2==0 { if g3==0 { if g4==4 { pass = pass + 1; gp("G4 rc ok (valid=0, indivisible=ERR) OK\n" as *u8) } } } }
57 if g4 != 4 { gp("G4 FAIL g4=" as *u8); gn(g4); gp("\n" as *u8) }
58
59 gp("GROUPED-CONV-GATE pass=" as *u8); gn(pass); gp("/4\n" as *u8)
60 if pass == 4 { gp("GROUPED-CONV-GATE GREEN 4/4 (depthwise + grouped + dense-equivalence + guard)\n" as *u8); sys_exit(0) }
61 sys_exit(1)
62 return 0
63}