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}