code wiki / _hdl_build / _bf_atan_gate_authored.nx
_bf_atan_gate_authored.nx source
↩ module page · 160 lines · 6537 B
1// _bf_atan_gate_authored.nx -- self-anchor gate for the SOVEREIGN bigfloat atan
2// oracle (nx_bigfloat120_atan). No external oracle anywhere:
3// 1. MACHIN: 16*atan01(1/5) - 4*atan01(1/239) through the GENERAL reduction
4// path must reproduce bf_pi to < 2^-108.
5// 2. TAN-ROUNDTRIP: tan(atan(x)) = x at 200 banded-random f64 points in
6// (0,1) + fixed boundary points, tan from the BLESSED bf_sin_r/bf_cos_r
7// organ (itself anchored by Machin-vs-Gauss + sin^2+cos^2), rel < 2^-100.
8// 3. f64 specials: NaN, +-0, +-inf -> +-fl(pi/2), oddness, monotone
9// continuity across x = 1 (branch seam) and x = 1/8 (Taylor seam).
10// Markers: BFATAN-MACHIN / BFATAN-TAN / BFATAN-SPEC / BFATAN-GATE verdict=
11
12import "nx_syscalls.nx"
13import "nx_bigfloat120.nx"
14import "nx_bigfloat120_div.nx"
15import "nx_bigfloat120_trig.nx"
16import "nx_bigfloat120_atan.nx"
17
18func bag_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
19func bag_putn(v: i64) -> i64 { let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) }; let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48; k = 1 }; while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 }; var i: i64 = 0; while i < k { bb[i] = t[k-1-i]; i = i + 1 }; sys_write(1, bb, k); return 0 }
20func bag_puthex(v: i64) -> i64 { let bb: *u8 = sys_mmap(20); var i: i64 = 0; while i < 16 { let nib: i64 = (v >> ((15 - i) * 4)) & 15; if nib < 10 { bb[i] = 48 + nib } else { bb[i] = 55 + nib } i = i + 1 } sys_write(1, bb, 16); return 0 }
21
22func bag_rng(state: *i64) -> i64 {
23 var s: i64 = state[0]
24 s = s ^ ((s >> 12) & 0x000FFFFFFFFFFFFF)
25 s = s ^ (s << 25)
26 s = s ^ ((s >> 27) & 0x0000001FFFFFFFFF)
27 state[0] = s
28 return s * 2685821657736338717
29}
30
31// 1 iff |a - b| < 2^-bits relative to b (exponent compare on the bigfloat)
32func bag_relok(a: *i64, b: *i64, bits: i64) -> i64 {
33 let d: *i64 = bf_new()
34 if bf_cmp(a, b) >= 0 { bf_sub(d, a, b) } else { bf_sub(d, b, a) }
35 if bf_is_zero(d) == 1 { return 1 }
36 if d[0] <= b[0] - bits { return 1 }
37 return 0
38}
39
40// tan(atan01(xb)) == xb to < 2^-100 relative; xb in (0, 1)
41func bag_tan_rt(xb: *i64) -> i64 {
42 let th: *i64 = bf_new()
43 bf_atan01(th, xb) // th <= pi/4: bf_sin_r domain
44 let sv: *i64 = bf_new()
45 let cv: *i64 = bf_new()
46 bf_sin_r(sv, th)
47 bf_cos_r(cv, th)
48 let tn: *i64 = bf_new()
49 bf_div(tn, sv, cv)
50 return bag_relok(tn, xb, 100)
51}
52
53func main() -> i64 {
54 var bad: i64 = 0
55
56 // ---- 1. Machin recombination through the GENERAL path ----
57 let one: *i64 = bf_new()
58 bf_set_int(one, 1)
59 let x5: *i64 = bf_new()
60 bf_div_small(x5, one, 5)
61 let a5: *i64 = bf_new()
62 bf_atan01(a5, x5)
63 a5[0] = a5[0] + 4 // * 16
64 let x239: *i64 = bf_new()
65 bf_div_small(x239, one, 239)
66 let a239: *i64 = bf_new()
67 bf_atan01(a239, x239)
68 a239[0] = a239[0] + 2 // * 4
69 let mp: *i64 = bf_new()
70 bf_sub(mp, a5, a239)
71 let pi: *i64 = bf_new()
72 bf_pi(pi)
73 if bag_relok(mp, pi, 108) == 1 {
74 bag_puts("BFATAN-MACHIN ok rel<2^-108\n" as *u8)
75 } else {
76 bad = bad + 1
77 bag_puts("BFATAN-MACHIN BAD\n" as *u8)
78 }
79
80 // ---- 2. tan(atan(x)) = x, 200 banded random + boundary-seam points ----
81 let xs: *i64 = sys_mmap(8 * 256) as *i64
82 var n: i64 = 0
83 xs[n] = 0x3FEFFFFFFFFFFFFF; n = n + 1 // just below 1 (theta -> pi/4)
84 xs[n] = 0x3FC0000000000000; n = n + 1 // exactly 1/8 (Taylor seam)
85 xs[n] = 0x3FC0000000000001; n = n + 1 // just above 1/8 (1 reduction)
86 xs[n] = 0x3FE6666666666666; n = n + 1 // ~0.7 (n=2 round)
87 xs[n] = 0x3FD3333333333333; n = n + 1 // ~0.3 (n=3/4 round)
88 xs[n] = 0x3E70000000000000; n = n + 1 // 2^-24 (deep Taylor)
89 let st: *i64 = sys_mmap(16) as *i64
90 st[0] = 2718281828459045235
91 var j: i64 = 0
92 while j < 200 {
93 var raw: i64 = bag_rng(st)
94 var efr: i64 = 0
95 let band: i64 = raw & 3
96 if band == 0 { efr = 1022 } // [0.5, 1)
97 if band == 1 { efr = 1018 + (raw & 3) } // 2^-5 .. 2^-1
98 if band == 2 { efr = 1010 + (raw & 7) } // 2^-13 .. 2^-5
99 if band == 3 { efr = 992 + (raw & 31) } // 2^-31 .. 2^0
100 if efr > 1022 { efr = 1022 }
101 raw = (efr << 52) | (bag_rng(st) & 0x000FFFFFFFFFFFFF)
102 xs[n] = raw
103 n = n + 1
104 j = j + 1
105 }
106 var tbad: i64 = 0
107 var i: i64 = 0
108 while i < n {
109 let xb: *i64 = bf_new()
110 bf_set_f64(xb, xs[i])
111 if bag_tan_rt(xb) == 0 {
112 tbad = tbad + 1
113 if tbad <= 10 {
114 bag_puts("BFATAN-TANBAD x=" as *u8); bag_puthex(xs[i]); bag_puts("\n" as *u8)
115 }
116 }
117 i = i + 1
118 }
119 bag_puts("BFATAN-TAN total=" as *u8); bag_putn(n)
120 bag_puts(" bad=" as *u8); bag_putn(tbad)
121 bag_puts(" bar=rel<2^-100\n" as *u8)
122 bad = bad + tbad
123
124 // ---- 3. f64 specials + seam monotonicity ----
125 var sbad: i64 = 0
126 if bf_atan_f64(0x7FF8000000000000) != 0x7FF8000000000000 { sbad = sbad + 1 }
127 if bf_atan_f64(0) != 0 { sbad = sbad + 1 }
128 if bf_atan_f64(1 << 63) != (1 << 63) { sbad = sbad + 1 }
129 let p2: *i64 = bf_new()
130 bf_pi(p2)
131 p2[0] = p2[0] - 1
132 let pio2f: i64 = bf_to_f64(p2, 0, 0)
133 if bf_atan_f64(0x7FF0000000000000) != pio2f { sbad = sbad + 1 }
134 if bf_atan_f64(0xFFF0000000000000) != (pio2f | (1 << 63)) { sbad = sbad + 1 }
135 // oddness at a random-ish point
136 let podd: i64 = bf_atan_f64(0x3FE921FB54442D18)
137 let nodd: i64 = bf_atan_f64(0xBFE921FB54442D18)
138 if nodd != (podd | (1 << 63)) { sbad = sbad + 1 }
139 // monotone continuity across the x = 1 branch seam
140 let v0: i64 = bf_atan_f64(0x3FEFFFFFFFFFFFFF)
141 let v1: i64 = bf_atan_f64(0x3FF0000000000000)
142 let v2: i64 = bf_atan_f64(0x3FF0000000000001)
143 if v0 > v1 { sbad = sbad + 1 }
144 if v1 > v2 { sbad = sbad + 1 }
145 if v1 - v0 > 2 { sbad = sbad + 1 }
146 if v2 - v1 > 2 { sbad = sbad + 1 }
147 // huge finite below pi/2-rounding, monotone to inf
148 let vh: i64 = bf_atan_f64(0x7FE0000000000000)
149 if vh > pio2f { sbad = sbad + 1 }
150 bag_puts("BFATAN-SPEC bad=" as *u8); bag_putn(sbad); bag_puts("\n" as *u8)
151 bad = bad + sbad
152
153 if bad == 0 {
154 bag_puts("BFATAN-GATE verdict=GREEN\n" as *u8)
155 return 0
156 }
157 bag_puts("BFATAN-GATE verdict=RED\n" as *u8)
158 if bad > 100 { bad = 100 }
159 return bad
160}