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}