code wiki / _hdl_build / _f64_tan_gate_authored.nx

_f64_tan_gate_authored.nx source

↩ module page · 129 lines · 5317 B

1// _f64_tan_gate_authored.nx -- ME1 tan gate: dd kernel (_pe_f64tan) vs the LIVE 2// sovereign bigfloat tan oracle. Pure Nishi end to end. 3// Edges: pole crossings at small k (fl(pi/2) +- ulp, 3pi/2, 5pi/2), anchor 4// seams (j/8 boundaries after reduction), tiny/subnormal, refusal band; plus 5// 320 banded xorshift points over |x| < 2^20. GREEN iff max ULP <= 1. 6// Markers: TNBAD x= exp= got= ulp= / TAN-ULP ... / TAN-GATE verdict=GREEN|RED 7 8import "nx_syscalls.nx" 9import "nx_f64.nx" 10import "nx_f64_div.nx" 11import "nx_f64_cvt.nx" 12import "nx_bigfloat120.nx" 13import "nx_bigfloat120_div.nx" 14import "nx_bigfloat120_trig.nx" 15import "nx_bigfloat120_tan.nx" 16import "_pm_tan_spec.nx" 17import "_pe_f64tan.nx" 18 19func tng_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 20func tng_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 } 21func tng_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 } 22 23func tng_rng(state: *i64) -> i64 { 24 var s: i64 = state[0] 25 s = s ^ ((s >> 12) & 0x000FFFFFFFFFFFFF) 26 s = s ^ (s << 25) 27 s = s ^ ((s >> 27) & 0x0000001FFFFFFFFF) 28 state[0] = s 29 return s * 2685821657736338717 30} 31 32func tng_ord(v: i64) -> i64 { 33 if v >= 0 { return v } 34 return (1 << 63) - v 35} 36 37func tng_ulp(got: i64, want: i64) -> i64 { 38 if got == want { return 0 } 39 var u: i64 = tng_ord(got) - tng_ord(want) 40 if u < 0 { u = 0 - u } 41 return u 42} 43 44func main() -> i64 { 45 let xs: *i64 = sys_mmap(8 * 512) as *i64 46 var n: i64 = 0 47 // specials + edges 48 xs[n] = 0x7FF8000000000000; n = n + 1 // NaN 49 xs[n] = 0x7FF0000000000000; n = n + 1 // inf 50 xs[n] = 0; n = n + 1 51 xs[n] = 1 << 63; n = n + 1 52 xs[n] = 1; n = n + 1 // min subnormal 53 xs[n] = 0x4140000000000000; n = n + 1 // 2^21: refused 54 xs[n] = 0x3FF921FB54442D18; n = n + 1 // fl(pi/2): pole-, huge + 55 xs[n] = 0x3FF921FB54442D19; n = n + 1 // pole+, huge - 56 xs[n] = 0x3FF921FB54442D17; n = n + 1 57 xs[n] = 0x4012D97C7F3321D2; n = n + 1 // ~3pi/2 58 xs[n] = 0x401F6A7A2955385E; n = n + 1 // ~5pi/2 59 xs[n] = 0x400921FB54442D18; n = n + 1 // ~pi (tan ~ -1.2e-16) 60 xs[n] = 0x401921FB54442D18; n = n + 1 // ~2pi 61 xs[n] = 0x3FE921FB54442D18; n = n + 1 // ~pi/4: tan ~ 1 62 xs[n] = 0xBFE921FB54442D18; n = n + 1 63 xs[n] = 0x3FC0000000000000; n = n + 1 // 1/8 anchor 64 xs[n] = 0x3FB0000000000000; n = n + 1 // 1/16 seam 65 xs[n] = 0x3FE8000000000000; n = n + 1 // 0.75 anchor 66 xs[n] = 0x3FF0000000000000; n = n + 1 // 1.0 (k=1, cot path) 67 xs[n] = 0x4000000000000000; n = n + 1 // 2.0 68 xs[n] = 0x3E50000000000000; n = n + 1 // 2^-26 69 xs[n] = 0x40F869F000000000; n = n + 1 // ~99999 70 // banded random over the v1 domain 71 let st: *i64 = sys_mmap(16) as *i64 72 st[0] = 11235813213455891442 73 var j: i64 = 0 74 while j < 320 { 75 var raw: i64 = tng_rng(st) 76 var efr: i64 = 0 77 let band: i64 = raw & 3 78 if band == 0 { efr = 1015 + (raw & 7) } // near 1 79 if band == 1 { efr = 1023 + (raw & 15) } // 1 .. 2^16 80 if band == 2 { efr = 950 + (raw & 63) } // small 81 if band == 3 { efr = 1033 + (raw & 7) } // 2^10 .. 2^17 82 raw = (efr << 52) | (tng_rng(st) & 0x000FFFFFFFFFFFFF) 83 if (tng_rng(st) & 1) == 1 { raw = raw | (1 << 63) } 84 xs[n] = raw 85 n = n + 1 86 j = j + 1 87 } 88 89 var t_exact: i64 = 0 90 var t_u1: i64 = 0 91 var t_worse: i64 = 0 92 var t_max: i64 = 0 93 var i: i64 = 0 94 while i < n { 95 let x: i64 = xs[i] 96 let tw: i64 = bf_tan_f64(x) 97 let tg: i64 = nx_f64_tan(x) 98 let tu: i64 = tng_ulp(tg, tw) 99 if tu == 0 { t_exact = t_exact + 1 } 100 if tu == 1 { t_u1 = t_u1 + 1 } 101 if tu > 1 { 102 t_worse = t_worse + 1 103 if t_worse <= 20 { 104 tng_puts("TNBAD x=" as *u8); tng_puthex(x) 105 tng_puts(" exp=" as *u8); tng_puthex(tw) 106 tng_puts(" got=" as *u8); tng_puthex(tg) 107 tng_puts(" ulp=" as *u8); tng_putn(tu) 108 tng_puts("\n" as *u8) 109 } 110 } 111 if tu > t_max { t_max = tu } 112 i = i + 1 113 } 114 115 tng_puts("TAN-ULP total=" as *u8); tng_putn(n) 116 tng_puts(" exact=" as *u8); tng_putn(t_exact) 117 tng_puts(" ulp1=" as *u8); tng_putn(t_u1) 118 tng_puts(" worse=" as *u8); tng_putn(t_worse) 119 tng_puts(" max=" as *u8); tng_putn(t_max) 120 tng_puts("\n" as *u8) 121 if t_worse == 0 { 122 tng_puts("TAN-GATE verdict=GREEN\n" as *u8) 123 return 0 124 } 125 tng_puts("TAN-GATE verdict=RED\n" as *u8) 126 var rc: i64 = t_worse 127 if rc > 100 { rc = 100 } 128 return rc 129}