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}