code wiki / _hdl_build / _bf_sinhcosh_gate_authored.nx
_bf_sinhcosh_gate_authored.nx source
↩ module page · 194 lines · 8982 B
1// _bf_sinhcosh_gate_authored.nx -- self-anchor gate for the SOVEREIGN bigfloat
2// sinh/cosh oracle (nx_bigfloat120_sinh). No external oracle:
3// 1. DOUBLE-ANGLE (cancellation-free, full domain): sinh(2u) = 2 sinh u cosh u
4// and cosh(2u) = 1 + 2 sinh^2 u at 150 banded points (u < 350), rel < 2^-100.
5// 2. PYTHAGOREAN strip: cosh^2 - sinh^2 = 1 for |x| <= 5 (the subtraction
6// cancels 2*log2(cosh) <= 13 bits there), 60 points, rel < 2^-90.
7// 3. f64 tie to the BLESSED exp organ: sinh(x)+cosh(x) within 2 ulp of
8// bf_exp_f64(x) at 100 points (different exp code path).
9// 4. Specials + overflow boundary + Taylor/exp seam at x = 1.
10// Markers: BFSH-DOUBLE / BFSH-PYTH / BFSH-EXPTIE / BFSH-SPEC / verdict=
11
12import "nx_syscalls.nx"
13import "nx_f64.nx"
14import "nx_f64_div.nx"
15import "nx_bigfloat120.nx"
16import "nx_bigfloat120_div.nx"
17import "nx_bigfloat120_exp.nx"
18import "nx_bigfloat120_ln.nx"
19import "nx_bigfloat120_pow.nx"
20import "nx_bigfloat120_sinh.nx"
21
22func bsg_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
23func bsg_putn(v: i64) -> i64 { let bb: *u8 = sys_mmap(28); var m: i64 = v; if m < 0 { m = 0 - m; sys_write(1, "-" as *u8, 1) }; let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48; k = 1 }; while m > 0 { t[k] = 48 + (m % 10); m = m / 10; k = k + 1 }; var i: i64 = 0; while i < k { bb[i] = t[k-1-i]; i = i + 1 }; sys_write(1, bb, k); return 0 }
24func bsg_puthex(v: i64) -> i64 { let bb: *u8 = sys_mmap(20); var i: i64 = 0; while i < 16 { let nib: i64 = (v >> ((15 - i) * 4)) & 15; if nib < 10 { bb[i] = 48 + nib } else { bb[i] = 55 + nib } i = i + 1 } sys_write(1, bb, 16); return 0 }
25
26func bsg_rng(state: *i64) -> i64 {
27 var s: i64 = state[0]
28 s = s ^ ((s >> 12) & 0x000FFFFFFFFFFFFF)
29 s = s ^ (s << 25)
30 s = s ^ ((s >> 27) & 0x0000001FFFFFFFFF)
31 state[0] = s
32 return s * 2685821657736338717
33}
34
35func bsg_relok(a: *i64, b: *i64, bits: i64) -> i64 {
36 let d: *i64 = bf_new()
37 if bf_cmp(a, b) >= 0 { bf_sub(d, a, b) } else { bf_sub(d, b, a) }
38 if bf_is_zero(d) == 1 { return 1 }
39 if d[0] <= b[0] - bits { return 1 }
40 return 0
41}
42
43func bsg_ord(v: i64) -> i64 {
44 if v >= 0 { return v }
45 return (1 << 63) - v
46}
47
48func bsg_ulp(a: i64, b: i64) -> i64 {
49 if a == b { return 0 }
50 var u: i64 = bsg_ord(a) - bsg_ord(b)
51 if u < 0 { u = 0 - u }
52 return u
53}
54
55func main() -> i64 {
56 var bad: i64 = 0
57 let one: *i64 = bf_new()
58 bf_set_int(one, 1)
59 let st: *i64 = sys_mmap(16) as *i64
60 // LN40 (2026-09-03): this PRNG seed was written as a 20-digit decimal that does not fit 64 bits, so
61 // every build before today WRAPPED it silently. The value below is exactly what it wrapped to, so the
62 // sequence this gate has always exercised is unchanged -- the literal now says what the machine does.
63 st[0] = 13176032527974241704
64
65 // ---- 1. double-angle, full domain ----
66 var dbad: i64 = 0
67 var j: i64 = 0
68 while j < 150 {
69 var raw: i64 = bsg_rng(st)
70 var efr: i64 = 0
71 let band: i64 = raw & 3
72 if band == 0 { efr = 1015 + (raw & 15) } // 2^-8 .. 2^8
73 if band == 1 { efr = 1023 + (raw & 7) } // 1 .. 256
74 if band == 2 { efr = 990 + (raw & 31) } // small
75 if band == 3 { efr = 1029 + (raw & 3) } // 64 .. 512 (2u < 710)
76 raw = (efr << 52) | (bsg_rng(st) & 0x000FFFFFFFFFFFFF)
77 if efr == 1031 { raw = (1031 << 52) | (bsg_rng(st) & 0x0007FFFFFFFFFFFF) } // cap < 350
78 if efr == 1032 { raw = (1029 << 52) | (bsg_rng(st) & 0x000FFFFFFFFFFFFF) }
79 let u: *i64 = bf_new()
80 bf_set_f64(u, raw)
81 let sh: *i64 = bf_new()
82 bf_sinh_xb(sh, u)
83 let ch: *i64 = bf_new()
84 bf_cosh_xb(ch, u)
85 let u2: *i64 = bf_new()
86 bf_copy(u2, u)
87 u2[0] = u2[0] + 1 // exact 2u
88 let sh2: *i64 = bf_new()
89 bf_sinh_xb(sh2, u2)
90 let ch2: *i64 = bf_new()
91 bf_cosh_xb(ch2, u2)
92 // sinh(2u) = 2 sinh u cosh u
93 let pr: *i64 = bf_new()
94 bf_mul(pr, sh, ch)
95 pr[0] = pr[0] + 1
96 var ok: i64 = bsg_relok(pr, sh2, 100)
97 // cosh(2u) = 1 + 2 sinh^2 u
98 let s2: *i64 = bf_new()
99 bf_mul(s2, sh, sh)
100 s2[0] = s2[0] + 1
101 let rhs: *i64 = bf_new()
102 bf_add(rhs, one, s2)
103 if bsg_relok(rhs, ch2, 100) == 0 { ok = 0 }
104 if ok == 0 {
105 dbad = dbad + 1
106 if dbad <= 10 { bsg_puts("BFSH-DBLBAD u=" as *u8); bsg_puthex(raw); bsg_puts("\n" as *u8) }
107 }
108 j = j + 1
109 }
110 bsg_puts("BFSH-DOUBLE total=150 bad=" as *u8); bsg_putn(dbad); bsg_puts(" bar=rel<2^-100\n" as *u8)
111 bad = bad + dbad
112
113 // ---- 2. pythagorean strip |x| <= 5 ----
114 var ybad: i64 = 0
115 j = 0
116 while j < 60 {
117 var raw2: i64 = bsg_rng(st)
118 let efr2: i64 = 1018 + (raw2 & 7) // 2^-5 .. 8 capped
119 raw2 = (efr2 << 52) | (bsg_rng(st) & 0x000FFFFFFFFFFFFF)
120 if efr2 == 1025 { raw2 = (1024 << 52) | (bsg_rng(st) & 0x000FFFFFFFFFFFFF) } // < 4
121 let xv: *i64 = bf_new()
122 bf_set_f64(xv, raw2)
123 let sh3: *i64 = bf_new()
124 bf_sinh_xb(sh3, xv)
125 let ch3: *i64 = bf_new()
126 bf_cosh_xb(ch3, xv)
127 let cq: *i64 = bf_new()
128 bf_mul(cq, ch3, ch3)
129 let sq: *i64 = bf_new()
130 bf_mul(sq, sh3, sh3)
131 let df: *i64 = bf_new()
132 bf_sub(df, cq, sq) // cosh^2 > sinh^2
133 if bsg_relok(df, one, 90) == 0 {
134 ybad = ybad + 1
135 if ybad <= 5 { bsg_puts("BFSH-PYTHBAD x=" as *u8); bsg_puthex(raw2); bsg_puts("\n" as *u8) }
136 }
137 j = j + 1
138 }
139 bsg_puts("BFSH-PYTH total=60 bad=" as *u8); bsg_putn(ybad); bsg_puts(" bar=rel<2^-90\n" as *u8)
140 bad = bad + ybad
141
142 // ---- 3. f64 tie: sinh + cosh = e^x vs the blessed exp organ ----
143 var ebad: i64 = 0
144 j = 0
145 while j < 100 {
146 var raw3: i64 = bsg_rng(st)
147 let efr3: i64 = 1015 + (raw3 & 15)
148 raw3 = (efr3 << 52) | (bsg_rng(st) & 0x000FFFFFFFFFFFFF)
149 let sf: i64 = bf_sinh_f64(raw3)
150 let cf: i64 = bf_cosh_f64(raw3)
151 let ex: i64 = bf_exp_f64(raw3)
152 if bsg_ulp(nx_f64_add(sf, cf), ex) > 2 {
153 ebad = ebad + 1
154 if ebad <= 5 { bsg_puts("BFSH-EXPBAD x=" as *u8); bsg_puthex(raw3); bsg_puts("\n" as *u8) }
155 }
156 j = j + 1
157 }
158 bsg_puts("BFSH-EXPTIE total=100 bad=" as *u8); bsg_putn(ebad); bsg_puts(" bar=2ulp\n" as *u8)
159 bad = bad + ebad
160
161 // ---- 4. specials + overflow boundary + seam ----
162 var sbad: i64 = 0
163 if bf_sinh_f64(0) != 0 { sbad = sbad + 1; bsg_puts("SPECBAD a\n" as *u8) }
164 if bf_sinh_f64(1 << 63) != (1 << 63) { sbad = sbad + 1; bsg_puts("SPECBAD b\n" as *u8) }
165 if bf_cosh_f64(0) != 0x3FF0000000000000 { sbad = sbad + 1; bsg_puts("SPECBAD c\n" as *u8) }
166 if bf_cosh_f64(1 << 63) != 0x3FF0000000000000 { sbad = sbad + 1; bsg_puts("SPECBAD d\n" as *u8) }
167 if bf_sinh_f64(0x7FF8000000000000) != 0x7FF8000000000000 { sbad = sbad + 1; bsg_puts("SPECBAD e\n" as *u8) }
168 if bf_sinh_f64(0x7FF0000000000000) != 0x7FF0000000000000 { sbad = sbad + 1; bsg_puts("SPECBAD f\n" as *u8) }
169 if bf_sinh_f64(0xFFF0000000000000) != 0xFFF0000000000000 { sbad = sbad + 1; bsg_puts("SPECBAD g\n" as *u8) }
170 if bf_cosh_f64(0xFFF0000000000000) != 0x7FF0000000000000 { sbad = sbad + 1; bsg_puts("SPECBAD h\n" as *u8) }
171 // overflow boundary: true cut ~710.476: 710.0 finite, 710.5 -> inf
172 if bf_sinh_f64(0x4086340000000000) != 0x7FF0000000000000 { sbad = sbad + 1; bsg_puts("SPECBAD i\n" as *u8) } // 710.5 -> inf
173 let fb: i64 = bf_sinh_f64(0x4086300000000000) // 710.0: finite
174 if ((fb >> 52) & 0x7FF) == 2047 { sbad = sbad + 1; bsg_puts("SPECBAD i2\n" as *u8) }
175 let fin: i64 = bf_cosh_f64(0x4086200000000000) // 708.25: finite
176 if ((fin >> 52) & 0x7FF) == 2047 { sbad = sbad + 1; bsg_puts("SPECBAD j\n" as *u8) }
177 if bf_cosh_f64(0x40C0000000000000) != 0x7FF0000000000000 { sbad = sbad + 1; bsg_puts("SPECBAD k\n" as *u8) } // 8192 -> inf
178 // sinh odd at the Taylor/exp seam
179 let pv: i64 = bf_sinh_f64(0x3FF0000000000000)
180 if bf_sinh_f64(0xBFF0000000000000) != (pv | (1 << 63)) { sbad = sbad + 1; bsg_puts("SPECBAD l\n" as *u8) }
181 // monotone across the seam x = 1
182 let s0: i64 = bf_sinh_f64(0x3FEFFFFFFFFFFFFF)
183 if s0 > pv { sbad = sbad + 1; bsg_puts("SPECBAD m\n" as *u8) }
184 bsg_puts("BFSH-SPEC bad=" as *u8); bsg_putn(sbad); bsg_puts("\n" as *u8)
185 bad = bad + sbad
186
187 if bad == 0 {
188 bsg_puts("BFSH-GATE verdict=GREEN\n" as *u8)
189 return 0
190 }
191 bsg_puts("BFSH-GATE verdict=RED\n" as *u8)
192 if bad > 100 { bad = 100 }
193 return bad
194}