code wiki / _hdl_build / _pe_f64tan.nx
_pe_f64tan.nx source
↩ module page · 156 lines · 5707 B
1// AUTHORED BY THE NISHI BUILDER (pattern: MATH_KERNEL / TAN) -- no Claude core logic.
2// All constants from the SOVEREIGN bigfloat spec (nx_mathspec_tan). v1 domain |x| < 2^20.
3// Accurate-table + double-double; exact tangent-number Taylor (no minimax).
4import "nx_syscalls.nx"
5import "nx_tier.nx"
6import "nx_f64.nx"
7import "nx_f64_div.nx"
8import "nx_f64_cvt.nx"
9const TN_SMASK: i64 = 0xFFFFFFFFF8000000
10func _tn_mul2(a: i64, b: i64, out: *i64) -> i64 {
11 let ah: i64 = a & TN_SMASK
12 let al: i64 = nx_f64_sub(a, ah)
13 let bh: i64 = b & TN_SMASK
14 let bl: i64 = nx_f64_sub(b, bh)
15 let p: i64 = nx_f64_mul(a, b)
16 var e: i64 = nx_f64_sub(nx_f64_mul(ah, bh), p)
17 e = nx_f64_add(e, nx_f64_mul(ah, bl))
18 e = nx_f64_add(e, nx_f64_mul(al, bh))
19 e = nx_f64_add(e, nx_f64_mul(al, bl))
20 out[0] = p
21 out[1] = e
22 return 0
23}
24func _tn_2sum(a: i64, b: i64, out: *i64) -> i64 {
25 let s: i64 = nx_f64_add(a, b)
26 let bv: i64 = nx_f64_sub(s, a)
27 let e: i64 = nx_f64_add(nx_f64_sub(a, nx_f64_sub(s, bv)), nx_f64_sub(b, bv))
28 out[0] = s
29 out[1] = e
30 return 0
31}
32func _tn_tab(tb: *i64) -> i64 {
33 tb[0] = 0
34 tb[1] = 4593671619917905920
35 tb[2] = 4598175219545276416
36 tb[3] = 4600427019358961664
37 tb[4] = 4602678819172646912
38 tb[5] = 4603804719079489536
39 tb[6] = 4604930618986332160
40 tb[7] = 0
41 tb[8] = 4593695223700591013
42 tb[9] = 4598271451042958422
43 tb[10] = 4600762565920553136
44 tb[11] = 4603095874924660554
45 tb[12] = 4604673773664476912
46 tb[13] = 4606566294485004012
47 tb[14] = 0
48 tb[15] = (0 - 4877474947179949392)
49 tb[16] = (0 - 4874646594127488451)
50 tb[17] = (0 - 4868978482769739392)
51 tb[18] = 4359702029082419721
52 tb[19] = (0 - 4859589607439340245)
53 tb[20] = (0 - 4868605643208884270)
54 tb[21] = 4607182418800017408
55 tb[22] = 4607253527095366650
56 tb[23] = 4607476051229208215
57 tb[24] = 4607880214998791302
58 tb[25] = 4608526501942727806
59 tb[26] = 4609526721642987662
60 tb[27] = 4611090966654505233
61 tb[28] = 0
62 tb[29] = (0 - 4858632800411268547)
63 tb[30] = (0 - 4857399076725437829)
64 tb[31] = 4357363442473848352
65 tb[32] = 4361246537643377741
66 tb[33] = 4366258138021095436
67 tb[34] = (0 - 4859648372893013672)
68 return 35
69}
70func _tn_core(ar: i64, art: i64, out: *i64) -> i64 {
71 let tk: i64 = nx_f64_add(nx_f64_mul(ar, 4620693217682128896), 4602678819172646912)
72 let j: i64 = nx_f64_to_i64(tk)
73 let tb: *i64 = sys_mmap(8 * 35) as *i64
74 _tn_tab(tb)
75 let d0: i64 = nx_f64_sub(ar, tb[j])
76 let dd: *i64 = sys_mmap(16) as *i64
77 _tn_2sum(d0, art, dd)
78 let dh: i64 = dd[0]
79 let dl: i64 = dd[1]
80 let z: i64 = nx_f64_mul(dh, dh)
81 var q: i64 = 4564356673986852323
82 q = nx_f64_add(nx_f64_mul(q, z), 4570429305847643616)
83 q = nx_f64_add(nx_f64_mul(q, z), 4576262929202463293)
84 q = nx_f64_add(nx_f64_mul(q, z), 4581960672315445498)
85 q = nx_f64_add(nx_f64_mul(q, z), 4587938466106554908)
86 q = nx_f64_add(nx_f64_mul(q, z), 4593971859893063953)
87 q = nx_f64_add(nx_f64_mul(q, z), 4599676419421066581)
88 let tcorr: i64 = nx_f64_add(nx_f64_mul(nx_f64_mul(dh, z), q), dl)
89 let tv: *i64 = sys_mmap(16) as *i64
90 _tn_2sum(dh, tcorr, tv)
91 let th: i64 = tv[0]
92 let tl: i64 = tv[1]
93 if j == 0 {
94 out[0] = th
95 out[1] = tl
96 return 0
97 }
98 let pr: *i64 = sys_mmap(16) as *i64
99 _tn_mul2(th, tb[21 + j], pr)
100 let n1: i64 = pr[0]
101 let n2: i64 = nx_f64_add(pr[1], nx_f64_add(nx_f64_mul(th, tb[28 + j]), nx_f64_mul(tl, tb[21 + j])))
102 _tn_mul2(tb[7 + j], th, pr)
103 let m1: i64 = pr[0]
104 let m2: i64 = nx_f64_add(pr[1], nx_f64_add(nx_f64_mul(tb[7 + j], tl), nx_f64_mul(tb[14 + j], th)))
105 let d1: i64 = nx_f64_sub(4607182418800017408, m1)
106 let d2f: i64 = m2 ^ (1 << 63)
107 let q0: i64 = nx_f64_div(n1, d1)
108 _tn_mul2(q0, d1, pr)
109 var e: i64 = nx_f64_sub(nx_f64_sub(n1, pr[0]), pr[1])
110 e = nx_f64_add(e, n2)
111 e = nx_f64_sub(e, nx_f64_mul(q0, d2f))
112 let ql: i64 = nx_f64_div(e, d1)
113 let sv: *i64 = sys_mmap(16) as *i64
114 _tn_2sum(tb[7 + j], q0, sv)
115 let vt: i64 = nx_f64_add(sv[1], nx_f64_add(tb[14 + j], ql))
116 _tn_2sum(sv[0], vt, sv)
117 out[0] = sv[0]
118 out[1] = sv[1]
119 return 0
120}
121func nx_f64_tan(x: i64) -> i64 {
122 let ax: i64 = x & 0x7FFFFFFFFFFFFFFF
123 let ef: i64 = (x >> 52) & 0x7FF
124 if ef == 2047 { return 0x7FF8000000000000 }
125 if ax == 0 { return x }
126 if ef >= 1043 { return 0x7FF8000000000000 }
127 let t8: i64 = nx_f64_mul(x, 4603909380684499075)
128 var tkr: i64 = 0
129 if ((t8 >> 63) & 1) == 1 { tkr = nx_f64_sub(t8, 4602678819172646912) } else { tkr = nx_f64_add(t8, 4602678819172646912) }
130 let k: i64 = nx_f64_to_i64(tkr)
131 let kf: i64 = nx_i64_to_f64(k)
132 let r1: i64 = nx_f64_sub(x, nx_f64_mul(kf, 4609753056924401664))
133 let r2: i64 = nx_f64_sub(r1, nx_f64_mul(kf, 4454258360616747008))
134 let w: i64 = nx_f64_mul(kf, 4297306550709743712)
135 let rh: i64 = nx_f64_sub(r2, w)
136 let rt: i64 = nx_f64_sub(nx_f64_sub(r2, rh), w)
137 let rs: i64 = (rh >> 63) & 1
138 let ar: i64 = rh & 0x7FFFFFFFFFFFFFFF
139 var art: i64 = rt
140 if rs == 1 { art = rt ^ (1 << 63) }
141 let v: *i64 = sys_mmap(16) as *i64
142 _tn_core(ar, art, v)
143 if (k & 1) == 0 {
144 let res: i64 = nx_f64_add(v[0], v[1])
145 if rs == 1 { return res ^ (1 << 63) }
146 return res
147 }
148 let q0: i64 = nx_f64_div(4607182418800017408, v[0])
149 let pr: *i64 = sys_mmap(16) as *i64
150 _tn_mul2(q0, v[0], pr)
151 var e2: i64 = nx_f64_sub(nx_f64_sub(4607182418800017408, pr[0]), pr[1])
152 e2 = nx_f64_sub(e2, nx_f64_mul(q0, v[1]))
153 let mag: i64 = nx_f64_add(q0, nx_f64_mul(q0, e2))
154 if rs == 1 { return mag }
155 return mag ^ (1 << 63)
156}