code wiki / _hdl_build / _f64_rootfind_gate.nx
_f64_rootfind_gate.nx source
↩ module page · 70 lines · 3556 B
1// _f64_rootfind_gate.nx -- self-validating gate for the GAMS-F bisection root-finder.
2// For each test function: find the root, assert |f(root)| ~ 0 (< 2^-40, the DEFINING
3// property -- a free oracle). For the two with closed-form roots (sqrt2, ln2) also assert
4// the root matches bit-tight (<= 4 ulp). Durable: ROOTFIND-GATE -> math_engine.log.
5// license_tier: ORIGINAL
6import "nx_syscalls.nx"
7import "nx_f64.nx"
8import "nx_f64_rootfind.nx"
9
10func rg_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
11func rg_f(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 }
12func rg_n(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m; sys_write(fd,"-" as *u8,1)}; let t: *u8=sys_mmap(28); 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}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 }
13func rg_ulp(a: i64, b: i64) -> i64 { if a >= b { return a - b } return b - a }
14
15const RG_ONE: i64 = 0x3FF0000000000000
16const RG_TWO: i64 = 0x4000000000000000
17const RG_ZERO: i64 = 0
18
19func main() -> i64 {
20 rg_p("=== F64-ROOTFIND GATE: bisection root-finder, |f(root)|~0 + closed-form roots ===\n" as *u8)
21 let thr: i64 = 983 << 52 // 2^-40
22 var froot_bad: i64 = 0
23 var maxfr: i64 = 0
24
25 // fid 0: x^2-2 on [1,2] -> sqrt2
26 let r0: i64 = nx_f64_root_bisect(0, RG_ONE, RG_TWO)
27 let f0: i64 = rf_eval(0, r0) & 0x7FFFFFFFFFFFFFFF
28 if f0 > maxfr { maxfr = f0 }
29 if f0 >= thr { froot_bad = froot_bad + 1 }
30 // fid 1: cos(x)-x on [0,1] -> Dottie
31 let r1: i64 = nx_f64_root_bisect(1, RG_ZERO, RG_ONE)
32 let f1: i64 = rf_eval(1, r1) & 0x7FFFFFFFFFFFFFFF
33 if f1 > maxfr { maxfr = f1 }
34 if f1 >= thr { froot_bad = froot_bad + 1 }
35 // fid 2: exp(x)-2 on [0,1] -> ln2
36 let r2: i64 = nx_f64_root_bisect(2, RG_ZERO, RG_ONE)
37 let f2: i64 = rf_eval(2, r2) & 0x7FFFFFFFFFFFFFFF
38 if f2 > maxfr { maxfr = f2 }
39 if f2 >= thr { froot_bad = froot_bad + 1 }
40 // fid 3: x^3-x-2 on [1,2]
41 let r3: i64 = nx_f64_root_bisect(3, RG_ONE, RG_TWO)
42 let f3: i64 = rf_eval(3, r3) & 0x7FFFFFFFFFFFFFFF
43 if f3 > maxfr { maxfr = f3 }
44 if f3 >= thr { froot_bad = froot_bad + 1 }
45
46 // closed-form root matches
47 let u_sqrt2: i64 = rg_ulp(r0, 0x3FF6A09E667F3BCD)
48 let u_ln2: i64 = rg_ulp(r2, 0x3FE62E42FEFA39EF)
49
50 var ok: i64 = 0
51 if froot_bad == 0 { if u_sqrt2 <= 4 { if u_ln2 <= 4 { ok = 1 } } }
52 let lfd: i64 = sys_openat_append("knowledge/status/math_engine.log" as *u8, 0x1a4)
53 if lfd >= 0 {
54 rg_f(lfd, "ROOTFIND-GATE epoch=" as *u8); rg_n(lfd, sys_now_realtime_sec())
55 rg_f(lfd, " fns=4 froot_bad=" as *u8); rg_n(lfd, froot_bad)
56 rg_f(lfd, " max_froot_bits=" as *u8); rg_n(lfd, maxfr)
57 rg_f(lfd, " ulp_sqrt2=" as *u8); rg_n(lfd, u_sqrt2)
58 rg_f(lfd, " ulp_ln2=" as *u8); rg_n(lfd, u_ln2)
59 rg_f(lfd, " method=bisection gams=F(nonlinear-solve)" as *u8)
60 if ok == 1 { rg_f(lfd, " verdict=GREEN\n" as *u8) } else { rg_f(lfd, " verdict=RED\n" as *u8) }
61 sys_close(lfd)
62 }
63 rg_p(" froot_bad=" as *u8); rg_n(1, froot_bad)
64 rg_p(" ulp_sqrt2=" as *u8); rg_n(1, u_sqrt2)
65 rg_p(" ulp_ln2=" as *u8); rg_n(1, u_ln2)
66 if ok == 1 { rg_p(" ROOTFIND-GATE: GREEN (GAMS-F nonlinear-solve class opened: bisection, |f(root)|~0 + sqrt2/ln2 tight)\n" as *u8); sys_exit(0); return 0 }
67 rg_p(" ROOTFIND-GATE: RED (measured gap named)\n" as *u8)
68 sys_exit(1)
69 return 1
70}