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}