code wiki / (root) / sketch_mann_kendall_test.nx

sketch_mann_kendall_test.nx source

↩ module page · 100 lines · 3033 B

1// sketch_mann_kendall_test.nx -- streaming Mann-Kendall trend test verification. 2 3import "syscalls.nx" 4import "sketch_mann_kendall.nx" 5import "sketch_types.nx" 6 7func main() -> i64 { 8 // ---- alloc ---- 9 let m: *MannKendall = nx_mk_alloc(20) 10 if m == (0 as *MannKendall) { return __syscall(93, 5, 0, 0, 0, 0, 0) } 11 // Reject W<3. 12 if nx_mk_alloc(2) != (0 as *MannKendall) { 13 return __syscall(93, 6, 0, 0, 0, 0, 0) 14 } 15 16 // ---- empty: NONE verdict ---- 17 if nx_mk_verdict(m) != NX_MK_TREND_NONE { 18 return __syscall(93, 10, 0, 0, 0, 0, 0) 19 } 20 21 // ---- strictly increasing: UP trend ---- 22 var i: i64 = 1 23 while i <= 20 { 24 nx_mk_push(m, i) 25 i = i + 1 26 } 27 // All pairs (i,j) with i<j have x_j > x_i: S = C(20,2) = 190. 28 if nx_mk_s(m) != 190 { 29 return __syscall(93, 20, 0, 0, 0, 0, 0) 30 } 31 // 190² = 36100; Var(S) = 20*19*45/18 = 950; 4*950 = 3800. 36100 > 3800. 32 if nx_mk_verdict(m) != NX_MK_TREND_UP { 33 return __syscall(93, 21, 0, 0, 0, 0, 0) 34 } 35 36 // ---- strictly decreasing: DOWN trend ---- 37 let m2: *MannKendall = nx_mk_alloc(20) 38 i = 20 39 while i >= 1 { 40 nx_mk_push(m2, i) 41 i = i - 1 42 } 43 // S = -190. 44 if nx_mk_s(m2) != -190 { 45 return __syscall(93, 30, 0, 0, 0, 0, 0) 46 } 47 if nx_mk_verdict(m2) != NX_MK_TREND_DOWN { 48 return __syscall(93, 31, 0, 0, 0, 0, 0) 49 } 50 51 // ---- alternating (no trend): NONE ---- 52 let m3: *MannKendall = nx_mk_alloc(20) 53 i = 0 54 while i < 20 { 55 // Alternating high/low values around 100. 56 if (i & 1) == 0 { nx_mk_push(m3, 100) } 57 if (i & 1) == 1 { nx_mk_push(m3, 105) } 58 i = i + 1 59 } 60 // Symmetric: S should be small (zero in expectation; some bias from ties). 61 if nx_mk_verdict(m3) != NX_MK_TREND_NONE { 62 return __syscall(93, 40, 0, 0, 0, 0, 0) 63 } 64 65 // ---- sliding-window: trend changes as new data arrives ---- 66 let m4: *MannKendall = nx_mk_alloc(10) 67 // Fill with decreasing data. 68 i = 10 69 while i >= 1 { 70 nx_mk_push(m4, i) 71 i = i - 1 72 } 73 if nx_mk_verdict(m4) != NX_MK_TREND_DOWN { 74 return __syscall(93, 50, 0, 0, 0, 0, 0) 75 } 76 // Now push increasing data; window slides. After 10 more inserts 77 // of 1..10, window contains 10 increasing values; trend flips to UP. 78 i = 1 79 while i <= 10 { 80 nx_mk_push(m4, i) 81 i = i + 1 82 } 83 if nx_mk_verdict(m4) != NX_MK_TREND_UP { 84 return __syscall(93, 51, 0, 0, 0, 0, 0) 85 } 86 87 // ---- typed envelope ---- 88 let q: *ApproxI64 = nx_mk_query(m) 89 if q.envelope_kind != NX_ENV_ABS { 90 return __syscall(93, 60, 0, 0, 0, 0, 0) 91 } 92 if q.conf_ppb != 950000000 { // 95% conf (two-sided) 93 return __syscall(93, 61, 0, 0, 0, 0, 0) 94 } 95 if q.maturity != NX_MATURITY_PRODUCTION { 96 return __syscall(93, 62, 0, 0, 0, 0, 0) 97 } 98 99 return 0 100}