eyeling 1.16.2 → 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/HANDBOOK.md +4 -0
- package/README.md +0 -1
- package/examples/ershov-mixed-computation.n3 +106 -0
- package/examples/output/ershov-mixed-computation.n3 +15 -0
- package/eyeling.js +510 -263
- package/lib/cli.js +22 -12
- package/lib/engine.js +488 -251
- 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
|
@@ -1,564 +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>Euclid’s Infinitude of Primes</title>
|
|
7
|
-
<style>
|
|
8
|
-
:root {
|
|
9
|
-
--bg: #f6f8fb;
|
|
10
|
-
--card: #ffffff;
|
|
11
|
-
--text: #1f2937;
|
|
12
|
-
--muted: #6b7280;
|
|
13
|
-
--accent: #0ea5e9;
|
|
14
|
-
--ring: rgba(14, 165, 233, 0.25);
|
|
15
|
-
--border: #e5e7eb;
|
|
16
|
-
}
|
|
17
|
-
* {
|
|
18
|
-
box-sizing: border-box;
|
|
19
|
-
}
|
|
20
|
-
html,
|
|
21
|
-
body {
|
|
22
|
-
height: 100%;
|
|
23
|
-
}
|
|
24
|
-
body {
|
|
25
|
-
margin: 0;
|
|
26
|
-
font:
|
|
27
|
-
16px/1.6 ui-sans-serif,
|
|
28
|
-
system-ui,
|
|
29
|
-
-apple-system,
|
|
30
|
-
Segoe UI,
|
|
31
|
-
Roboto,
|
|
32
|
-
Ubuntu,
|
|
33
|
-
Cantarell,
|
|
34
|
-
Noto Sans,
|
|
35
|
-
'Helvetica Neue',
|
|
36
|
-
Arial,
|
|
37
|
-
'Apple Color Emoji',
|
|
38
|
-
'Segoe UI Emoji';
|
|
39
|
-
color: var(--text);
|
|
40
|
-
background: radial-gradient(1400px 700px at 20% -10%, #ffffff 0, #f5fbff 40%, var(--bg) 100%);
|
|
41
|
-
}
|
|
42
|
-
.container {
|
|
43
|
-
max-width: 980px;
|
|
44
|
-
margin: 24px auto 80px;
|
|
45
|
-
padding: 0 16px;
|
|
46
|
-
}
|
|
47
|
-
header {
|
|
48
|
-
margin: 8px 0 22px;
|
|
49
|
-
}
|
|
50
|
-
h1 {
|
|
51
|
-
font-size: clamp(24px, 3.6vw, 34px);
|
|
52
|
-
margin: 0 0 6px;
|
|
53
|
-
letter-spacing: -0.02em;
|
|
54
|
-
}
|
|
55
|
-
.subtitle {
|
|
56
|
-
color: var(--muted);
|
|
57
|
-
font-size: 14px;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/* Vertical cards */
|
|
61
|
-
.card {
|
|
62
|
-
background: var(--card);
|
|
63
|
-
border: 1px solid var(--border);
|
|
64
|
-
border-radius: 18px;
|
|
65
|
-
padding: 20px clamp(16px, 2vw, 26px);
|
|
66
|
-
margin: 14px 0;
|
|
67
|
-
box-shadow:
|
|
68
|
-
0 10px 24px rgba(2, 8, 23, 0.04),
|
|
69
|
-
0 2px 6px rgba(2, 8, 23, 0.03);
|
|
70
|
-
}
|
|
71
|
-
.card h2 {
|
|
72
|
-
display: flex;
|
|
73
|
-
align-items: center;
|
|
74
|
-
gap: 10px;
|
|
75
|
-
font-size: clamp(18px, 2.6vw, 22px);
|
|
76
|
-
margin: 0 0 10px;
|
|
77
|
-
}
|
|
78
|
-
.k-pill {
|
|
79
|
-
display: inline-flex;
|
|
80
|
-
align-items: center;
|
|
81
|
-
gap: 8px;
|
|
82
|
-
padding: 6px 10px;
|
|
83
|
-
border-radius: 999px;
|
|
84
|
-
background: #eaf6fe;
|
|
85
|
-
color: #0369a1;
|
|
86
|
-
border: 1px solid #d7eefc;
|
|
87
|
-
font-size: 12px;
|
|
88
|
-
text-transform: uppercase;
|
|
89
|
-
letter-spacing: 0.06em;
|
|
90
|
-
font-weight: 650;
|
|
91
|
-
}
|
|
92
|
-
.stats {
|
|
93
|
-
display: grid;
|
|
94
|
-
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
95
|
-
gap: 12px;
|
|
96
|
-
margin-top: 10px;
|
|
97
|
-
}
|
|
98
|
-
.stat {
|
|
99
|
-
background: #fcfdff;
|
|
100
|
-
border: 1px solid var(--border);
|
|
101
|
-
border-radius: 14px;
|
|
102
|
-
padding: 10px 14px;
|
|
103
|
-
}
|
|
104
|
-
.stat .label {
|
|
105
|
-
color: var(--muted);
|
|
106
|
-
font-size: 12px;
|
|
107
|
-
text-transform: uppercase;
|
|
108
|
-
letter-spacing: 0.06em;
|
|
109
|
-
}
|
|
110
|
-
.stat .value {
|
|
111
|
-
font-size: 20px;
|
|
112
|
-
font-weight: 700;
|
|
113
|
-
margin-top: 2px;
|
|
114
|
-
}
|
|
115
|
-
.muted {
|
|
116
|
-
color: var(--muted);
|
|
117
|
-
}
|
|
118
|
-
.mono {
|
|
119
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
|
|
120
|
-
}
|
|
121
|
-
.codebox {
|
|
122
|
-
background: #0b1220;
|
|
123
|
-
color: #d7e2ff;
|
|
124
|
-
border-radius: 14px;
|
|
125
|
-
padding: 14px 16px;
|
|
126
|
-
overflow: auto;
|
|
127
|
-
border: 1px solid #1e2a44;
|
|
128
|
-
}
|
|
129
|
-
table {
|
|
130
|
-
width: 100%;
|
|
131
|
-
border-collapse: collapse;
|
|
132
|
-
}
|
|
133
|
-
th,
|
|
134
|
-
td {
|
|
135
|
-
padding: 8px 10px;
|
|
136
|
-
text-align: left;
|
|
137
|
-
border-bottom: 1px dashed var(--border);
|
|
138
|
-
}
|
|
139
|
-
th {
|
|
140
|
-
font-size: 12px;
|
|
141
|
-
color: var(--muted);
|
|
142
|
-
text-transform: uppercase;
|
|
143
|
-
letter-spacing: 0.06em;
|
|
144
|
-
}
|
|
145
|
-
tbody tr:hover {
|
|
146
|
-
background: #fafcff;
|
|
147
|
-
}
|
|
148
|
-
details {
|
|
149
|
-
border: 1px dashed var(--border);
|
|
150
|
-
border-radius: 12px;
|
|
151
|
-
padding: 10px 12px;
|
|
152
|
-
background: #fbfdff;
|
|
153
|
-
}
|
|
154
|
-
details + details {
|
|
155
|
-
margin-top: 10px;
|
|
156
|
-
}
|
|
157
|
-
summary {
|
|
158
|
-
cursor: pointer;
|
|
159
|
-
font-weight: 600;
|
|
160
|
-
}
|
|
161
|
-
.chips {
|
|
162
|
-
display: flex;
|
|
163
|
-
flex-wrap: wrap;
|
|
164
|
-
gap: 8px;
|
|
165
|
-
margin: 8px 0 0;
|
|
166
|
-
}
|
|
167
|
-
.chip {
|
|
168
|
-
background: #f1f5f9;
|
|
169
|
-
border: 1px solid var(--border);
|
|
170
|
-
padding: 6px 10px;
|
|
171
|
-
border-radius: 999px;
|
|
172
|
-
font-variant-numeric: tabular-nums;
|
|
173
|
-
}
|
|
174
|
-
.footer-note {
|
|
175
|
-
font-size: 12px;
|
|
176
|
-
color: var(--muted);
|
|
177
|
-
margin-top: 8px;
|
|
178
|
-
}
|
|
179
|
-
.small {
|
|
180
|
-
font-size: 13px;
|
|
181
|
-
}
|
|
182
|
-
.accent {
|
|
183
|
-
color: var(--accent);
|
|
184
|
-
font-weight: 700;
|
|
185
|
-
}
|
|
186
|
-
.sep {
|
|
187
|
-
height: 8px;
|
|
188
|
-
}
|
|
189
|
-
.kbd {
|
|
190
|
-
font-weight: 650;
|
|
191
|
-
border: 1px solid var(--border);
|
|
192
|
-
background: #fff;
|
|
193
|
-
padding: 2px 6px;
|
|
194
|
-
border-radius: 6px;
|
|
195
|
-
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.05);
|
|
196
|
-
}
|
|
197
|
-
.badge {
|
|
198
|
-
display: inline-flex;
|
|
199
|
-
align-items: center;
|
|
200
|
-
gap: 6px;
|
|
201
|
-
padding: 2px 8px;
|
|
202
|
-
border-radius: 999px;
|
|
203
|
-
border: 1px solid var(--border);
|
|
204
|
-
font-size: 12px;
|
|
205
|
-
font-weight: 700;
|
|
206
|
-
}
|
|
207
|
-
.badge.pass {
|
|
208
|
-
background: #ecfdf5;
|
|
209
|
-
border-color: #bbf7d0;
|
|
210
|
-
color: #065f46;
|
|
211
|
-
}
|
|
212
|
-
.badge.fail {
|
|
213
|
-
background: #fef2f2;
|
|
214
|
-
border-color: #fecaca;
|
|
215
|
-
color: #7f1d1d;
|
|
216
|
-
}
|
|
217
|
-
</style>
|
|
218
|
-
</head>
|
|
219
|
-
<body>
|
|
220
|
-
<div class="container">
|
|
221
|
-
<header>
|
|
222
|
-
<h1>Euclid’s Infinitude of Primes</h1>
|
|
223
|
-
<div class="subtitle">
|
|
224
|
-
A P3-style, client‑side demo: we restate the theorem, explain Euclid’s one‑line proof, and run computational
|
|
225
|
-
checks (sieve, Euclid constructions, and prime-count growth) to corroborate it.
|
|
226
|
-
</div>
|
|
227
|
-
</header>
|
|
228
|
-
|
|
229
|
-
<!-- 1/ Answer -->
|
|
230
|
-
<section class="card" aria-labelledby="answer-title">
|
|
231
|
-
<h2 id="answer-title"><span class="k-pill">1/ Answer</span> Concise results</h2>
|
|
232
|
-
<p>
|
|
233
|
-
There are <strong>infinitely many prime numbers</strong>. Below we also compute evidence up to a large bound.
|
|
234
|
-
</p>
|
|
235
|
-
<div class="stats">
|
|
236
|
-
<div class="stat">
|
|
237
|
-
<div class="label">Bound checked</div>
|
|
238
|
-
<div class="value mono" id="bound">—</div>
|
|
239
|
-
</div>
|
|
240
|
-
<div class="stat">
|
|
241
|
-
<div class="label">π(x) at bound</div>
|
|
242
|
-
<div class="value mono" id="piBound">—</div>
|
|
243
|
-
</div>
|
|
244
|
-
<div class="stat">
|
|
245
|
-
<div class="label">Largest prime ≤ bound</div>
|
|
246
|
-
<div class="value mono" id="largestPrime">—</div>
|
|
247
|
-
</div>
|
|
248
|
-
<div class="stat">
|
|
249
|
-
<div class="label">Max prime gap ≤ bound</div>
|
|
250
|
-
<div class="value mono" id="maxGap">—</div>
|
|
251
|
-
</div>
|
|
252
|
-
<div class="stat">
|
|
253
|
-
<div class="label">π(x) / (x / ln x)</div>
|
|
254
|
-
<div class="value mono" id="ratio">—</div>
|
|
255
|
-
</div>
|
|
256
|
-
</div>
|
|
257
|
-
<div class="footer-note">
|
|
258
|
-
Here π(x) counts primes ≤ x. We compute all primes up to the bound in your browser via a sieve.
|
|
259
|
-
</div>
|
|
260
|
-
</section>
|
|
261
|
-
|
|
262
|
-
<!-- 2/ Reason why -->
|
|
263
|
-
<section class="card" aria-labelledby="reason-title">
|
|
264
|
-
<h2 id="reason-title"><span class="k-pill">2/ Reason why</span> Euclid’s proof (mathematical English)</h2>
|
|
265
|
-
<div class="proofbox small">
|
|
266
|
-
<p><strong>Claim.</strong> There are infinitely many prime numbers.</p>
|
|
267
|
-
<p>
|
|
268
|
-
<strong>Proof.</strong> Assume for contradiction that only finitely many primes exist. List them as
|
|
269
|
-
<em>p</em><sub>1</sub> ≤ <em>p</em><sub>2</sub> ≤ … ≤ <em>p</em><sub>k</sub>. Define
|
|
270
|
-
<span class="mono">N = p</span><sub>1</sub><span class="mono">p</span><sub>2</sub
|
|
271
|
-
><span class="mono">⋯p</span><sub>k</sub><span class="mono"> + 1</span>.
|
|
272
|
-
</p>
|
|
273
|
-
<p>
|
|
274
|
-
For each index <em>i</em>, division of <em>N</em> by <em>p</em><sub>i</sub> leaves remainder 1;
|
|
275
|
-
equivalently, <em>N</em> is not divisible by any of <em>p</em><sub>1</sub>, …, <em>p</em><sub>k</sub>.
|
|
276
|
-
</p>
|
|
277
|
-
<p>
|
|
278
|
-
Since <em>N</em> > 1, it has a prime divisor <em>q</em>. Because none of <em>p</em><sub>1</sub>, …,
|
|
279
|
-
<em>p</em><sub>k</sub> divides <em>N</em>, this prime <em>q</em> is different from every prime on the list,
|
|
280
|
-
contradicting the assumption that the list contained all primes. Therefore the set of primes is infinite. ∎
|
|
281
|
-
</p>
|
|
282
|
-
</div>
|
|
283
|
-
<p class="small muted">
|
|
284
|
-
The reasoning does not search for “the last prime”: it shows that <em>every</em> finite list of primes can be
|
|
285
|
-
extended.
|
|
286
|
-
</p>
|
|
287
|
-
</section>
|
|
288
|
-
|
|
289
|
-
<!-- 3/ Checks (five, uncollapsed) -->
|
|
290
|
-
<section class="card" aria-labelledby="check-title">
|
|
291
|
-
<h2 id="check-title"><span class="k-pill">3/ Checks</span> Computed in the browser</h2>
|
|
292
|
-
|
|
293
|
-
<details open id="check1">
|
|
294
|
-
<summary>Check 1 — Sieve sanity (tiny set) <span class="badge" id="chk1badge">—</span></summary>
|
|
295
|
-
<p class="small">Verify some known primes/composites are classified correctly.</p>
|
|
296
|
-
<div class="chips">
|
|
297
|
-
<span class="chip mono">primes ok: <span id="chk1p">—</span></span
|
|
298
|
-
><span class="chip mono">composites ok: <span id="chk1c">—</span></span>
|
|
299
|
-
</div>
|
|
300
|
-
</details>
|
|
301
|
-
|
|
302
|
-
<div class="sep"></div>
|
|
303
|
-
|
|
304
|
-
<details open id="check2">
|
|
305
|
-
<summary>
|
|
306
|
-
Check 2 — Euclid step on first k primes (k = 3…10) <span class="badge" id="chk2badge">—</span>
|
|
307
|
-
</summary>
|
|
308
|
-
<p class="small">For each k, build N = 1 + ∏<sub>i≤k</sub> pᵢ and find a prime factor q ∤ ∏ pᵢ.</p>
|
|
309
|
-
<table>
|
|
310
|
-
<thead>
|
|
311
|
-
<tr>
|
|
312
|
-
<th>k</th>
|
|
313
|
-
<th>∏ pᵢ + 1 (N)</th>
|
|
314
|
-
<th>found factor q</th>
|
|
315
|
-
<th>q in first k?</th>
|
|
316
|
-
</tr>
|
|
317
|
-
</thead>
|
|
318
|
-
<tbody id="euclid-k"></tbody>
|
|
319
|
-
</table>
|
|
320
|
-
</details>
|
|
321
|
-
|
|
322
|
-
<div class="sep"></div>
|
|
323
|
-
|
|
324
|
-
<details open id="check3">
|
|
325
|
-
<summary>Check 3 — π(10²)…π(10⁶) strictly increases <span class="badge" id="chk3badge">—</span></summary>
|
|
326
|
-
<table>
|
|
327
|
-
<thead>
|
|
328
|
-
<tr>
|
|
329
|
-
<th>x</th>
|
|
330
|
-
<th>π(x)</th>
|
|
331
|
-
<th>x/ln x</th>
|
|
332
|
-
<th>ratio</th>
|
|
333
|
-
</tr>
|
|
334
|
-
</thead>
|
|
335
|
-
<tbody id="pi-table"></tbody>
|
|
336
|
-
</table>
|
|
337
|
-
</details>
|
|
338
|
-
|
|
339
|
-
<div class="sep"></div>
|
|
340
|
-
|
|
341
|
-
<details open id="check4">
|
|
342
|
-
<summary>
|
|
343
|
-
Check 4 — Sample Bertrand intervals contain a prime <span class="badge" id="chk4badge">—</span>
|
|
344
|
-
</summary>
|
|
345
|
-
<p class="small">For selected n, we confirm a prime exists in (n, 2n].</p>
|
|
346
|
-
<div id="bertrand" class="chips"></div>
|
|
347
|
-
</details>
|
|
348
|
-
|
|
349
|
-
<div class="sep"></div>
|
|
350
|
-
|
|
351
|
-
<details open id="check5">
|
|
352
|
-
<summary>Check 5 — Random Euclid sets (mod‑1 property) <span class="badge" id="chk5badge">—</span></summary>
|
|
353
|
-
<p class="small">
|
|
354
|
-
Random small prime sets S ⊂ {first 15 primes}; we verify (∏S + 1) mod p = 1 for all p∈S. This guarantees
|
|
355
|
-
every prime factor of ∏S+1 is outside S.
|
|
356
|
-
</p>
|
|
357
|
-
<div id="rand-euclid" class="chips"></div>
|
|
358
|
-
</details>
|
|
359
|
-
</section>
|
|
360
|
-
|
|
361
|
-
<section class="card" aria-labelledby="appendix-title">
|
|
362
|
-
<h2 id="appendix-title"><span class="k-pill">Appendix</span> Implementation notes</h2>
|
|
363
|
-
<ul class="small">
|
|
364
|
-
<li>
|
|
365
|
-
Sieve of Eratosthenes up to the bound; all numbers are native JS <span class="mono">Number</span> unless
|
|
366
|
-
BigInt is needed for intermediate products.
|
|
367
|
-
</li>
|
|
368
|
-
<li>Euclid constructions for k≤10 are easily factored with the prime list (√N is small).</li>
|
|
369
|
-
</ul>
|
|
370
|
-
</section>
|
|
371
|
-
</div>
|
|
372
|
-
|
|
373
|
-
<script>
|
|
374
|
-
// ===== Utilities =====
|
|
375
|
-
const LIMIT = 1_000_000; // bound for sieve and stats
|
|
376
|
-
const isPrime = new Uint8Array(LIMIT + 1);
|
|
377
|
-
const primes = [];
|
|
378
|
-
|
|
379
|
-
function sieve(n = LIMIT) {
|
|
380
|
-
for (let i = 0; i <= n; i++) isPrime[i] = 1;
|
|
381
|
-
isPrime[0] = 0;
|
|
382
|
-
isPrime[1] = 0;
|
|
383
|
-
for (let p = 2; p * p <= n; p++) if (isPrime[p]) for (let m = p * p; m <= n; m += p) isPrime[m] = 0;
|
|
384
|
-
for (let i = 2; i <= n; i++) if (isPrime[i]) primes.push(i);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
function pi(x) {
|
|
388
|
-
// count primes ≤ x
|
|
389
|
-
// primes is sorted
|
|
390
|
-
let lo = 0,
|
|
391
|
-
hi = primes.length; // count of elements ≤ x
|
|
392
|
-
while (lo < hi) {
|
|
393
|
-
const mid = (lo + hi) >> 1;
|
|
394
|
-
if (primes[mid] <= x) lo = mid + 1;
|
|
395
|
-
else hi = mid;
|
|
396
|
-
}
|
|
397
|
-
return lo;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
function largestPrimeLE(x) {
|
|
401
|
-
let idx = pi(x) - 1;
|
|
402
|
-
return idx >= 0 ? primes[idx] : null;
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
function maxPrimeGapUpTo(x) {
|
|
406
|
-
let last = 2,
|
|
407
|
-
mx = 0;
|
|
408
|
-
for (const p of primes) {
|
|
409
|
-
if (p > x) break;
|
|
410
|
-
mx = Math.max(mx, p - last);
|
|
411
|
-
last = p;
|
|
412
|
-
}
|
|
413
|
-
return mx;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
function smallestPrimeFactor(n) {
|
|
417
|
-
// n is Number, n>=2
|
|
418
|
-
const r = Math.floor(Math.sqrt(n));
|
|
419
|
-
for (const p of primes) {
|
|
420
|
-
if (p > r) break;
|
|
421
|
-
if (n % p === 0) return p;
|
|
422
|
-
}
|
|
423
|
-
return n; // n is prime
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
function productFirstK(k) {
|
|
427
|
-
let prod = 1;
|
|
428
|
-
for (let i = 0; i < k; i++) prod *= primes[i];
|
|
429
|
-
return prod;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
// ===== Run computations =====
|
|
433
|
-
sieve();
|
|
434
|
-
|
|
435
|
-
// Answer stats
|
|
436
|
-
const piBound = pi(LIMIT);
|
|
437
|
-
const lp = largestPrimeLE(LIMIT);
|
|
438
|
-
const gap = maxPrimeGapUpTo(LIMIT);
|
|
439
|
-
const ratio = (piBound / (LIMIT / Math.log(LIMIT))).toFixed(4);
|
|
440
|
-
document.getElementById('bound').textContent = LIMIT.toLocaleString();
|
|
441
|
-
document.getElementById('piBound').textContent = piBound.toLocaleString();
|
|
442
|
-
document.getElementById('largestPrime').textContent = lp?.toLocaleString?.() ?? '—';
|
|
443
|
-
document.getElementById('maxGap').textContent = gap.toLocaleString();
|
|
444
|
-
document.getElementById('ratio').textContent = ratio;
|
|
445
|
-
|
|
446
|
-
// ===== Checks & badges =====
|
|
447
|
-
function setBadge(id, ok) {
|
|
448
|
-
const el = document.getElementById(id + 'badge');
|
|
449
|
-
if (!el) return;
|
|
450
|
-
el.textContent = ok ? 'PASS' : 'FAIL';
|
|
451
|
-
el.className = 'badge ' + (ok ? 'pass' : 'fail');
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
// Check 1 — Sieve sanity
|
|
455
|
-
(function () {
|
|
456
|
-
const knownP = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 97, 9973].filter((x) => x <= LIMIT);
|
|
457
|
-
const knownC = [1, 4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 10000].filter((x) => x <= LIMIT);
|
|
458
|
-
const pOK = knownP.every((x) => isPrime[x] === 1);
|
|
459
|
-
const cOK = knownC.every((x) => isPrime[x] === 0);
|
|
460
|
-
document.getElementById('chk1p').textContent = pOK ? 'OK' : 'MISS';
|
|
461
|
-
document.getElementById('chk1c').textContent = cOK ? 'OK' : 'MISS';
|
|
462
|
-
setBadge('chk1', pOK && cOK);
|
|
463
|
-
})();
|
|
464
|
-
|
|
465
|
-
// Check 2 — Euclid step on first k primes
|
|
466
|
-
(function () {
|
|
467
|
-
const tbody = document.getElementById('euclid-k');
|
|
468
|
-
let allOK = true;
|
|
469
|
-
for (let k = 3; k <= 10; k++) {
|
|
470
|
-
const prod = productFirstK(k);
|
|
471
|
-
const N = prod + 1;
|
|
472
|
-
const q = smallestPrimeFactor(N);
|
|
473
|
-
const inFirst = primes.slice(0, k).includes(q);
|
|
474
|
-
const tr = document.createElement('tr');
|
|
475
|
-
tr.innerHTML = `<td>${k}</td><td class="mono">${N.toLocaleString()}</td><td class="mono">${q.toLocaleString()}</td><td>${inFirst ? 'yes' : 'no'}</td>`;
|
|
476
|
-
tbody.appendChild(tr);
|
|
477
|
-
if (inFirst) allOK = false;
|
|
478
|
-
}
|
|
479
|
-
setBadge('chk2', allOK);
|
|
480
|
-
})();
|
|
481
|
-
|
|
482
|
-
// Check 3 — π(10^2)…π(10^6) strictly increases
|
|
483
|
-
(function () {
|
|
484
|
-
const xs = [1e2, 1e3, 1e4, 1e5, 1e6];
|
|
485
|
-
const tbody = document.getElementById('pi-table');
|
|
486
|
-
let ok = true,
|
|
487
|
-
last = -1;
|
|
488
|
-
for (const x of xs) {
|
|
489
|
-
const pcount = pi(x);
|
|
490
|
-
if (pcount <= last) ok = false;
|
|
491
|
-
last = pcount;
|
|
492
|
-
const approx = x / Math.log(x);
|
|
493
|
-
const tr = document.createElement('tr');
|
|
494
|
-
tr.innerHTML = `<td class="mono">${x.toLocaleString()}</td><td class="mono">${pcount.toLocaleString()}</td><td class="mono">${approx.toFixed(0)}</td><td class="mono">${(pcount / approx).toFixed(4)}</td>`;
|
|
495
|
-
tbody.appendChild(tr);
|
|
496
|
-
}
|
|
497
|
-
setBadge('chk3', ok);
|
|
498
|
-
})();
|
|
499
|
-
|
|
500
|
-
// Check 4 — Sample Bertrand intervals contain a prime
|
|
501
|
-
(function () {
|
|
502
|
-
const samples = [10, 20, 50, 100, 500, 1_000, 5_000, 10_000, 50_000, 100_000, 200_000, 300_000, 400_000];
|
|
503
|
-
const wrap = document.getElementById('bertrand');
|
|
504
|
-
let ok = true;
|
|
505
|
-
for (const n of samples) {
|
|
506
|
-
const a = n + 1,
|
|
507
|
-
b = Math.min(2 * n, LIMIT);
|
|
508
|
-
let has = false;
|
|
509
|
-
for (let x = a; x <= b; x++) {
|
|
510
|
-
if (isPrime[x]) {
|
|
511
|
-
has = true;
|
|
512
|
-
break;
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
const chip = document.createElement('span');
|
|
516
|
-
chip.className = 'chip mono';
|
|
517
|
-
chip.textContent = `${n.toLocaleString()}→${(2 * n).toLocaleString()}: ${has ? 'prime found' : 'none'}`;
|
|
518
|
-
wrap.appendChild(chip);
|
|
519
|
-
if (!has) ok = false;
|
|
520
|
-
}
|
|
521
|
-
setBadge('chk4', ok);
|
|
522
|
-
})();
|
|
523
|
-
|
|
524
|
-
// Check 5 — Random Euclid sets (mod‑1 property)
|
|
525
|
-
(function () {
|
|
526
|
-
const wrap = document.getElementById('rand-euclid');
|
|
527
|
-
const base = primes.slice(0, 15);
|
|
528
|
-
const trials = 20;
|
|
529
|
-
let ok = true;
|
|
530
|
-
function randInt(a, b) {
|
|
531
|
-
return Math.floor(Math.random() * (b - a + 1)) + a;
|
|
532
|
-
}
|
|
533
|
-
for (let t = 0; t < trials; t++) {
|
|
534
|
-
const size = randInt(2, 6);
|
|
535
|
-
// build a random subset without replacement
|
|
536
|
-
const pool = base.slice();
|
|
537
|
-
for (let i = pool.length - 1; i > 0; i--) {
|
|
538
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
539
|
-
[pool[i], pool[j]] = [pool[j], pool[i]];
|
|
540
|
-
}
|
|
541
|
-
const S = pool.slice(0, size);
|
|
542
|
-
let prod = 1;
|
|
543
|
-
for (const p of S) {
|
|
544
|
-
prod *= p;
|
|
545
|
-
}
|
|
546
|
-
const N = prod + 1;
|
|
547
|
-
let allOne = true;
|
|
548
|
-
for (const p of S) {
|
|
549
|
-
if (N % p !== 1) {
|
|
550
|
-
allOne = false;
|
|
551
|
-
break;
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
const chip = document.createElement('span');
|
|
555
|
-
chip.className = 'chip mono';
|
|
556
|
-
chip.textContent = `{${S.join(',')}} ⇒ Π+1=${N.toLocaleString()} (mod p = 1: ${allOne ? 'yes' : 'no'})`;
|
|
557
|
-
wrap.appendChild(chip);
|
|
558
|
-
if (!allOne) ok = false;
|
|
559
|
-
}
|
|
560
|
-
setBadge('chk5', ok);
|
|
561
|
-
})();
|
|
562
|
-
</script>
|
|
563
|
-
</body>
|
|
564
|
-
</html>
|