code wiki / _hdl_build / nx_mathspec_sincos.nx
nx_mathspec_sincos.nx source
↩ module page · 117 lines · 4076 B
1// nx_mathspec_sincos.nx -- SOVEREIGN SPEC EMITTER (the role python generators held,
2// now a team organ): computes every SINCOS kernel constant on the 120-bit bigfloat
3// and writes the _pm_sin_spec.nx data module the MATH_KERNEL emitter consumes.
4// - 2/pi (f64)
5// - 3-part pi/2 split: HI/MID keep 32 effective mantissa bits (low 21 zeroed) so
6// k*HI and k*MID are EXACT for |k| <= 2^21; LO = f64 remainder.
7// - sin coeffs (-1)^k/(2k+1)!, k=0..9 and cos coeffs (-1)^k/(2k)!, k=0..9
8// NEGATIVE literals are emitted in `0 - N` form (unary-minus literal landmine).
9// Layout: c[0]=2/pi c[1]=HI c[2]=MID c[3]=LO c[4]=half c[5]=one
10// c[6..15] sin coeffs HI-FIRST (a9..a0) c[16..25] cos coeffs HI-FIRST
11// license_tier: ORIGINAL
12import "nx_syscalls.nx"
13import "nx_pattern_emit.nx"
14import "nx_bigfloat120.nx"
15import "nx_bigfloat120_div.nx"
16import "nx_bigfloat120_trig.nx"
17
18// write v as a valid NishiLang i64 literal (0 - N form when negative)
19func msc_wlit(fd: i64, v: i64) -> i64 {
20 if v < 0 {
21 pe_w(fd, "0 - " as *u8)
22 pe_wn(fd, 0 - v)
23 return 0
24 }
25 pe_wn(fd, v)
26 return 0
27}
28
29func msc_emit_row(fd: i64, idx: i64, v: i64) -> i64 {
30 pe_w(fd, " c[" as *u8); pe_wn(fd, idx); pe_w(fd, "] = " as *u8)
31 msc_wlit(fd, v)
32 pe_w(fd, "\n" as *u8)
33 return 0
34}
35
36func main() -> i64 {
37 let pi: *i64 = bf_new()
38 bf_pi(pi)
39 let pio2: *i64 = bf_new()
40 bf_copy(pio2, pi)
41 pio2[0] = pio2[0] - 1
42 let two: *i64 = bf_new()
43 bf_set_int(two, 2)
44 let topi: *i64 = bf_new()
45 bf_div(topi, two, pi)
46 let m21: i64 = (1 << 21) - 1
47
48 // 3-part split
49 let hi_bits: i64 = bf_to_f64(pio2, 0, 0) & (0 - 1 - m21) // zero low 21 mantissa bits
50 let hib: *i64 = bf_new()
51 bf_set_f64(hib, hi_bits)
52 let rem1: *i64 = bf_new()
53 bf_sub(rem1, pio2, hib)
54 let mid_bits: i64 = bf_to_f64(rem1, 0, 0) & (0 - 1 - m21)
55 let midb: *i64 = bf_new()
56 bf_set_f64(midb, mid_bits)
57 let rem2: *i64 = bf_new()
58 bf_sub(rem2, rem1, midb)
59 let lo_bits: i64 = bf_to_f64(rem2, 0, 0)
60
61 let fd: i64 = sys_openat_wr("runtime/_hdl_build/_pm_sin_spec.nx" as *u8, 0x1a4)
62 if fd < 0 { sys_exit(2) }
63 pe_w(fd, "// _pm_sin_spec.nx -- GENERATED by nx_mathspec_sincos (SOVEREIGN bigfloat,\n" as *u8)
64 pe_w(fd, "// no python). DO NOT HAND-EDIT. Layout: see nx_mathspec_sincos.nx header.\n" as *u8)
65 pe_w(fd, "import \"nx_syscalls.nx\"\n\nfunc pm_sin_spec_fill(c: *i64) -> i64 {\n" as *u8)
66 msc_emit_row(fd, 0, bf_to_f64(topi, 0, 0))
67 msc_emit_row(fd, 1, hi_bits)
68 msc_emit_row(fd, 2, mid_bits)
69 msc_emit_row(fd, 3, lo_bits)
70 let one: *i64 = bf_new()
71 bf_set_int(one, 1)
72 let half: *i64 = bf_new()
73 bf_copy(half, one)
74 half[0] = half[0] - 1
75 msc_emit_row(fd, 4, bf_to_f64(half, 0, 0))
76 msc_emit_row(fd, 5, bf_to_f64(one, 0, 0))
77
78 // sin coeffs a_k = (-1)^k / (2k+1)! -- compute a0..a9, emit hi-first
79 let av: *i64 = sys_mmap(8 * 12) as *i64
80 let cur: *i64 = bf_new()
81 bf_copy(cur, one)
82 av[0] = bf_to_f64(cur, 0, 0)
83 var k: i64 = 1
84 let nxt: *i64 = bf_new()
85 while k <= 9 {
86 bf_div_small(nxt, cur, (2 * k) * (2 * k + 1))
87 bf_copy(cur, nxt)
88 var bits: i64 = bf_to_f64(cur, 0, 0)
89 if (k & 1) == 1 { bits = bits | (1 << 63) }
90 av[k] = bits
91 k = k + 1
92 }
93 var i: i64 = 0
94 while i < 10 { msc_emit_row(fd, 6 + i, av[9 - i]); i = i + 1 }
95
96 // cos coeffs b_k = (-1)^k / (2k)!
97 let bv: *i64 = sys_mmap(8 * 12) as *i64
98 bf_copy(cur, one)
99 bv[0] = bf_to_f64(cur, 0, 0)
100 k = 1
101 while k <= 9 {
102 bf_div_small(nxt, cur, (2 * k - 1) * (2 * k))
103 bf_copy(cur, nxt)
104 var bits2: i64 = bf_to_f64(cur, 0, 0)
105 if (k & 1) == 1 { bits2 = bits2 | (1 << 63) }
106 bv[k] = bits2
107 k = k + 1
108 }
109 i = 0
110 while i < 10 { msc_emit_row(fd, 16 + i, bv[9 - i]); i = i + 1 }
111
112 pe_w(fd, " return 26\n}\n" as *u8)
113 sys_close(fd)
114 pe_w(1, "SPEC EMITTED: _pm_sin_spec.nx (26 consts, all from sovereign bigfloat)\n" as *u8)
115 sys_exit(0)
116 return 0
117}