code wiki / _hdl_build / _f64_igammaq_gate.nx
_f64_igammaq_gate.nx source
↩ module page · 105 lines · 4251 B
1// _f64_igammaq_gate.nx -- ULP gate for integer-order Q(n,x) vs a sovereign 120-bit
2// finite-sum oracle (same closed form computed in bigfloat; bfc_exp reused from the erfc
3// organ). Grid n=1..12, x=k/2 (0.5..12). Plus the closed-form rail Q(1,x)==e^(-x)
4// (bit-exact: the n=1 kernel IS e^(-x)). RUNG bar: max ULP <= 4.
5// Durable: IGAMMAQ-GATE -> knowledge/status/math_engine.log.
6// license_tier: ORIGINAL
7import "nx_syscalls.nx"
8import "nx_bigfloat120.nx"
9import "nx_bigfloat120_div.nx"
10import "nx_bigfloat120_erfc.nx"
11import "nx_f64_exp.nx"
12import "_pe_f64igammaq.nx"
13
14func iq_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
15func iq_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 }
16func iq_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 }
17func iq_ulp(a: i64, b: i64) -> i64 { if a >= b { return a - b } return b - a }
18
19// bigfloat Q(n,x) = e^(-x) * sum_{k=0}^{n-1} x^k/k! (the oracle)
20func iq_bf(out: *i64, n: i64, xb: *i64) -> i64 {
21 let term: *i64 = bf_new()
22 bf_set_int(term, 1)
23 let sum: *i64 = bf_new()
24 bf_copy(sum, term)
25 let t: *i64 = bf_new()
26 let snew: *i64 = bf_new()
27 var k: i64 = 1
28 while k < n {
29 bf_mul(t, term, xb)
30 bf_div_small(term, t, k)
31 bf_add(snew, sum, term)
32 bf_copy(sum, snew)
33 k = k + 1
34 }
35 let ex: *i64 = bf_new()
36 bfc_exp(ex, xb)
37 let one: *i64 = bf_new()
38 bf_set_int(one, 1)
39 let emx: *i64 = bf_new()
40 bf_div(emx, one, ex)
41 bf_mul(out, emx, sum)
42 return 0
43}
44
45func main() -> i64 {
46 iq_p("=== F64-IGAMMAQ GATE: integer-order Q(n,x) vs 120-bit finite-sum oracle ===\n" as *u8)
47 let kb: *i64 = bf_new()
48 let xb: *i64 = bf_new()
49 let oc: *i64 = bf_new()
50 var maxulp: i64 = 0
51 var worst_n: i64 = 0
52 var worst_x: i64 = 0
53 var npts: i64 = 0
54 var n: i64 = 1
55 while n <= 12 {
56 var kx: i64 = 1
57 while kx <= 24 {
58 bf_set_int(kb, kx)
59 bf_div_small(xb, kb, 2) // x = kx/2
60 let xbits: i64 = bf_to_f64(xb, 0, 0)
61 iq_bf(oc, n, xb)
62 let want: i64 = bf_to_f64(oc, 0, 0)
63 let got: i64 = nx_f64_igammaq(n, xbits)
64 let u: i64 = iq_ulp(got, want)
65 if u > maxulp { maxulp = u; worst_n = n; worst_x = xbits }
66 npts = npts + 1
67 kx = kx + 1
68 }
69 n = n + 1
70 }
71 // closed-form rail: Q(1,x) must equal e^(-x) bit-exactly at a few x
72 var rail_bad: i64 = 0
73 var rk: i64 = 1
74 while rk <= 10 {
75 bf_set_int(kb, rk)
76 bf_div_small(xb, kb, 2)
77 let xr: i64 = bf_to_f64(xb, 0, 0)
78 let q1: i64 = nx_f64_igammaq(1, xr)
79 let ex: i64 = nx_f64_exp(nx_f64_neg(xr))
80 if q1 != ex { rail_bad = rail_bad + 1 }
81 rk = rk + 1
82 }
83
84 var ok: i64 = 0
85 if maxulp <= 4 { if rail_bad == 0 { ok = 1 } }
86 let lfd: i64 = sys_openat_append("knowledge/status/math_engine.log" as *u8, 0x1a4)
87 if lfd >= 0 {
88 iq_f(lfd, "IGAMMAQ-GATE epoch=" as *u8); iq_n(lfd, sys_now_realtime_sec())
89 iq_f(lfd, " points=" as *u8); iq_n(lfd, npts)
90 iq_f(lfd, " max_ulp=" as *u8); iq_n(lfd, maxulp)
91 iq_f(lfd, " worst_n=" as *u8); iq_n(lfd, worst_n)
92 iq_f(lfd, " worst_x_bits=" as *u8); iq_n(lfd, worst_x)
93 iq_f(lfd, " q1_rail_bad=" as *u8); iq_n(lfd, rail_bad)
94 iq_f(lfd, " dlmf=ch8 form=closed-finite-sum oracle=120bit(SOVEREIGN)" as *u8)
95 if ok == 1 { iq_f(lfd, " verdict=GREEN\n" as *u8) } else { iq_f(lfd, " verdict=RED\n" as *u8) }
96 sys_close(lfd)
97 }
98 iq_p(" points=" as *u8); iq_n(1, npts)
99 iq_p(" max_ulp=" as *u8); iq_n(1, maxulp)
100 iq_p(" q1_rail_bad=" as *u8); iq_n(1, rail_bad)
101 if ok == 1 { iq_p(" IGAMMAQ-GATE: GREEN (integer-order incomplete gamma <=4 ulp + Q(1,x)=e^-x rail)\n" as *u8); sys_exit(0); return 0 }
102 iq_p(" IGAMMAQ-GATE: RED (measured gap named)\n" as *u8)
103 sys_exit(1)
104 return 1
105}