eyeling 1.16.3 → 1.16.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/package.json +2 -3
- package/arctifacts/README.md +0 -59
- package/arctifacts/ackermann.html +0 -678
- package/arctifacts/auroracare.html +0 -1297
- package/arctifacts/bike-trip.html +0 -752
- package/arctifacts/binomial-theorem.html +0 -631
- package/arctifacts/bmi.html +0 -511
- package/arctifacts/building-performance.html +0 -750
- package/arctifacts/clinical-care.html +0 -726
- package/arctifacts/collatz.html +0 -403
- package/arctifacts/complex.html +0 -321
- package/arctifacts/control-system.html +0 -482
- package/arctifacts/delfour.html +0 -849
- package/arctifacts/earthquake-epicenter.html +0 -982
- package/arctifacts/eco-route.html +0 -662
- package/arctifacts/euclid-infinitude.html +0 -564
- package/arctifacts/euler-identity.html +0 -667
- package/arctifacts/exoplanet-transit.html +0 -1000
- package/arctifacts/faltings-theorem.html +0 -1046
- package/arctifacts/fibonacci.html +0 -299
- package/arctifacts/fundamental-theorem-arithmetic.html +0 -398
- package/arctifacts/godel-numbering.html +0 -743
- package/arctifacts/gps-bike.html +0 -759
- package/arctifacts/gps-clinical-bench.html +0 -792
- package/arctifacts/graph-french.html +0 -449
- package/arctifacts/grass-molecular.html +0 -592
- package/arctifacts/group-theory.html +0 -740
- package/arctifacts/health-info.html +0 -833
- package/arctifacts/kaprekar-constant.html +0 -576
- package/arctifacts/lee.html +0 -805
- package/arctifacts/linked-lists.html +0 -502
- package/arctifacts/lldm.html +0 -612
- package/arctifacts/matrix-multiplication.html +0 -502
- package/arctifacts/matrix.html +0 -651
- package/arctifacts/newton-raphson.html +0 -944
- package/arctifacts/peano-factorial.html +0 -456
- package/arctifacts/pi.html +0 -363
- package/arctifacts/polynomial.html +0 -646
- package/arctifacts/prime.html +0 -366
- package/arctifacts/pythagorean-theorem.html +0 -468
- package/arctifacts/rest-path.html +0 -469
- package/arctifacts/roots-of-unity.html +0 -363
- package/arctifacts/turing.html +0 -409
- package/arctifacts/wind-turbines.html +0 -726
package/arctifacts/pi.html
DELETED
|
@@ -1,363 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
6
|
-
<title>π — Chudnovsky</title>
|
|
7
|
-
<style>
|
|
8
|
-
:root {
|
|
9
|
-
--bg: #f7fafc;
|
|
10
|
-
--ink: #0b1220;
|
|
11
|
-
--muted: #5b6780;
|
|
12
|
-
--accent: #0b6cff;
|
|
13
|
-
--panel: #fff;
|
|
14
|
-
--border: #dfe6ee;
|
|
15
|
-
--card: #f3f6fb;
|
|
16
|
-
--ok: #15803d;
|
|
17
|
-
--fail: #c2410c;
|
|
18
|
-
--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, 'Liberation Mono', monospace;
|
|
19
|
-
}
|
|
20
|
-
* {
|
|
21
|
-
box-sizing: border-box;
|
|
22
|
-
}
|
|
23
|
-
body {
|
|
24
|
-
margin: 0;
|
|
25
|
-
background: var(--bg);
|
|
26
|
-
color: var(--ink);
|
|
27
|
-
font:
|
|
28
|
-
14px/1.45 system-ui,
|
|
29
|
-
-apple-system,
|
|
30
|
-
Segoe UI,
|
|
31
|
-
Roboto,
|
|
32
|
-
Helvetica,
|
|
33
|
-
Arial,
|
|
34
|
-
sans-serif;
|
|
35
|
-
}
|
|
36
|
-
h1 {
|
|
37
|
-
margin: 18px 0 4px;
|
|
38
|
-
font-size: 20px;
|
|
39
|
-
letter-spacing: -0.01em;
|
|
40
|
-
}
|
|
41
|
-
.wrap {
|
|
42
|
-
max-width: 860px;
|
|
43
|
-
margin: 0 auto;
|
|
44
|
-
padding: 16px;
|
|
45
|
-
}
|
|
46
|
-
.controls {
|
|
47
|
-
display: flex;
|
|
48
|
-
flex-wrap: wrap;
|
|
49
|
-
gap: 10px;
|
|
50
|
-
align-items: center;
|
|
51
|
-
background: var(--panel);
|
|
52
|
-
border: 1px solid var(--border);
|
|
53
|
-
border-radius: 12px;
|
|
54
|
-
padding: 10px;
|
|
55
|
-
margin-bottom: 14px;
|
|
56
|
-
}
|
|
57
|
-
.controls input {
|
|
58
|
-
width: 120px;
|
|
59
|
-
padding: 8px 10px;
|
|
60
|
-
border-radius: 10px;
|
|
61
|
-
border: 1px solid var(--border);
|
|
62
|
-
}
|
|
63
|
-
.controls button {
|
|
64
|
-
padding: 9px 12px;
|
|
65
|
-
border-radius: 10px;
|
|
66
|
-
border: 1px solid var(--border);
|
|
67
|
-
background: #fff;
|
|
68
|
-
cursor: pointer;
|
|
69
|
-
}
|
|
70
|
-
.controls button.primary {
|
|
71
|
-
background: linear-gradient(180deg, #4da3ff, #0b6cff);
|
|
72
|
-
border-color: #0b6cff;
|
|
73
|
-
color: #fff;
|
|
74
|
-
}
|
|
75
|
-
.hint {
|
|
76
|
-
color: var(--muted);
|
|
77
|
-
font-size: 12px;
|
|
78
|
-
}
|
|
79
|
-
.card {
|
|
80
|
-
background: var(--panel);
|
|
81
|
-
border: 1px solid var(--border);
|
|
82
|
-
border-radius: 12px;
|
|
83
|
-
padding: 12px;
|
|
84
|
-
margin-bottom: 12px;
|
|
85
|
-
}
|
|
86
|
-
.card h3 {
|
|
87
|
-
margin: 0 0 8px;
|
|
88
|
-
color: var(--muted);
|
|
89
|
-
text-transform: uppercase;
|
|
90
|
-
font-size: 12px;
|
|
91
|
-
letter-spacing: 0.08em;
|
|
92
|
-
}
|
|
93
|
-
.answer {
|
|
94
|
-
font-family: var(--mono);
|
|
95
|
-
background: var(--card);
|
|
96
|
-
border: 1px dashed #cfd8e3;
|
|
97
|
-
border-radius: 10px;
|
|
98
|
-
padding: 10px;
|
|
99
|
-
white-space: pre-wrap;
|
|
100
|
-
word-break: break-word;
|
|
101
|
-
}
|
|
102
|
-
.small {
|
|
103
|
-
color: var(--muted);
|
|
104
|
-
font-size: 12px;
|
|
105
|
-
}
|
|
106
|
-
.check {
|
|
107
|
-
border-left: 6px solid var(--border);
|
|
108
|
-
background: var(--card);
|
|
109
|
-
border: 1px solid #e2e8f0;
|
|
110
|
-
border-radius: 10px;
|
|
111
|
-
padding: 8px 10px;
|
|
112
|
-
margin: 6px 0;
|
|
113
|
-
}
|
|
114
|
-
.check.ok {
|
|
115
|
-
border-left-color: var(--ok);
|
|
116
|
-
}
|
|
117
|
-
.check.fail {
|
|
118
|
-
border-left-color: var(--fail);
|
|
119
|
-
}
|
|
120
|
-
.check b {
|
|
121
|
-
display: block;
|
|
122
|
-
margin-bottom: 2px;
|
|
123
|
-
}
|
|
124
|
-
</style>
|
|
125
|
-
</head>
|
|
126
|
-
<body>
|
|
127
|
-
<div class="wrap">
|
|
128
|
-
<h1>π — Chudnovsky</h1>
|
|
129
|
-
<p class="small">
|
|
130
|
-
Computes π to N decimals in your browser (BigInt, fixed-point). Shows Answer • Reason • Checks.
|
|
131
|
-
</p>
|
|
132
|
-
|
|
133
|
-
<div class="controls">
|
|
134
|
-
<label for="digits">Digits:</label>
|
|
135
|
-
<input id="digits" type="number" min="1" max="2000" value="100" />
|
|
136
|
-
<button id="run" class="primary">Run</button>
|
|
137
|
-
<button id="copy">Copy</button>
|
|
138
|
-
<span class="hint">Up to 2 000 digits. Uses guard digits, then <b>truncates</b> to N.</span>
|
|
139
|
-
</div>
|
|
140
|
-
|
|
141
|
-
<section class="card">
|
|
142
|
-
<h3>Answer</h3>
|
|
143
|
-
<div id="answer" class="answer">—</div>
|
|
144
|
-
<div class="small" id="meta">–</div>
|
|
145
|
-
</section>
|
|
146
|
-
|
|
147
|
-
<section class="card">
|
|
148
|
-
<h3>Reason</h3>
|
|
149
|
-
<div id="reason" class="small">—</div>
|
|
150
|
-
</section>
|
|
151
|
-
|
|
152
|
-
<section class="card">
|
|
153
|
-
<h3>Checks</h3>
|
|
154
|
-
<div id="checks"></div>
|
|
155
|
-
</section>
|
|
156
|
-
</div>
|
|
157
|
-
|
|
158
|
-
<script>
|
|
159
|
-
/* ---------- Utils ---------- */
|
|
160
|
-
const $ = (s) => document.querySelector(s);
|
|
161
|
-
function pow10n(e) {
|
|
162
|
-
let E = BigInt(e),
|
|
163
|
-
b = 10n,
|
|
164
|
-
r = 1n;
|
|
165
|
-
while (E > 0n) {
|
|
166
|
-
if (E & 1n) r *= b;
|
|
167
|
-
E >>= 1n;
|
|
168
|
-
if (E) b *= b;
|
|
169
|
-
}
|
|
170
|
-
return r;
|
|
171
|
-
}
|
|
172
|
-
function isqrt(n) {
|
|
173
|
-
if (n < 0n) throw Error('isqrt neg');
|
|
174
|
-
if (n < 2n) return n;
|
|
175
|
-
let x = n,
|
|
176
|
-
y = (n >> 1n) + 1n;
|
|
177
|
-
while (y < x) {
|
|
178
|
-
x = y;
|
|
179
|
-
y = (y + n / y) >> 1n;
|
|
180
|
-
}
|
|
181
|
-
return x;
|
|
182
|
-
}
|
|
183
|
-
function formatScaled(S, prec) {
|
|
184
|
-
const s = S.toString(),
|
|
185
|
-
p = s.length - prec;
|
|
186
|
-
return p <= 0 ? '0.' + '0'.repeat(-p) + s : s.slice(0, p) + '.' + s.slice(p);
|
|
187
|
-
}
|
|
188
|
-
function prettyBreak(s) {
|
|
189
|
-
const i = s.indexOf('.');
|
|
190
|
-
return i < 0 ? s : s.slice(0, i + 1) + s.slice(i + 1).replace(/.{1,100}/g, '$&\n');
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/* ---------- π via Chudnovsky (fixed-point, truncate) ---------- */
|
|
194
|
-
function chudnovskyPi(digits, guard = 20) {
|
|
195
|
-
if (!Number.isFinite(digits) || digits < 1) throw Error('digits >= 1');
|
|
196
|
-
const A = 13591409n,
|
|
197
|
-
B = 545140134n,
|
|
198
|
-
C3 = 262537412640768000n,
|
|
199
|
-
K = 426880n; // 640320^3
|
|
200
|
-
const prec = digits + guard,
|
|
201
|
-
scale = pow10n(prec);
|
|
202
|
-
const sqrt10005 = isqrt(10005n * scale * scale); // floor(sqrt(10005)*10^prec)
|
|
203
|
-
|
|
204
|
-
const terms = Math.ceil((digits + guard) / 14) + 2; // ~14 digits/term
|
|
205
|
-
let S = 0n,
|
|
206
|
-
M = 1n,
|
|
207
|
-
X = 1n,
|
|
208
|
-
sign = 1n;
|
|
209
|
-
for (let k = 0; k < terms; k++) {
|
|
210
|
-
const kk = BigInt(k),
|
|
211
|
-
L = A + B * kk;
|
|
212
|
-
const term = (M * L * scale) / X; // floor((M*L/X)*10^prec)
|
|
213
|
-
S += sign * term;
|
|
214
|
-
const k1 = kk + 1n,
|
|
215
|
-
sixk = 6n * kk;
|
|
216
|
-
const num = (sixk + 1n) * (sixk + 2n) * (sixk + 3n) * (sixk + 4n) * (sixk + 5n) * (sixk + 6n);
|
|
217
|
-
const den = (3n * kk + 1n) * (3n * kk + 2n) * (3n * kk + 3n) * (k1 * k1 * k1);
|
|
218
|
-
M = (M * num) / den;
|
|
219
|
-
X = X * C3;
|
|
220
|
-
sign = -sign;
|
|
221
|
-
}
|
|
222
|
-
if (S === 0n) throw Error('internal sum zero');
|
|
223
|
-
// pi_full is scaled by 10^(digits+guard)
|
|
224
|
-
let pi_full = (K * sqrt10005 * scale) / S;
|
|
225
|
-
// TRUNCATE guard digits to match reference prefixes
|
|
226
|
-
if (guard > 0) pi_full = pi_full / pow10n(guard);
|
|
227
|
-
return { text: formatScaled(pi_full, digits), raw: pi_full, prec, terms, guard };
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/* ---------- Independent Machin cross-check (truncate) ---------- */
|
|
231
|
-
// π = 16*atan(1/5) − 4*atan(1/239)
|
|
232
|
-
function arctan_inv_scaled(m, prec) {
|
|
233
|
-
// floor(atan(1/m) * 10^prec)
|
|
234
|
-
const scale = pow10n(prec),
|
|
235
|
-
x = scale / BigInt(m);
|
|
236
|
-
let t = x,
|
|
237
|
-
sum = t;
|
|
238
|
-
for (let n = 0; n < 40000; n++) {
|
|
239
|
-
// t_{n+1} = - t_n * x^2 * (2n+1)/(2n+3), with per-step rounding to reduce drift
|
|
240
|
-
let t1 = (t * x + scale / 2n) / scale; // round
|
|
241
|
-
t1 = (t1 * x + scale / 2n) / scale; // round again => *x^2
|
|
242
|
-
t1 = (t1 * BigInt(2 * n + 1) + BigInt(2 * n + 3) / 2n) / BigInt(2 * n + 3); // round ratio
|
|
243
|
-
t = -t1;
|
|
244
|
-
if (t === 0n) break;
|
|
245
|
-
sum += t;
|
|
246
|
-
}
|
|
247
|
-
return sum; // scaled by 10^prec
|
|
248
|
-
}
|
|
249
|
-
function machinPiTrunc(digits) {
|
|
250
|
-
const guard = 50,
|
|
251
|
-
prec = digits + guard;
|
|
252
|
-
let p = 16n * arctan_inv_scaled(5, prec) - 4n * arctan_inv_scaled(239, prec);
|
|
253
|
-
p = p / pow10n(guard); // TRUNCATE to digits
|
|
254
|
-
return formatScaled(p, digits);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/* ---------- Checks ---------- */
|
|
258
|
-
const PI_PREFIX_200 =
|
|
259
|
-
'3.14159265358979323846264338327950288419716939937510' +
|
|
260
|
-
'58209749445923078164062862089986280348253421170679' +
|
|
261
|
-
'82148086513282306647093844609550582231725359408128';
|
|
262
|
-
|
|
263
|
-
function runChecks(answerText, digits) {
|
|
264
|
-
const out = [],
|
|
265
|
-
clean = answerText.replace(/[^0-9.]/g, '');
|
|
266
|
-
|
|
267
|
-
// 0) Format / length
|
|
268
|
-
const okBegins = clean.startsWith('3.'),
|
|
269
|
-
okLen = clean.length === 2 + digits;
|
|
270
|
-
out.push({
|
|
271
|
-
name: 'Format check',
|
|
272
|
-
ok: okBegins && okLen,
|
|
273
|
-
detail: okBegins
|
|
274
|
-
? okLen
|
|
275
|
-
? 'starts with 3. and length OK'
|
|
276
|
-
: `length ${clean.length} ≠ ${2 + digits}`
|
|
277
|
-
: 'does not start with 3.',
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
// 1) Prefix (≤200 digits)
|
|
281
|
-
const upto = Math.min(clean.length, PI_PREFIX_200.length);
|
|
282
|
-
const okPrefix = clean.slice(0, upto) === PI_PREFIX_200.slice(0, upto);
|
|
283
|
-
out.push({
|
|
284
|
-
name: `Prefix check (≤ ${Math.max(0, upto - 2)} decimals)`,
|
|
285
|
-
ok: okPrefix,
|
|
286
|
-
detail: okPrefix ? 'prefix matches' : 'prefix differs',
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
// 2) Stability (guard +10, still truncated)
|
|
290
|
-
const b = chudnovskyPi(digits, 30).text.replace(/[^0-9.]/g, '');
|
|
291
|
-
const okStable = clean.slice(0, 2 + digits) === b.slice(0, 2 + digits);
|
|
292
|
-
out.push({
|
|
293
|
-
name: 'Stability check (guard +10)',
|
|
294
|
-
ok: okStable,
|
|
295
|
-
detail: okStable ? 'first N digits unchanged' : 'leading digits changed',
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
// 3) Machin cross-check (truncate; first K decimals)
|
|
299
|
-
const K = Math.min(60, digits);
|
|
300
|
-
if (K >= 10) {
|
|
301
|
-
const m = machinPiTrunc(K).replace(/[^0-9.]/g, '');
|
|
302
|
-
const okMach = clean.slice(0, 2 + K) === m.slice(0, 2 + K);
|
|
303
|
-
out.push({ name: `Machin cross-check (${K} dec)`, ok: okMach, detail: okMach ? 'matches' : 'differs' });
|
|
304
|
-
}
|
|
305
|
-
return out;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
/* ---------- UI ---------- */
|
|
309
|
-
const ans = $('#answer'),
|
|
310
|
-
meta = $('#meta'),
|
|
311
|
-
reason = $('#reason'),
|
|
312
|
-
list = $('#checks');
|
|
313
|
-
function renderChecks(items) {
|
|
314
|
-
list.innerHTML = items
|
|
315
|
-
.map(
|
|
316
|
-
(r) =>
|
|
317
|
-
`<div class="check ${r.ok ? 'ok' : 'fail'}"><b>${r.ok ? '✓' : '✗'} ${r.name}</b><span>${r.detail}</span></div>`,
|
|
318
|
-
)
|
|
319
|
-
.join('');
|
|
320
|
-
}
|
|
321
|
-
function compute() {
|
|
322
|
-
const n = Math.max(1, Math.min(2000, parseInt($('#digits').value || '100', 10)));
|
|
323
|
-
const t0 = performance.now();
|
|
324
|
-
let out;
|
|
325
|
-
try {
|
|
326
|
-
out = chudnovskyPi(n, 20);
|
|
327
|
-
} catch (e) {
|
|
328
|
-
ans.textContent = 'Error: ' + (e.message || e);
|
|
329
|
-
reason.textContent = '';
|
|
330
|
-
list.innerHTML = '';
|
|
331
|
-
meta.textContent = '';
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
const ms = performance.now() - t0;
|
|
335
|
-
ans.textContent = prettyBreak(out.text);
|
|
336
|
-
meta.textContent = `"3." + ${n} decimals (truncated)`;
|
|
337
|
-
reason.textContent = `Chudnovsky; terms=${out.terms}; guard=${out.guard}; precision=${out.prec}; time=${ms.toFixed(0)} ms.`;
|
|
338
|
-
renderChecks(runChecks(out.text, n));
|
|
339
|
-
}
|
|
340
|
-
$('#run').addEventListener('click', compute);
|
|
341
|
-
$('#copy').addEventListener('click', async () => {
|
|
342
|
-
try {
|
|
343
|
-
await navigator.clipboard.writeText(ans.textContent.replace(/\n/g, ''));
|
|
344
|
-
$('#copy').textContent = 'Copied!';
|
|
345
|
-
setTimeout(() => ($('#copy').textContent = 'Copy'), 1000);
|
|
346
|
-
} catch {
|
|
347
|
-
$('#copy').textContent = 'Copy failed';
|
|
348
|
-
setTimeout(() => ($('#copy').textContent = 'Copy'), 1200);
|
|
349
|
-
}
|
|
350
|
-
});
|
|
351
|
-
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', compute);
|
|
352
|
-
else compute();
|
|
353
|
-
|
|
354
|
-
/* ---------- Error surfacing ---------- */
|
|
355
|
-
window.addEventListener('error', (e) => {
|
|
356
|
-
ans.textContent = 'Error: ' + (e.message || 'script error');
|
|
357
|
-
});
|
|
358
|
-
window.addEventListener('unhandledrejection', (e) => {
|
|
359
|
-
ans.textContent = 'Error: ' + ((e.reason && e.reason.message) || e.reason);
|
|
360
|
-
});
|
|
361
|
-
</script>
|
|
362
|
-
</body>
|
|
363
|
-
</html>
|