nx_bigfloat120_tan.nx source
↩ module page · 58 lines · 2383 B
1// nx_bigfloat120_tan.nx -- SOVEREIGN tan oracle on the 120-bit bigfloat:
2// tan = sin/cos over the blessed trig organ's reduction (period pi handled by
3// the quadrant parity: k odd -> -cot). Positive-only core; the bigfloat entry
4// point bf_tan_xb takes an UNROUNDED bigfloat argument so the self-anchor gate
5// can test algebraic identities (half-angle, pi-shift) at full precision across
6// DIFFERENT reduction paths -- not just at f64-rounded points.
7// v1 domain |x| < 2^20 (the trig organ's Cody-Waite range; same honest refusal).
8// Near poles: r >= ~2^-61 for any f64 near k*pi/2, so cot = cos/sin stays a
9// well-conditioned bigfloat division (no overflow band in f64 tan).
10// license_tier: ORIGINAL
11
12import "nx_syscalls.nx"
13import "nx_tier.nx"
14import "nx_bigfloat120.nx"
15import "nx_bigfloat120_div.nx"
16import "nx_bigfloat120_trig.nx"
17const K_MAGIC_2047: i64 = 2047
18const K_MAGIC_1043: i64 = 1043
19
20// tan(|xb|) for positive bigfloat xb < 2^20: writes |tan| to mag, returns the
21// sign bit of tan(xb) (0/1). Zero xb -> mag zero, sign 0.
22func bf_tan_xb(mag: *i64, xb: *i64) -> i64 {
23 if bf_is_zero(xb) == 1 { return bf_copy(mag, xb) }
24 let r: *i64 = bf_new()
25 let kq: *i64 = sys_mmap(16) as *i64
26 _bf_trig_reduce(r, kq, xb)
27 let sv: *i64 = bf_new()
28 let cv: *i64 = bf_new()
29 bf_sin_r(sv, r)
30 bf_cos_r(cv, r)
31 let kk: i64 = kq[0] & 1 // tan has period pi
32 let rneg: i64 = kq[1]
33 if kk == 0 {
34 // tan(k*pi + t), t = +-r: tan(t) = +-tan(r)
35 if bf_is_zero(sv) == 1 { return bf_copy(mag, sv) }
36 bf_div(mag, sv, cv)
37 return rneg
38 }
39 // tan(k*pi + pi/2 + t) = -cot(t): t = +r -> sign 1; t = -r -> sign 0
40 bf_div(mag, cv, sv)
41 return 1 - rneg
42}
43
44// tan(raw f64) -> f64 bit pattern (|x| < 2^20; NaN past that = honest refusal)
45func bf_tan_f64(x: i64) -> i64 {
46 let ax: i64 = x & 0x7FFFFFFFFFFFFFFF
47 let ef: i64 = (x >> 52) & 0x7FF
48 let sgn: i64 = (x >> 63) & 1
49 if ef == K_MAGIC_2047 { return 0x7FF8000000000000 }
50 if ax == 0 { return x } // tan(+-0) = +-0
51 if ef >= K_MAGIC_1043 { return 0x7FF8000000000000 } // |x| >= 2^20: refused v1
52 let xb: *i64 = bf_new()
53 bf_set_f64(xb, ax)
54 let mag: *i64 = bf_new()
55 var s: i64 = bf_tan_xb(mag, xb)
56 if sgn == 1 { s = 1 - s } // tan odd
57 return bf_to_f64(mag, s, 0)
58}