code wiki / _hdl_build / nx_dataframe_gate.nx
nx_dataframe_gate.nx source
↩ module page · 142 lines · 7035 B
1import "nx_gate_gn.nx"
2// nx_dataframe_gate.nx -- GATE for the aggregation front door (nx_dataframe). Known-answer tests on a fixed
3// column so every reduction, predicate scan, quantile, GROUP BY, and inner join is proven EXACT (integer-
4// reproducible). Anti-false-green: a deliberately-wrong expected value is NOT used; every assert is the true
5// hand-computed answer. expect_exit: 0 license_tier: ORIGINAL
6import "nx_syscalls.nx"
7import "_hdl_build/nx_dataframe.nx"
8import "nx_gate_verdict.nx"
9
10func gp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
11
12func main() -> i64 {
13 gp("=== nx_dataframe_gate ===\n" as *u8)
14 var pass: i64 = 0
15 var fail: i64 = 0
16
17 // column = [5, 2, 9, 2, 7, 5] (n=6) sum=30 min=2 max=9 mean=5 (30/6) sorted=[2,2,5,5,7,9]
18 let col: *i64 = sys_mmap(6 * 8) as *i64
19 col[0]=5; col[1]=2; col[2]=9; col[3]=2; col[4]=7; col[5]=5
20 let n: i64 = 6
21
22 // T1 reductions
23 var t1: i64 = 1
24 if df_count(col, n) != 6 { t1 = 0 }
25 if df_sum(col, n) != 30 { t1 = 0 }
26 if df_min(col, n) != 2 { t1 = 0 }
27 if df_max(col, n) != 9 { t1 = 0 }
28 if t1 == 1 { pass = pass + 1 } else { fail = fail + 1; gp("T1 FAIL reductions\n" as *u8) }
29
30 // T2 mean + remainder + milli mean (30/6 = 5 exact; milli = 5000)
31 var t2: i64 = 1
32 let rem: *i64 = sys_mmap(8) as *i64
33 if df_mean(col, n, rem) != 5 { t2 = 0 }
34 if rem[0] != 0 { t2 = 0 }
35 if df_mean_milli(col, n) != 5000 { t2 = 0 }
36 if t2 == 1 { pass = pass + 1 } else { fail = fail + 1; gp("T2 FAIL mean\n" as *u8) }
37
38 // T3 mean with remainder on a non-divisible column [1,2,3,4] sum=10 n=4 mean=2 rem=2 milli=2500
39 let c2: *i64 = sys_mmap(4 * 8) as *i64
40 c2[0]=1; c2[1]=2; c2[2]=3; c2[3]=4
41 var t3: i64 = 1
42 if df_mean(c2, 4, rem) != 2 { t3 = 0 }
43 if rem[0] != 2 { t3 = 0 }
44 if df_mean_milli(c2, 4) != 2500 { t3 = 0 }
45 if t3 == 1 { pass = pass + 1 } else { fail = fail + 1; gp("T3 FAIL mean-remainder\n" as *u8) }
46
47 // T4 variance + stddev on [2,4,4,4,5,5,7,9]: mean=5, var=4, stddev=2 (textbook)
48 let c3: *i64 = sys_mmap(8 * 8) as *i64
49 c3[0]=2; c3[1]=4; c3[2]=4; c3[3]=4; c3[4]=5; c3[5]=5; c3[6]=7; c3[7]=9
50 var t4: i64 = 1
51 let vm: i64 = df_var_milli(c3, 8) // 4 * 1000 = 4000
52 if vm != 4000 { t4 = 0 }
53 if df_isqrt(vm / 1000) != 2 { t4 = 0 } // sqrt(4) = 2
54 if df_isqrt(9) != 3 { t4 = 0 }
55 if df_isqrt(10) != 3 { t4 = 0 } // floor
56 if t4 == 1 { pass = pass + 1 } else { fail = fail + 1; gp("T4 FAIL variance/stddev\n" as *u8) }
57
58 // T5 predicate scans on col [5,2,9,2,7,5]: >=5 -> {5,9,7,5}=4 count, sum=26 ; ==2 -> 2 count
59 var t5: i64 = 1
60 if df_filter_count(col, n, 4, 5) != 4 { t5 = 0 } // >=5
61 if df_filter_sum(col, n, 4, 5) != 26 { t5 = 0 }
62 if df_filter_count(col, n, 0, 2) != 2 { t5 = 0 } // ==2
63 if df_filter_count(col, n, 1, 5) != 2 { t5 = 0 } // <5 -> {2,2}
64 if t5 == 1 { pass = pass + 1 } else { fail = fail + 1; gp("T5 FAIL predicate scan\n" as *u8) }
65
66 // T6 quantiles on sorted [2,2,5,5,7,9]: min(q0)=2, max(q1000)=9, median(q500)=rank (500*5/1000)=2 -> cp[2]=5
67 var t6: i64 = 1
68 if df_quantile(col, n, 0) != 2 { t6 = 0 }
69 if df_quantile(col, n, 1000) != 9 { t6 = 0 }
70 if df_quantile(col, n, 500) != 5 { t6 = 0 }
71 // the source column must be UNCHANGED (quantile sorts a copy)
72 if col[0] != 5 { t6 = 0 }
73 if col[1] != 2 { t6 = 0 }
74 if t6 == 1 { pass = pass + 1 } else { fail = fail + 1; gp("T6 FAIL quantile / column-immutability\n" as *u8) }
75
76 // T7 GROUP BY: keys=[1,2,1,3,2,1] vals=[10,20,30,40,50,60]
77 // count: g1=3 g2=2 g3=1 ; sum: g1=100 g2=70 g3=40
78 let gk: *i64 = sys_mmap(6 * 8) as *i64
79 let gv: *i64 = sys_mmap(6 * 8) as *i64
80 gk[0]=1; gk[1]=2; gk[2]=1; gk[3]=3; gk[4]=2; gk[5]=1
81 gv[0]=10; gv[1]=20; gv[2]=30; gv[3]=40; gv[4]=50; gv[5]=60
82 let ok: *i64 = sys_mmap(16 * 8) as *i64
83 let oa: *i64 = sys_mmap(16 * 8) as *i64
84 var t7: i64 = 1
85 let gc: i64 = df_groupby(gk, gv, 6, 0, ok, oa, 16) // count
86 if gc != 3 { t7 = 0 }
87 // groups emitted in first-seen order: key1,key2,key3
88 if ok[0] != 1 { t7 = 0 } else { if oa[0] != 3 { t7 = 0 } }
89 if ok[1] != 2 { t7 = 0 } else { if oa[1] != 2 { t7 = 0 } }
90 if ok[2] != 3 { t7 = 0 } else { if oa[2] != 1 { t7 = 0 } }
91 let gc2: i64 = df_groupby(gk, gv, 6, 1, ok, oa, 16) // sum
92 if gc2 != 3 { t7 = 0 }
93 if oa[0] != 100 { t7 = 0 }
94 if oa[1] != 70 { t7 = 0 }
95 if oa[2] != 40 { t7 = 0 }
96 if t7 == 1 { pass = pass + 1 } else { fail = fail + 1; gp("T7 FAIL groupby\n" as *u8) }
97
98 // T8 INNER JOIN: left keys=[1,2,3] vals=[100,200,300]; right keys=[2,3,4] vals=[22,33,44]
99 // matches: (200,22),(300,33) -> 2 rows
100 let lk: *i64 = sys_mmap(3 * 8) as *i64
101 let lv: *i64 = sys_mmap(3 * 8) as *i64
102 let rk: *i64 = sys_mmap(3 * 8) as *i64
103 let rv: *i64 = sys_mmap(3 * 8) as *i64
104 lk[0]=1; lk[1]=2; lk[2]=3; lv[0]=100; lv[1]=200; lv[2]=300
105 rk[0]=2; rk[1]=3; rk[2]=4; rv[0]=22; rv[1]=33; rv[2]=44
106 let jl: *i64 = sys_mmap(8 * 8) as *i64
107 let jr: *i64 = sys_mmap(8 * 8) as *i64
108 var t8: i64 = 1
109 let jn: i64 = df_inner_join(lk, lv, 3, rk, rv, 3, jl, jr, 8)
110 if jn != 2 { t8 = 0 }
111 if jl[0] != 200 { t8 = 0 } else { if jr[0] != 22 { t8 = 0 } }
112 if jl[1] != 300 { t8 = 0 } else { if jr[1] != 33 { t8 = 0 } }
113 if t8 == 1 { pass = pass + 1 } else { fail = fail + 1; gp("T8 FAIL inner join\n" as *u8) }
114
115 // T9 empty-column safety (no crash, sane zeros)
116 var t9: i64 = 1
117 let ec: *i64 = sys_mmap(8) as *i64
118 if df_count(ec, 0) != 0 { t9 = 0 }
119 if df_sum(ec, 0) != 0 { t9 = 0 }
120 if df_mean(ec, 0, rem) != 0 { t9 = 0 }
121 if df_quantile(ec, 0, 500) != 0 { t9 = 0 }
122 if t9 == 1 { pass = pass + 1 } else { fail = fail + 1; gp("T9 FAIL empty safety\n" as *u8) }
123
124 gp("pass=" as *u8); gn(pass); gp(" fail=" as *u8); gn(fail); gp("\n" as *u8)
125 let log: *u8 = sys_mmap(128)
126 var lo: i64 = 0
127 let pre: *u8 = "DATAFRAME authored=organ verdict=" as *u8
128 var pi: i64 = 0; while pre[pi]!=(0 as u8){log[lo]=pre[pi];lo=lo+1;pi=pi+1}
129 if fail == 0 { let g: *u8="GREEN\n" as *u8; var gi:i64=0; while g[gi]!=(0 as u8){log[lo]=g[gi];lo=lo+1;gi=gi+1} } else { let rr: *u8="RED\n" as *u8; var ri:i64=0; while rr[ri]!=(0 as u8){log[lo]=rr[ri];lo=lo+1;ri=ri+1} }
130 let fd: i64 = sys_openat_wr("knowledge/status/dataframe.log" as *u8, 0x1A4)
131 if fd >= 0 { sys_write(fd, log, lo); sys_close(fd) }
132
133 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
134 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
135 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
136 let ctr__dry: *i64 = gv_ctr()
137 ctr__dry[0] = pass
138 ctr__dry[1] = pass + fail
139 let rc__dry: i64 = gv_verdict("DATAFRAME-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
140 sys_exit(rc__dry)
141 return rc__dry
142}