sketch_moments_test.nx source
↩ module page · 124 lines · 3762 B
1// sketch_moments_test.nx -- streaming skewness + kurtosis verification.
2
3import "syscalls.nx"
4import "sketch_moments.nx"
5import "sketch_types.nx"
6
7func iabs(x: i64) -> i64 {
8 if x < 0 { return -x }
9 return x
10}
11
12func main() -> i64 {
13 // ---- alloc + empty ----
14 let m: *Moments = nx_mom_alloc()
15 if m == (0 as *Moments) { return __syscall(93, 5, 0, 0, 0, 0, 0) }
16 if m.count != 0 { return __syscall(93, 6, 0, 0, 0, 0, 0) }
17 if nx_mom_skewness_ppm(m) != 0 { return __syscall(93, 7, 0, 0, 0, 0, 0) }
18 if nx_mom_kurtosis_ppm(m) != 0 { return __syscall(93, 8, 0, 0, 0, 0, 0) }
19
20 // ---- symmetric data: skewness near 0 ----
21 // [-3, -1, 1, 3]: mean=0, symmetric -> skewness exactly 0.
22 nx_mom_add(m, -3)
23 nx_mom_add(m, -1)
24 nx_mom_add(m, 1)
25 nx_mom_add(m, 3)
26 if nx_mom_mean(m) != 0 { return __syscall(93, 10, 0, 0, 0, 0, 0) }
27 // variance = (9+1+1+9)/4 = 5.
28 if nx_mom_variance(m) != 5 {
29 return __syscall(93, 11, 0, 0, 0, 0, 0)
30 }
31 // Symmetric -> skewness = 0.
32 if iabs(nx_mom_skewness_ppm(m)) > 100000 { // < 10% in ppm
33 return __syscall(93, 12, 0, 0, 0, 0, 0)
34 }
35
36 // ---- positive skew: right tail dominates ----
37 // [1, 1, 1, 1, 1, 100]: mostly low, one big. Skewness > 0.
38 let m2: *Moments = nx_mom_alloc()
39 nx_mom_add(m2, 1)
40 nx_mom_add(m2, 1)
41 nx_mom_add(m2, 1)
42 nx_mom_add(m2, 1)
43 nx_mom_add(m2, 1)
44 nx_mom_add(m2, 100)
45 let s: i64 = nx_mom_skewness_ppm(m2)
46 if s <= 0 {
47 return __syscall(93, 20, 0, 0, 0, 0, 0)
48 }
49 // Should be significantly positive.
50 if s < 1000000 { // > 1.0 expected for this skewed sample
51 return __syscall(93, 21, 0, 0, 0, 0, 0)
52 }
53
54 // ---- negative skew ----
55 let m3: *Moments = nx_mom_alloc()
56 nx_mom_add(m3, 100)
57 nx_mom_add(m3, 100)
58 nx_mom_add(m3, 100)
59 nx_mom_add(m3, 100)
60 nx_mom_add(m3, 100)
61 nx_mom_add(m3, 1)
62 let s3: i64 = nx_mom_skewness_ppm(m3)
63 if s3 >= 0 {
64 return __syscall(93, 30, 0, 0, 0, 0, 0)
65 }
66 if s3 > -1000000 {
67 return __syscall(93, 31, 0, 0, 0, 0, 0)
68 }
69
70 // ---- merge ----
71 let ma: *Moments = nx_mom_alloc()
72 let mb: *Moments = nx_mom_alloc()
73 var i: i64 = 0
74 while i < 50 {
75 nx_mom_add(ma, i + 1)
76 i = i + 1
77 }
78 i = 51
79 while i <= 100 {
80 nx_mom_add(mb, i)
81 i = i + 1
82 }
83 let merged: *Moments = nx_mom_merge(ma, mb)
84 if merged.count != 100 {
85 return __syscall(93, 40, 0, 0, 0, 0, 0)
86 }
87 // Mean of 1..100 = 50.5 -> integer 50.
88 if iabs(nx_mom_mean(merged) - 50) > 1 {
89 return __syscall(93, 41, 0, 0, 0, 0, 0)
90 }
91
92 // ---- overflow guard ----
93 if nx_mom_safe_p(2048) != 0 {
94 return __syscall(93, 50, 0, 0, 0, 0, 0)
95 }
96 if nx_mom_safe_p(2000) != 1 {
97 return __syscall(93, 51, 0, 0, 0, 0, 0)
98 }
99 if nx_mom_safe_p(-2048) != 0 {
100 return __syscall(93, 52, 0, 0, 0, 0, 0)
101 }
102 let mo: *Moments = nx_mom_alloc()
103 if nx_mom_add(mo, 2048) != -1 {
104 return __syscall(93, 53, 0, 0, 0, 0, 0)
105 }
106 if mo.count != 0 { // failed add must not mutate
107 return __syscall(93, 54, 0, 0, 0, 0, 0)
108 }
109
110 // ---- typed envelope ----
111 let q: *ApproxI64 = nx_mom_query_skewness(merged)
112 if q.envelope_kind != NX_ENV_REL_STDDEV {
113 return __syscall(93, 60, 0, 0, 0, 0, 0)
114 }
115 // n=100 -> stderr_ppb = 1e9 / 10 = 1e8.
116 if q.param_a != 100000000 {
117 return __syscall(93, 61, 0, 0, 0, 0, 0)
118 }
119 if q.maturity != NX_MATURITY_REFERENCE_IMPL {
120 return __syscall(93, 62, 0, 0, 0, 0, 0)
121 }
122
123 return 0
124}