code wiki / (root) / nx_bench_metrics_test.nx

nx_bench_metrics_test.nx source

↩ module page · 106 lines · 4024 B

1// nx_bench_metrics_test.nx -- KAT for the retrieval-quality kernels. 2// 3// Native sovereign lane: nx_compile_x86_native.elf -> as -> ld -> run. 4// Exit 0 = all pass; exit N = assertion N failed. 5// 6// Goldens (Q16.16, FX_ONE = 65536): 7// DCG[3,2,3,0,1,2]@6 = 6.8610 * 65536 ~= 449640 8// IDCG (sorted desc) = 7.1410 * 65536 ~= 467989 9// nDCG = 0.96081 * 65536 ~= 62968 10// precision@4 (2 rel) = 0.5 -> 32768 (exact) 11// recall@4 (2 of 3) = 0.6667 -> 43690 (exact, truncated) 12// RR (first rel @ 2) = 0.5 -> 32768 (exact) 13// AP [a,b,c,d] rel{a,c}= (1 + 2/3)/2 = 0.8333 -> 54613 (exact, trunc) 14// primary@4 [1,0,1,1] = 0.75 -> 49152 (exact) 15// canonical_rate[1,1,2,3]= 0.75 -> 49152 (exact) 16 17import "fx.nx" 18import "nx_bench_metrics.nx" 19 20func within(a: i64, b: i64, tol: i64) -> i64 { 21 var d: i64 = a - b 22 if d < 0 { d = 0 - d } 23 if d <= tol { return 1 } 24 return 0 25} 26 27func main() -> i64 { 28 // ---- graded gains [3,2,3,0,1,2] in Q16.16 ---- 29 let g_raw: *u8 = sys_mmap(6 * 8) 30 let g: *i64 = g_raw as *i64 31 g[0] = fx_from_int(3) 32 g[1] = fx_from_int(2) 33 g[2] = fx_from_int(3) 34 g[3] = 0 35 g[4] = fx_from_int(1) 36 g[5] = fx_from_int(2) 37 38 let dcg: i64 = nx_bench_dcg(g, 6, 6) 39 if within(dcg, 449640, 200) != 1 { return 1 } 40 41 let ndcg: i64 = nx_bench_ndcg(g, 6, 6) 42 if within(ndcg, 62968, 150) != 1 { return 2 } 43 44 // already-ideal order normalizes to 1.0 45 let g2_raw: *u8 = sys_mmap(3 * 8) 46 let g2: *i64 = g2_raw as *i64 47 g2[0] = fx_from_int(3); g2[1] = fx_from_int(2); g2[2] = fx_from_int(1) 48 if within(nx_bench_ndcg(g2, 3, 3), FX_ONE, 4) != 1 { return 3 } 49 50 // no relevant gain -> nDCG 0 51 let g3_raw: *u8 = sys_mmap(3 * 8) 52 let g3: *i64 = g3_raw as *i64 53 g3[0] = 0; g3[1] = 0; g3[2] = 0 54 if nx_bench_ndcg(g3, 3, 3) != 0 { return 4 } 55 56 // ---- id lists: retrieved [10,20,30,40], relevant {10,30,50} ---- 57 let retr_raw: *u8 = sys_mmap(4 * 8) 58 let retr: *i64 = retr_raw as *i64 59 retr[0] = 10; retr[1] = 20; retr[2] = 30; retr[3] = 40 60 let rel_raw: *u8 = sys_mmap(3 * 8) 61 let rel: *i64 = rel_raw as *i64 62 rel[0] = 10; rel[1] = 30; rel[2] = 50 63 64 // precision@4 = 2/4 = 0.5 65 if nx_bench_precision_at_k(retr, 4, rel, 3, 4) != FX_HALF { return 5 } 66 // recall@4 = 2/3 -> (2<<16)/3 = 43690 67 if nx_bench_recall_at_k(retr, 4, rel, 3, 4) != 43690 { return 6 } 68 // RR: first relevant is 10 at rank 1 -> 1.0 69 if nx_bench_reciprocal_rank(retr, 4, rel, 3) != FX_ONE { return 7 } 70 71 // RR with first relevant at rank 2: retrieved [20,10,30], rel {10} 72 let retr2_raw: *u8 = sys_mmap(3 * 8) 73 let retr2: *i64 = retr2_raw as *i64 74 retr2[0] = 20; retr2[1] = 10; retr2[2] = 30 75 let rel2_raw: *u8 = sys_mmap(1 * 8) 76 let rel2: *i64 = rel2_raw as *i64 77 rel2[0] = 10 78 if nx_bench_reciprocal_rank(retr2, 3, rel2, 1) != FX_HALF { return 8 } 79 80 // AP: retrieved [10,20,30,40], rel {10,30} -> (1/1 + 2/3)/2 81 // = (65536 + 43690)/2 = 54613 82 let relac_raw: *u8 = sys_mmap(2 * 8) 83 let relac: *i64 = relac_raw as *i64 84 relac[0] = 10; relac[1] = 30 85 if within(nx_bench_average_precision(retr, 4, relac, 2), 54613, 1) != 1 { return 9 } 86 87 // ---- primary-source precision: [1,0,1,1]@4 = 0.75 ---- 88 let prim_raw: *u8 = sys_mmap(4 * 8) 89 let prim: *i64 = prim_raw as *i64 90 prim[0] = 1; prim[1] = 0; prim[2] = 1; prim[3] = 1 91 if nx_bench_primary_precision_at_k(prim, 4, 4) != 49152 { return 10 } 92 // top-2 [1,0] = 0.5 93 if nx_bench_primary_precision_at_k(prim, 4, 2) != FX_HALF { return 11 } 94 95 // ---- canonical rate: [1,1,2,3] = 3 distinct / 4 = 0.75 ---- 96 let can_raw: *u8 = sys_mmap(4 * 8) 97 let can: *i64 = can_raw as *i64 98 can[0] = 1; can[1] = 1; can[2] = 2; can[3] = 3 99 if nx_bench_canonical_rate(can, 4) != 49152 { return 12 } 100 101 // ---- altitude = (ndcg + primary)/2 ---- 102 if nx_bench_altitude(FX_ONE, FX_ONE) != FX_ONE { return 13 } 103 if nx_bench_altitude(FX_ONE, 0) != FX_HALF { return 14 } 104 105 return 0 106}