code wiki / _hdl_build / _f64_erf_gate_authored.nx

_f64_erf_gate_authored.nx source

↩ module page · 132 lines · 5762 B

1// _f64_erf_gate_authored.nx -- f64 EDGE gate for the Builder-authored erf (component 5). 2// Complements the bf oracle gate (semantics) with IEEE edge discipline: 3// E1 denormal in -> finite, sign-preserved, non-NaN (series path: x*p well-defined) 4// E2 monotone non-decreasing over 0.5..1.75 step 1/256 (no Horner wiggle at the top) 5// E3 gap contract: first bits ABOVE the 1.75 cut -> NAN_RAW (loud, never wrong-number) 6// E4 result strictly < 1.0 inside the series domain (erf(1.75)=0.98667...) 7// E5 SEMANTIC ANCHORS (the tamper judge's teeth -- RUNGRUN re-runs THIS gate after 8// flipping a kernel literal, so edge checks alone are blind to coefficient/scale 9// flips that preserve monotonicity): 8-point bf-oracle ULP<=4 at x=k/8, k=1..8, 10// with 2/sqrt(pi) re-derived INDEPENDENTLY (judge diversity, not shared spec). 11// Durable: F64ERF row -> knowledge/status/math_engine.log. Exit 0 iff all held. 12// license_tier: ORIGINAL 13import "nx_syscalls.nx" 14import "nx_bigfloat120.nx" 15import "nx_bigfloat120_div.nx" 16import "nx_bigfloat120_trig.nx" 17import "_pe_f64erf.nx" 18func fg_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 19func fg_f(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 20func fg_n(fd: i64, v: i64) -> i64 { let bb: *u8=sys_mmap(28); var m: i64=v; if m<0{m=0-m; sys_write(fd,"-" as *u8,1)}; let t: *u8=sys_mmap(28); var k: i64=0; if m==0{t[0]=48 as u8;k=1}; while m>0{t[k]=(48+(m%10)) as u8;m=m/10;k=k+1}; var i: i64=0; while i<k{bb[i]=t[k-1-i];i=i+1}; sys_write(fd,bb,k); return 0 } 21func fg_sqrt(out: *i64, a: *i64, seed_raw: i64) -> i64 { 22 let s: *i64 = bf_new() 23 bf_set_f64(s, seed_raw) 24 let q: *i64 = bf_new() 25 let sum: *i64 = bf_new() 26 var i: i64 = 0 27 while i < 8 { 28 bf_div(q, a, s) 29 bf_add(sum, s, q) 30 bf_div_small(s, sum, 2) 31 i = i + 1 32 } 33 return bf_copy(out, s) 34} 35func fg_oracle(xbits: i64, tosp: *i64) -> i64 { 36 let x: *i64 = bf_new() 37 bf_set_f64(x, xbits) 38 let x2: *i64 = bf_new() 39 bf_mul(x2, x, x) 40 let u: *i64 = bf_new() 41 bf_copy(u, x) 42 let pos: *i64 = bf_new() 43 bf_copy(pos, x) 44 let neg: *i64 = bf_new() 45 bf_set_int(neg, 0) 46 let t: *i64 = bf_new() 47 let term: *i64 = bf_new() 48 let acc: *i64 = bf_new() 49 var n: i64 = 1 50 while n <= 44 { 51 bf_mul(t, u, x2) 52 bf_div_small(u, t, n) 53 bf_div_small(term, u, 2 * n + 1) 54 if (n & 1) == 1 { bf_add(acc, neg, term); bf_copy(neg, acc) } else { bf_add(acc, pos, term); bf_copy(pos, acc) } 55 n = n + 1 56 } 57 let dif: *i64 = bf_new() 58 if bf_cmp(pos, neg) >= 0 { bf_sub(dif, pos, neg) } else { bf_sub(dif, neg, pos) } 59 let r: *i64 = bf_new() 60 bf_mul(r, dif, tosp) 61 return bf_to_f64(r, 0, 0) 62} 63func main() -> i64 { 64 fg_p("=== F64-ERF EDGE GATE: denormals, monotonicity, gap contract, semantic anchors ===\n" as *u8) 65 var bad: i64 = 0 66 // E1 denormals (positive + negative smallest and a mid-denormal) 67 let d1: i64 = nx_f64_erf(1) 68 if d1 == NX_F64_NAN_RAW { bad = bad + 1 } 69 if (d1 & (1 << 63)) != 0 { bad = bad + 1 } 70 let d2: i64 = nx_f64_erf((1 << 63) | 1) 71 if d2 == NX_F64_NAN_RAW { bad = bad + 1 } 72 if (d2 & (1 << 63)) == 0 { bad = bad + 1 } 73 let d3: i64 = nx_f64_erf(0x000FFFFFFFFFFFFF) 74 if d3 == NX_F64_NAN_RAW { bad = bad + 1 } 75 // E2 monotone non-decreasing 0.5 -> 1.75 step 1/256 (bits compare valid: positive) 76 // 0.5 = 128/256 ... 1.75 = 448/256: x_k bits via integer-ratio f64 build is heavy -- 77 // step in BITS instead: from 0x3FE0000000000000 (0.5) to 0x3FFC000000000000 (1.75) 78 // sampling 320 evenly spaced bit-points (monotone in bits = monotone in value for 79 // positive finite doubles; consecutive kernel outputs must not DECREASE) 80 let lo: i64 = 0x3FE0000000000000 81 let hi: i64 = 0x3FFC000000000000 82 let step: i64 = (hi - lo) / 320 83 var prev: i64 = 0 84 var k: i64 = 0 85 while k <= 320 { 86 let xb: i64 = lo + k * step 87 let y: i64 = nx_f64_erf(xb) 88 if y == NX_F64_NAN_RAW { bad = bad + 1 } 89 if y < prev { bad = bad + 1 } 90 prev = y 91 k = k + 1 92 } 93 // E3 gap contract: just above the cut -> loud NaN (cut bits 0x3FFC000000000000) 94 if nx_f64_erf(0x3FFC000000000001) != NX_F64_NAN_RAW { bad = bad + 1 } 95 // E4 strictly below one inside the domain 96 let top: i64 = nx_f64_erf(0x3FFC000000000000) 97 if top >= 0x3FF0000000000000 { bad = bad + 1 } 98 // E5 semantic anchors: 8-point independent bf oracle, ULP <= 4 99 let pi: *i64 = bf_new() 100 bf_pi(pi) 101 let spi: *i64 = bf_new() 102 fg_sqrt(spi, pi, 0x3FFC5BF891B4EF6A) 103 let two: *i64 = bf_new() 104 bf_set_int(two, 2) 105 let tosp: *i64 = bf_new() 106 bf_div(tosp, two, spi) 107 let kb: *i64 = bf_new() 108 let xb: *i64 = bf_new() 109 var j: i64 = 1 110 while j <= 8 { 111 bf_set_int(kb, j) 112 bf_div_small(xb, kb, 8) 113 let axbits: i64 = bf_to_f64(xb, 0, 0) 114 let want: i64 = fg_oracle(axbits, tosp) 115 let got: i64 = nx_f64_erf(axbits) 116 var du: i64 = got - want 117 if du < 0 { du = 0 - du } 118 if du > 4 { bad = bad + 1 } 119 j = j + 1 120 } 121 let lfd: i64 = sys_openat_append("knowledge/status/math_engine.log" as *u8, 0x1a4) 122 if lfd >= 0 { 123 fg_f(lfd, "F64ERF-GATE epoch=" as *u8); fg_n(lfd, sys_now_realtime_sec()) 124 fg_f(lfd, " bad=" as *u8); fg_n(lfd, bad) 125 if bad == 0 { fg_f(lfd, " verdict=GREEN\n" as *u8) } else { fg_f(lfd, " verdict=RED\n" as *u8) } 126 sys_close(lfd) 127 } 128 if bad == 0 { fg_p(" F64ERF-GATE: GREEN (edges + monotone + gap contract held)\n" as *u8); sys_exit(0); return 0 } 129 fg_p(" F64ERF-GATE: RED\n" as *u8) 130 sys_exit(1) 131 return 1 132}