code wiki / _hdl_build / nx_timeseries_gate.nx
nx_timeseries_gate.nx source
↩ module page · 110 lines · 5838 B
1// nx_timeseries_gate.nx -- GATE for time-series analytics (nx_timeseries). Known-answer: an exact rising
2// ramp -> slope=+1000 (1.0/step) intercept=base; a falling ramp -> negative; a flat series -> ~0 + FLAT
3// class; rolling mean smooths + endpoints correct; growth% exact. expect_exit: 0 license_tier: ORIGINAL
4import "nx_syscalls.nx"
5import "_hdl_build/nx_timeseries.nx"
6import "nx_gate_verdict.nx"
7
8func tp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
9func tn(v: i64) -> i64 { var m: i64=v; if m<0{tp("-" as *u8);m=0-m} let t:*u8=sys_mmap(24); var k:i64=0; if m==0{t[0]=48 as u8;k=1} while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1} let o:*u8=sys_mmap(24); var i:i64=0; while i<k{o[i]=t[k-1-i];i=i+1} sys_write(1,o,k); return 0 }
10func tstreq(a: *u8, b: *u8) -> i64 { var i: i64=0; while a[i]!=(0 as u8){ if a[i]!=b[i] { return 0 } i=i+1 } if b[i]!=(0 as u8){return 0} return 1 }
11
12func main() -> i64 {
13 tp("=== nx_timeseries_gate ===\n" as *u8)
14 var pass: i64 = 0
15 var fail: i64 = 0
16 let n: i64 = 50
17 let sm: *i64 = sys_mmap(8) as *i64
18 let ic: *i64 = sys_mmap(8) as *i64
19
20 // C1 rising ramp: y = 100 + 3*i -> slope 3.0 (=3000 milli), intercept 100
21 let rise: *i64 = sys_mmap(n * 8) as *i64
22 var i: i64 = 0
23 while i < n { rise[i] = 100 + 3 * i; i = i + 1 }
24 ts_linear_trend(rise, n, sm, ic)
25 tp("rising slope_milli=" as *u8); tn(sm[0]); tp(" intercept=" as *u8); tn(ic[0]); tp("\n" as *u8)
26 var t1: i64 = 1
27 if sm[0] != 3000 { t1 = 0 }
28 if ic[0] != 100 { t1 = 0 }
29 if ts_trend_class(sm[0], 100) != TS_RISING { t1 = 0 }
30 if tstreq(ts_class_str(ts_trend_class(sm[0], 100)), "rising" as *u8) == 0 { t1 = 0 }
31 if t1 == 1 { pass = pass + 1 } else { fail = fail + 1; tp("C1 FAIL rising trend\n" as *u8) }
32
33 // C2 falling ramp: y = 500 - 2*i -> slope -2000, FALLING
34 let fall: *i64 = sys_mmap(n * 8) as *i64
35 i = 0
36 while i < n { fall[i] = 500 - 2 * i; i = i + 1 }
37 ts_linear_trend(fall, n, sm, ic)
38 tp("falling slope_milli=" as *u8); tn(sm[0]); tp("\n" as *u8)
39 var t2: i64 = 1
40 if sm[0] != (0 - 2000) { t2 = 0 }
41 if ts_trend_class(sm[0], 100) != TS_FALLING { t2 = 0 }
42 if t2 == 1 { pass = pass + 1 } else { fail = fail + 1; tp("C2 FAIL falling trend\n" as *u8) }
43
44 // C3 flat: constant 42 -> slope 0, FLAT
45 let flat: *i64 = sys_mmap(n * 8) as *i64
46 i = 0
47 while i < n { flat[i] = 42; i = i + 1 }
48 ts_linear_trend(flat, n, sm, ic)
49 var t3: i64 = 1
50 if sm[0] != 0 { t3 = 0 }
51 if ts_trend_class(sm[0], 100) != TS_FLAT { t3 = 0 }
52 if tstreq(ts_class_str(TS_FLAT), "flat" as *u8) == 0 { t3 = 0 }
53 if t3 == 1 { pass = pass + 1 } else { fail = fail + 1; tp("C3 FAIL flat trend\n" as *u8) }
54
55 // C4 rolling mean window=3 on [0,3,6,9,...]: out[0]=0, out[1]=(0+3)/2=1, out[2]=(0+3+6)/3=3, out[3]=(3+6+9)/3=6
56 let rm: *i64 = sys_mmap(n * 8) as *i64
57 ts_rolling_mean(rise, n, 3, rm) // rise=100+3i; trailing window smooths but tracks up
58 var t4: i64 = 1
59 // window=3 trailing mean of a linear series lags by ~1 step-mean; verify monotonic increasing + endpoint
60 if rm[0] != rise[0] { t4 = 0 } // first element = itself (window of 1)
61 if rm[n - 1] >= rise[n - 1] { t4 = 0 } // trailing mean of rising series < current value
62 var mono: i64 = 1
63 var k: i64 = 1
64 while k < n { if rm[k] < rm[k - 1] { mono = 0 } k = k + 1 }
65 if mono == 0 { t4 = 0 }
66 // exact check on a simple ramp y=i (window 3): out[3] = (1+2+3)/3 = 2
67 let ramp: *i64 = sys_mmap(n * 8) as *i64
68 i = 0
69 while i < n { ramp[i] = i; i = i + 1 }
70 ts_rolling_mean(ramp, n, 3, rm)
71 if rm[3] != 2 { t4 = 0 }
72 if rm[2] != 1 { t4 = 0 }
73 if t4 == 1 { pass = pass + 1 } else { fail = fail + 1; tp("C4 FAIL rolling mean\n" as *u8) }
74
75 // C5 growth permil: first=100 last=100+3*49=247 -> (247-100)*1000/100 = 1470 permil
76 let g: i64 = ts_growth_permil(rise, n)
77 tp("growth_permil=" as *u8); tn(g); tp("\n" as *u8)
78 var t5: i64 = 1
79 if g != 1470 { t5 = 0 }
80 if ts_growth_permil(fall, n) >= 0 { t5 = 0 } // falling -> negative growth
81 if t5 == 1 { pass = pass + 1 } else { fail = fail + 1; tp("C5 FAIL growth\n" as *u8) }
82
83 // C6 degenerate/empty safety
84 var t6: i64 = 1
85 let one: *i64 = sys_mmap(8) as *i64
86 one[0] = 5
87 if ts_linear_trend(one, 1, sm, ic) != (0 - 1) { t6 = 0 }
88 if ts_growth_permil(one, 1) != 0 { t6 = 0 }
89 if t6 == 1 { pass = pass + 1 } else { fail = fail + 1; tp("C6 FAIL degenerate safety\n" as *u8) }
90
91 tp("pass=" as *u8); tn(pass); tp(" fail=" as *u8); tn(fail); tp("\n" as *u8)
92 let log: *u8 = sys_mmap(128)
93 var lo: i64 = 0
94 let pre: *u8 = "TIMESERIES authored=organ verdict=" as *u8
95 var pi: i64 = 0
96 while pre[pi] != (0 as u8) { log[lo] = pre[pi]; lo = lo + 1; pi = pi + 1 }
97 if fail == 0 { let gg: *u8 = "GREEN\n" as *u8; var gi: i64 = 0; while gg[gi] != (0 as u8) { log[lo] = gg[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 } }
98 let fd: i64 = sys_openat_wr("knowledge/status/timeseries.log" as *u8, 0x1A4)
99 if fd >= 0 { sys_write(fd, log, lo); sys_close(fd) }
100
101 // MIGRATED onto nx_gate_verdict by nx_gate_dry_apply (D001, minimal form): every check
102 // row above is untouched, so the PASS/FAIL vector cannot change; only the hand-rolled
103 // verdict emission is replaced by the ONE shared base class. Proven by nx_gate_migrate verify.
104 let ctr__dry: *i64 = gv_ctr()
105 ctr__dry[0] = pass
106 ctr__dry[1] = pass + fail
107 let rc__dry: i64 = gv_verdict("TIMESERIES-GATE" as *u8, ctr__dry, "teeth unchanged; verdict emission migrated onto the shared base class" as *u8)
108 sys_exit(rc__dry)
109 return rc__dry
110}