code wiki / _hdl_build / nx_pattern_emit6_erf.nx

nx_pattern_emit6_erf.nx source

↩ module page · 95 lines · 6460 B

1// nx_pattern_emit6_erf.nx -- PATTERN EMITTER: MATH_KERNEL / ERF_TAYLOR (DLMF ch7 rung 1, 2// ME2-ERF-001). The Builder authors f64 erf from the SOVEREIGN spec (nx_mathspec_erf: 3// bf_pi + Newton sqrt, rails held bit-exact vs known-good). The emitter contains 4// STRUCTURE only -- every number written into the module comes from the spec table c[]. 5// kernel: specials (NaN/+-0 sign-preserved/+-Inf->+-1) -> integer-compare domain cuts 6// on |x| bits (positive f64 ordering): |x|>=c[37] (6.0) -> +-1 sub-ulp; |x|>c[36] 7// (1.75) -> NAN_RAW = the RUNG-1 HONEST GAP (erfc route = ME2-ERF-002, named debt; 8// a wrong number is worse than a loud gap) -> else 32-term signed Horner in z=x*x 9// (plain f64, the ch4 core gene) -> EXACT two-product x*p (_er_mul2 27-bit-split dd) 10// -> dd scale by 2/sqrt(pi) (full-bits product + lo-residual tail recombine). 11// Antisymmetry erf(-x) = -erf(x) is BIT-EXACT by construction (odd path only). 12// The emitted test checks ALGORITHM INVARIANTS (specials/cuts/antisymmetry) -- the 13// semantic ULP bar is the Engineer's separate bf-oracle gate (_bf_erf_gate, next). 14// license_tier: ORIGINAL 15import "nx_pattern_emit.nx" 16import "nx_syscalls.nx" 17 18func pe6e_wlit(fd: i64, v: i64) -> i64 { 19 if v < 0 { 20 pe_w(fd, "0 - " as *u8) 21 pe_wn(fd, 0 - v) 22 return 0 23 } 24 pe_wn(fd, v) 25 return 0 26} 27 28func pe6e_mod_head(mf: i64) -> i64 { 29 pe_w(mf, "// AUTHORED BY THE NISHI BUILDER (pattern: MATH_KERNEL / ERF_TAYLOR) -- no Claude core logic.\n" as *u8) 30 pe_w(mf, "// All constants from the SOVEREIGN bigfloat spec (nx_mathspec_erf; rails R1+R2 held).\n" as *u8) 31 pe_w(mf, "// Rung-1 domain: |x|<=1.75 series; |x|>=6 exact +-1; gap = LOUD NAN (ME2-ERF-002 erfc).\n" as *u8) 32 pe_w(mf, "import \"nx_syscalls.nx\"\nimport \"nx_tier.nx\"\nimport \"nx_f64.nx\"\nimport \"nx_f64_div.nx\"\nimport \"nx_f64_cvt.nx\"\n" as *u8) 33 pe_w(mf, "const ER_SMASK: i64 = 0xFFFFFFFFF8000000\n" as *u8) 34 pe_w(mf, "func _er_mul2(a: i64, b: i64, out: *i64) -> i64 {\n" as *u8) 35 pe_w(mf, " let ah: i64 = a & ER_SMASK\n let al: i64 = nx_f64_sub(a, ah)\n" as *u8) 36 pe_w(mf, " let bh: i64 = b & ER_SMASK\n let bl: i64 = nx_f64_sub(b, bh)\n" as *u8) 37 pe_w(mf, " let p: i64 = nx_f64_mul(a, b)\n" as *u8) 38 pe_w(mf, " var e: i64 = nx_f64_sub(nx_f64_mul(ah, bh), p)\n" as *u8) 39 pe_w(mf, " e = nx_f64_add(e, nx_f64_mul(ah, bl))\n" as *u8) 40 pe_w(mf, " e = nx_f64_add(e, nx_f64_mul(al, bh))\n" as *u8) 41 pe_w(mf, " e = nx_f64_add(e, nx_f64_mul(al, bl))\n" as *u8) 42 pe_w(mf, " out[0] = p\n out[1] = e\n return 0\n}\n" as *u8) 43 return 0 44} 45 46func pe6_author_erf(modfile: *u8, modpath: *u8, testpath: *u8, c: *i64) -> i64 { 47 let mf: i64 = sys_openat_wr(modpath, 0x1a4); if mf < 0 { return 0 } 48 pe6e_mod_head(mf) 49 pe_w(mf, "func nx_f64_erf(x: i64) -> i64 {\n" as *u8) 50 pe_w(mf, " let cls: nx_int = nx_f64_classify(x)\n" as *u8) 51 pe_w(mf, " if cls == NX_F64_CLS_NAN { return NX_F64_NAN_RAW }\n" as *u8) 52 pe_w(mf, " if cls == NX_F64_CLS_ZERO { return x }\n" as *u8) 53 pe_w(mf, " let sgn: i64 = x & (1 << 63)\n" as *u8) 54 pe_w(mf, " let ax: i64 = x & 0x7FFFFFFFFFFFFFFF\n" as *u8) 55 pe_w(mf, " if cls == NX_F64_CLS_INF { return sgn | " as *u8); pe6e_wlit(mf, c[0]); pe_w(mf, " }\n" as *u8) 56 pe_w(mf, " if ax >= " as *u8); pe6e_wlit(mf, c[37]); pe_w(mf, " { return sgn | " as *u8); pe6e_wlit(mf, c[0]); pe_w(mf, " }\n" as *u8) 57 pe_w(mf, " if ax > " as *u8); pe6e_wlit(mf, c[36]); pe_w(mf, " { return NX_F64_NAN_RAW }\n" as *u8) 58 pe_w(mf, " let z: i64 = nx_f64_mul(x, x)\n" as *u8) 59 pe_w(mf, " var p: i64 = " as *u8); pe6e_wlit(mf, c[4]); pe_w(mf, "\n" as *u8) 60 var i: i64 = 5 61 while i <= 35 { 62 pe_w(mf, " p = nx_f64_add(nx_f64_mul(p, z), " as *u8); pe6e_wlit(mf, c[i]); pe_w(mf, ")\n" as *u8) 63 i = i + 1 64 } 65 pe_w(mf, " let sv: *i64 = sys_mmap(16) as *i64\n" as *u8) 66 pe_w(mf, " _er_mul2(x, p, sv)\n" as *u8) 67 pe_w(mf, " let pv: *i64 = sys_mmap(16) as *i64\n" as *u8) 68 pe_w(mf, " _er_mul2(sv[0], " as *u8); pe6e_wlit(mf, c[1]); pe_w(mf, ", pv)\n" as *u8) 69 pe_w(mf, " let tail: i64 = nx_f64_add(pv[1], nx_f64_mul(sv[1], " as *u8); pe6e_wlit(mf, c[1]); pe_w(mf, "))\n" as *u8) 70 pe_w(mf, " return nx_f64_add(pv[0], tail)\n}\n" as *u8) 71 sys_close(mf) 72 // ---- the emitted INVARIANT test (specials/cuts/antisymmetry; ULP = separate gate) ---- 73 let tf: i64 = sys_openat_wr(testpath, 0x1a4); if tf < 0 { return 0 } 74 pe_w(tf, "// GENERATED invariant KATs for the Builder-authored erf (ERF_TAYLOR).\n" as *u8) 75 pe_w(tf, "import \"" as *u8); pe_w(tf, modfile); pe_w(tf, "\"\n" as *u8) 76 pe_w(tf, "func main() -> i64 {\n var bad: i64 = 0\n" as *u8) 77 pe_w(tf, " if nx_f64_erf(0x7FF8000000000000) != NX_F64_NAN_RAW { bad = bad + 1 }\n" as *u8) 78 pe_w(tf, " if nx_f64_erf(0) != 0 { bad = bad + 1 }\n" as *u8) 79 pe_w(tf, " if nx_f64_erf(0x8000000000000000) != 0x8000000000000000 { bad = bad + 1 }\n" as *u8) 80 pe_w(tf, " if nx_f64_erf(0x7FF0000000000000) != " as *u8); pe6e_wlit(tf, c[0]); pe_w(tf, " { bad = bad + 1 }\n" as *u8) 81 pe_w(tf, " if nx_f64_erf(0xFFF0000000000000) != (" as *u8); pe6e_wlit(tf, c[0]); pe_w(tf, " | (1 << 63)) { bad = bad + 1 }\n" as *u8) 82 pe_w(tf, " if nx_f64_erf(0x4020000000000000) != " as *u8); pe6e_wlit(tf, c[0]); pe_w(tf, " { bad = bad + 1 }\n" as *u8) 83 pe_w(tf, " if nx_f64_erf(0x4000000000000000) != NX_F64_NAN_RAW { bad = bad + 1 }\n" as *u8) 84 pe_w(tf, " if nx_f64_erf(" as *u8); pe6e_wlit(tf, c[36]); pe_w(tf, ") == NX_F64_NAN_RAW { bad = bad + 1 }\n" as *u8) 85 pe_w(tf, " let h: i64 = nx_f64_erf(0x3FE0000000000000)\n" as *u8) 86 pe_w(tf, " if nx_f64_erf(0xBFE0000000000000) != (h | (1 << 63)) { bad = bad + 1 }\n" as *u8) 87 pe_w(tf, " let o: i64 = nx_f64_erf(0x3FF0000000000000)\n" as *u8) 88 pe_w(tf, " if nx_f64_erf(0xBFF0000000000000) != (o | (1 << 63)) { bad = bad + 1 }\n" as *u8) 89 pe_w(tf, " if (h & 0x7FFFFFFFFFFFFFFF) >= " as *u8); pe6e_wlit(tf, c[0]); pe_w(tf, " { bad = bad + 1 }\n" as *u8) 90 pe_w(tf, " if (o & 0x7FFFFFFFFFFFFFFF) >= " as *u8); pe6e_wlit(tf, c[0]); pe_w(tf, " { bad = bad + 1 }\n" as *u8) 91 pe_w(tf, " if (o & 0x7FFFFFFFFFFFFFFF) <= (h & 0x7FFFFFFFFFFFFFFF) { bad = bad + 1 }\n" as *u8) 92 pe_w(tf, " sys_exit(bad)\n return bad\n}\n" as *u8) 93 sys_close(tf) 94 return 1 95}