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}