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.
Files changed (45) hide show
  1. package/README.md +0 -1
  2. package/package.json +2 -3
  3. package/arctifacts/README.md +0 -59
  4. package/arctifacts/ackermann.html +0 -678
  5. package/arctifacts/auroracare.html +0 -1297
  6. package/arctifacts/bike-trip.html +0 -752
  7. package/arctifacts/binomial-theorem.html +0 -631
  8. package/arctifacts/bmi.html +0 -511
  9. package/arctifacts/building-performance.html +0 -750
  10. package/arctifacts/clinical-care.html +0 -726
  11. package/arctifacts/collatz.html +0 -403
  12. package/arctifacts/complex.html +0 -321
  13. package/arctifacts/control-system.html +0 -482
  14. package/arctifacts/delfour.html +0 -849
  15. package/arctifacts/earthquake-epicenter.html +0 -982
  16. package/arctifacts/eco-route.html +0 -662
  17. package/arctifacts/euclid-infinitude.html +0 -564
  18. package/arctifacts/euler-identity.html +0 -667
  19. package/arctifacts/exoplanet-transit.html +0 -1000
  20. package/arctifacts/faltings-theorem.html +0 -1046
  21. package/arctifacts/fibonacci.html +0 -299
  22. package/arctifacts/fundamental-theorem-arithmetic.html +0 -398
  23. package/arctifacts/godel-numbering.html +0 -743
  24. package/arctifacts/gps-bike.html +0 -759
  25. package/arctifacts/gps-clinical-bench.html +0 -792
  26. package/arctifacts/graph-french.html +0 -449
  27. package/arctifacts/grass-molecular.html +0 -592
  28. package/arctifacts/group-theory.html +0 -740
  29. package/arctifacts/health-info.html +0 -833
  30. package/arctifacts/kaprekar-constant.html +0 -576
  31. package/arctifacts/lee.html +0 -805
  32. package/arctifacts/linked-lists.html +0 -502
  33. package/arctifacts/lldm.html +0 -612
  34. package/arctifacts/matrix-multiplication.html +0 -502
  35. package/arctifacts/matrix.html +0 -651
  36. package/arctifacts/newton-raphson.html +0 -944
  37. package/arctifacts/peano-factorial.html +0 -456
  38. package/arctifacts/pi.html +0 -363
  39. package/arctifacts/polynomial.html +0 -646
  40. package/arctifacts/prime.html +0 -366
  41. package/arctifacts/pythagorean-theorem.html +0 -468
  42. package/arctifacts/rest-path.html +0 -469
  43. package/arctifacts/roots-of-unity.html +0 -363
  44. package/arctifacts/turing.html +0 -409
  45. package/arctifacts/wind-turbines.html +0 -726
@@ -1,667 +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>Euler's Identity</title>
7
- <style>
8
- :root {
9
- --bg: #f7f9fc;
10
- --card: #ffffff;
11
- --text: #0f172a;
12
- --muted: #475569;
13
- --accent: #2563eb;
14
- --good: #16a34a;
15
- --bad: #dc2626;
16
- --border: #e2e8f0;
17
- --chip: #eef2ff;
18
- --code: #111827;
19
- }
20
- html,
21
- body {
22
- background: var(--bg);
23
- color: var(--text);
24
- font-family:
25
- ui-sans-serif,
26
- system-ui,
27
- -apple-system,
28
- Segoe UI,
29
- Roboto,
30
- Helvetica,
31
- Arial,
32
- 'Apple Color Emoji',
33
- 'Segoe UI Emoji';
34
- }
35
- * {
36
- box-sizing: border-box;
37
- }
38
- .container {
39
- max-width: 960px;
40
- margin: 24px auto;
41
- padding: 0 16px;
42
- }
43
- header {
44
- display: flex;
45
- flex-direction: column;
46
- gap: 8px;
47
- margin-bottom: 16px;
48
- }
49
- h1 {
50
- font-size: 1.8rem;
51
- margin: 0;
52
- letter-spacing: -0.02em;
53
- }
54
- .subtitle {
55
- color: var(--muted);
56
- }
57
- .card {
58
- background: var(--card);
59
- border: 1px solid var(--border);
60
- border-radius: 16px;
61
- padding: 16px;
62
- box-shadow: 0 6px 20px rgba(2, 6, 23, 0.05);
63
- }
64
- .stack {
65
- display: flex;
66
- flex-direction: column;
67
- gap: 16px;
68
- }
69
- .pill {
70
- display: inline-flex;
71
- align-items: center;
72
- gap: 8px;
73
- padding: 4px 10px;
74
- background: var(--chip);
75
- color: #1e3a8a;
76
- border-radius: 999px;
77
- font-size: 12px;
78
- font-weight: 600;
79
- border: 1px solid #c7d2fe;
80
- }
81
- .row {
82
- display: flex;
83
- gap: 12px;
84
- align-items: center;
85
- min-width: 0;
86
- flex-wrap: wrap;
87
- }
88
- input[type='number'] {
89
- width: 160px;
90
- padding: 10px 12px;
91
- border-radius: 10px;
92
- border: 1px solid var(--border);
93
- background: #fbfdff;
94
- }
95
- button {
96
- appearance: none;
97
- border: none;
98
- background: var(--accent);
99
- color: white;
100
- padding: 10px 14px;
101
- border-radius: 12px;
102
- font-weight: 700;
103
- cursor: pointer;
104
- box-shadow: 0 4px 14px rgba(37, 99, 235, 0.25);
105
- }
106
- button.secondary {
107
- background: #0ea5e9;
108
- }
109
- button.ghost {
110
- background: transparent;
111
- color: var(--accent);
112
- border: 1px solid var(--accent);
113
- }
114
- .muted {
115
- color: var(--muted);
116
- }
117
- .mono {
118
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
119
- color: var(--code);
120
- word-break: break-word;
121
- overflow-wrap: anywhere;
122
- white-space: normal;
123
- }
124
- .kpi {
125
- display: flex;
126
- gap: 16px;
127
- flex-wrap: wrap;
128
- }
129
- .kpi .card {
130
- padding: 12px 14px;
131
- }
132
- .k {
133
- font-weight: 700;
134
- }
135
- .v {
136
- font-variant-numeric: tabular-nums;
137
- word-break: break-word;
138
- overflow-wrap: anywhere;
139
- }
140
- .list {
141
- display: flex;
142
- flex-direction: column;
143
- gap: 12px;
144
- }
145
- .term {
146
- padding: 10px;
147
- background: #f8fafc;
148
- border: 1px dashed var(--border);
149
- border-radius: 12px;
150
- }
151
- details {
152
- border: 1px solid var(--border);
153
- border-radius: 12px;
154
- padding: 10px 12px;
155
- background: #fafcff;
156
- }
157
- details summary {
158
- cursor: pointer;
159
- font-weight: 700;
160
- color: #0b3eaa;
161
- }
162
- .badge {
163
- padding: 2px 8px;
164
- border-radius: 999px;
165
- font-weight: 700;
166
- font-size: 12px;
167
- border: 1px solid #cbd5e1;
168
- background: #f1f5f9;
169
- color: #0f172a;
170
- }
171
- .ok {
172
- background: #dcfce7;
173
- color: #166534;
174
- border: 1px solid #86efac;
175
- }
176
- .fail {
177
- background: #fee2e2;
178
- color: #991b1b;
179
- border: 1px solid #fecaca;
180
- }
181
- .harness {
182
- border-left: 6px solid #c7d2fe;
183
- }
184
- .h-title {
185
- display: flex;
186
- align-items: center;
187
- justify-content: space-between;
188
- gap: 8px;
189
- }
190
- .small {
191
- font-size: 12px;
192
- }
193
- code {
194
- background: #f1f5f9;
195
- padding: 2px 6px;
196
- border-radius: 6px;
197
- }
198
- footer {
199
- color: var(--muted);
200
- font-size: 12px;
201
- text-align: center;
202
- margin: 16px 0 40px;
203
- }
204
- .divider {
205
- height: 1px;
206
- background: var(--border);
207
- margin: -4px 0 8px;
208
- }
209
- svg {
210
- width: 100%;
211
- height: auto;
212
- background: #ffffff;
213
- border: 1px solid var(--border);
214
- border-radius: 12px;
215
- }
216
- .input-grid {
217
- flex-wrap: nowrap;
218
- gap: 10px;
219
- }
220
- .field {
221
- display: flex;
222
- align-items: center;
223
- gap: 6px;
224
- }
225
- input.short {
226
- width: 110px;
227
- padding: 6px 8px;
228
- }
229
- .buttons-row {
230
- gap: 8px;
231
- }
232
- @media (max-width: 520px) {
233
- .input-grid {
234
- flex-wrap: wrap;
235
- }
236
- }
237
- </style>
238
- </head>
239
- <body>
240
- <div class="container stack">
241
- <header class="card stack">
242
- <div class="row" style="justify-content: space-between; align-items: flex-start; width: 100%">
243
- <div>
244
- <h1>Euler's identity</h1>
245
- </div>
246
- </div>
247
- <span class="badge">Problem: e^{iπ} + 1 = 0</span>
248
- <p class="muted">
249
- This page states Euler's identity, explains why <span class="mono">e^{iπ} = -1</span> in mathematical English,
250
- illustrates it on the unit circle, and verifies it numerically with a small test harness.
251
- </p>
252
- </header>
253
-
254
- <!-- SVG ILLUSTRATION -->
255
- <section class="card stack">
256
- <h2 style="margin: 0">Illustration</h2>
257
- <div class="divider"></div>
258
- <svg viewBox="0 0 600 300" role="img" aria-label="Unit circle with angle π showing e^{iπ} at (-1,0)">
259
- <defs>
260
- <marker
261
- id="arrow"
262
- markerWidth="8"
263
- markerHeight="8"
264
- refX="6"
265
- refY="3"
266
- orient="auto"
267
- markerUnits="strokeWidth">
268
- <path d="M0,0 L0,6 L6,3 z" fill="#0b3eaa" />
269
- </marker>
270
- </defs>
271
- <!-- background grid -->
272
- <rect x="0" y="0" width="600" height="300" fill="#fff" rx="12" />
273
- <!-- axes -->
274
- <g stroke="#cbd5e1" stroke-width="1">
275
- <line x1="50" y1="150" x2="550" y2="150" />
276
- <line x1="300" y1="20" x2="300" y2="280" />
277
- </g>
278
- <!-- unit circle -->
279
- <circle cx="300" cy="150" r="100" fill="none" stroke="#94a3b8" stroke-width="2" />
280
- <!-- angle arc π from +x to -x -->
281
- <path d="M 400 150 A 100 100 0 0 1 200 150" fill="none" stroke="#0b3eaa" stroke-width="3" />
282
- <text x="300" y="125" fill="#0b3eaa" text-anchor="middle" font-size="12">θ = π</text>
283
- <!-- vector e^{iπ} -->
284
- <line x1="300" y1="150" x2="200" y2="150" stroke="#0b3eaa" stroke-width="3" marker-end="url(#arrow)" />
285
- <!-- points 1 and -1 -->
286
- <circle cx="400" cy="150" r="4" fill="#22c55e" />
287
- <text x="400" y="140" fill="#166534" text-anchor="middle" font-size="12">1</text>
288
- <circle cx="200" cy="150" r="4" fill="#ef4444" />
289
- <text x="200" y="140" fill="#991b1b" text-anchor="middle" font-size="12">−1 = e^{iπ}</text>
290
- <!-- tip annotation e^{iπ}+1=0 showing cancellation -->
291
- <g>
292
- <line x1="200" y1="150" x2="400" y2="150" stroke="#10b981" stroke-dasharray="4 4" />
293
- <text x="300" y="170" fill="#0f172a" text-anchor="middle" font-size="12">e^{iπ} + 1 → 0</text>
294
- </g>
295
- <!-- axis labels -->
296
- <text x="555" y="160" fill="#475569" font-size="12">Re</text>
297
- <text x="310" y="25" fill="#475569" font-size="12">Im</text>
298
- </svg>
299
- <p class="small muted">
300
- The complex exponential <span class="mono">e^{iθ}</span> traces the unit circle. At
301
- <span class="mono">θ=π</span> the point is <span class="mono">−1</span>, so
302
- <span class="mono">e^{iπ}+1=0</span>.
303
- </p>
304
- </section>
305
-
306
- <!-- INPUT -->
307
- <section class="card stack" id="input-card">
308
- <h2 style="margin: 0">Input</h2>
309
- <div class="divider"></div>
310
- <div class="row input-grid">
311
- <div class="field">
312
- <label class="mono" for="kInput">k (integer)</label
313
- ><input class="short" id="kInput" type="number" step="1" value="0" />
314
- </div>
315
- <div class="field">
316
- <label class="mono" for="epsInput">ε (tolerance)</label
317
- ><input class="short" id="epsInput" type="number" step="any" value="1e-12" />
318
- </div>
319
- <div class="field">
320
- <label class="mono" for="NInput">Series terms N</label
321
- ><input class="short" id="NInput" type="number" min="1" step="1" value="40" />
322
- </div>
323
- </div>
324
- <div class="row buttons-row">
325
- <button type="button" id="solve">Evaluate</button>
326
- <button type="button" id="clear">Clear</button>
327
- </div>
328
- <p class="small muted">
329
- We evaluate at <span class="mono">θ = π + 2πk</span>. <strong>N</strong> is the number of terms used in the
330
- power‑series expansions for <span class="mono">cos</span> and <span class="mono">sin</span>; higher
331
- <strong>N</strong> gives a tighter approximation (30–50 is typically plenty after angle reduction to
332
- <span class="mono">[−π,π]</span>). The tolerance <span class="mono">ε</span> is used by the numerical checks.
333
- </p>
334
- </section>
335
-
336
- <!-- OUTPUT -->
337
- <section class="card stack" id="output-card" aria-live="polite">
338
- <h2 style="margin: 0">Output</h2>
339
- <div class="divider"></div>
340
-
341
- <!-- Answer KPIs -->
342
- <section class="stack">
343
- <div class="kpi">
344
- <div class="card">
345
- <div class="k">Answer</div>
346
- <div id="answer" class="v mono">—</div>
347
- </div>
348
- <div class="card">
349
- <div class="k">Angle θ</div>
350
- <div id="theta" class="v mono">—</div>
351
- </div>
352
- <div class="card">
353
- <div class="k">e^{iθ} (cos/sin)</div>
354
- <div id="cis" class="v mono">—</div>
355
- </div>
356
- <div class="card">
357
- <div class="k">Series approx</div>
358
- <div id="seriesVal" class="v mono">—</div>
359
- </div>
360
- </div>
361
- </section>
362
-
363
- <!-- Reason Why (mathematical English) -->
364
- <section class="stack">
365
- <h3 style="margin: 0">Reason Why</h3>
366
- <div class="list">
367
- <div class="term">
368
- <strong>Power‑series derivation.</strong>
369
- The exponential, sine, and cosine have the absolutely convergent series for real
370
- <span class="mono">x</span>:
371
- <div class="mono">
372
- e^z = Σ_{n≥0} z^n/n!,  cos x = Σ_{n≥0} (−1)^n x^{2n}/(2n)!,  sin x = Σ_{n≥0} (−1)^n x^{2n+1}/(2n+1)!.
373
- </div>
374
- Substituting <span class="mono">z = ix</span> and regrouping even/odd powers gives
375
- <span class="mono">e^{ix} = cos x + i sin x</span> (Euler's formula). Taking
376
- <span class="mono">x = π</span> yields <span class="mono">e^{iπ} = cos π + i sin π = −1 + i·0</span>,
377
- hence <span class="mono">e^{iπ} + 1 = 0</span>.
378
- </div>
379
- <div class="term">
380
- <strong>Differential‑equation proof.</strong>
381
- Define <span class="mono">f(x) = e^{-ix}(cos x + i sin x)</span>. Then
382
- <span class="mono">f'(x) = 0</span>, so <span class="mono">f</span> is constant. As
383
- <span class="mono">f(0)=1</span>, we have <span class="mono">f(x)=1</span> for all
384
- <span class="mono">x</span>, and again <span class="mono">e^{ix} = cos x + i sin x</span>.
385
- </div>
386
- <div class="term">
387
- <strong>Geometric picture.</strong>
388
- The map <span class="mono">x ↦ e^{ix}</span> parametrizes the unit circle counterclockwise. The angle
389
- <span class="mono">π</span> lands at <span class="mono">−1</span> on the real axis, so adding
390
- <span class="mono">1</span> returns the origin.
391
- </div>
392
- </div>
393
- </section>
394
-
395
- <!-- Check (harness) for the user's inputs -->
396
- <section class="stack">
397
- <h3 style="margin: 0">Check (harness)</h3>
398
- <div id="checks" class="list"></div>
399
- </section>
400
- </section>
401
-
402
- <!-- PRELOADED HARNESS CASES (≥ 8) -->
403
- <section class="card stack harness" id="preloaded">
404
- <div class="h-title">
405
- <h2 style="margin: 0">Preloaded Checks (harness)</h2>
406
- <div class="row">
407
- <button id="runAll">Run all</button>
408
- <button class="ghost" id="clearHarness">Clear results</button>
409
- </div>
410
- </div>
411
- <p class="small muted">
412
- Each block checks that <span class="mono">|e^{iθ}+1| ≤ ε</span> for <span class="mono">θ = π + 2πk</span> and
413
- fails for a noncongruent angle.
414
- </p>
415
- <div id="harnesses" class="stack"></div>
416
- </section>
417
-
418
- <footer>
419
- <div>Built as a self‑checking artifact: program → <em>Answer</em>, <em>Reason Why</em>, <em>Check</em>.</div>
420
- <div class="small">This page performs only on‑device computation.</div>
421
- </footer>
422
- </div>
423
-
424
- <script>
425
- // ---------- Math helpers ----------
426
- const TAU = Math.PI * 2;
427
- const normAngle = (t) => {
428
- // wrap to [-π, π]
429
- let x = ((((t + Math.PI) % TAU) + TAU) % TAU) - Math.PI; // robust modulo
430
- // handle −0
431
- return x === 0 ? 0 : x;
432
- };
433
- const cis = (t) => ({ re: Math.cos(t), im: Math.sin(t) });
434
- const add = (a, b) => ({ re: a.re + b.re, im: a.im + b.im });
435
- const abs = (z) => Math.hypot(z.re, z.im);
436
- const mul = (a, b) => ({ re: a.re * b.re - a.im * b.im, im: a.re * b.im + a.im * b.re });
437
- const powComplex = (z, n) => {
438
- let r = { re: 1, im: 0 };
439
- for (let i = 0; i < n; i++) r = mul(r, z);
440
- return r;
441
- };
442
-
443
- // power series for cos/sin with N terms and range reduction
444
- function cosSeries(x, N) {
445
- x = normAngle(x);
446
- let term = 1,
447
- sum = 1; // k=0
448
- for (let k = 1; k < N; k++) {
449
- term *= (-x * x) / ((2 * k - 1) * (2 * k));
450
- sum += term;
451
- }
452
- return sum;
453
- }
454
- function sinSeries(x, N) {
455
- x = normAngle(x);
456
- let term = x,
457
- sum = x; // k=0
458
- for (let k = 1; k < N; k++) {
459
- term *= (-x * x) / (2 * k * (2 * k + 1));
460
- sum += term;
461
- }
462
- return sum;
463
- }
464
-
465
- function evaluate() {
466
- const k = Number(document.getElementById('kInput').value || 0);
467
- const eps = Number(document.getElementById('epsInput').value || 1e-12);
468
- const N = Math.max(1, Number(document.getElementById('NInput').value || 40));
469
-
470
- const theta = Math.PI + TAU * k;
471
- const z = cis(theta);
472
- const sRe = cosSeries(theta, N),
473
- sIm = sinSeries(theta, N);
474
- const zSeries = { re: sRe, im: sIm };
475
-
476
- const ans = { re: z.re + 1, im: z.im };
477
- const ansSeries = { re: zSeries.re + 1, im: zSeries.im };
478
-
479
- document.getElementById('answer').textContent = `|e^{iπ+2πi·${k}} + 1| ≈ ${abs(ans).toExponential(3)}`;
480
- document.getElementById('theta').textContent = `θ = π + 2π·${k} ≈ ${theta.toPrecision(6)}`;
481
- document.getElementById('cis').textContent =
482
- `cos θ + i sin θ ≈ ${z.re.toPrecision(12)} + ${z.im.toPrecision(12)} i`;
483
- document.getElementById('seriesVal').textContent =
484
- `series_N=${N} ⇒ ${zSeries.re.toPrecision(12)} + ${zSeries.im.toPrecision(12)} i`;
485
-
486
- renderChecks(k, eps, N, theta, z, zSeries, ans, ansSeries);
487
- }
488
-
489
- function renderChecks(k, eps, N, theta, z, zSeries, ans, ansSeries) {
490
- const checks = document.getElementById('checks');
491
- const list = [];
492
-
493
- const eq = abs(ans) <= eps;
494
- list.push(row(eq, `Equality |e^{iθ}+1| ≤ ε`, `|⋅| ≈ ${abs(ans).toExponential(6)} ≤ ${eps}`));
495
-
496
- const reOk = Math.abs(z.re + 1) <= eps;
497
- list.push(
498
- row(reOk, `Real part ≈ −1`, `Re ≈ ${z.re.toPrecision(12)}, |Re+1| ≈ ${Math.abs(z.re + 1).toExponential(6)}`),
499
- );
500
-
501
- const imOk = Math.abs(z.im) <= eps;
502
- list.push(row(imOk, `Imag part ≈ 0`, `Im ≈ ${z.im.toPrecision(12)}`));
503
-
504
- const seriesOk = abs(ansSeries) <= Math.max(eps, 1e-15);
505
- list.push(row(seriesOk, `Series (N=${N})`, `|series+1| ≈ ${abs(ansSeries).toExponential(6)}`));
506
-
507
- const squareOk = abs(add(mul(z, z), { re: -1, im: 0 })) <= eps * 10; // |(e^{iπ})^2 - 1| small
508
- list.push(
509
- row(
510
- squareOk,
511
- `Square check`,
512
- `|(e^{iθ})^2 − 1| ≈ ${abs(add(mul(z, z), { re: -1, im: 0 })).toExponential(6)}`,
513
- ),
514
- );
515
-
516
- const periodicOk = abs(cis(theta + TAU)).toExponential
517
- ? abs(add(cis(theta + TAU), { re: 1, im: 0 })) <= eps
518
- : true;
519
- list.push(
520
- row(
521
- periodicOk,
522
- `Periodicity`,
523
- `θ → θ+2π ⇒ |e^{i(θ+2π)}+1| ≈ ${abs(add(cis(theta + TAU), { re: 1, im: 0 })).toExponential(6)}`,
524
- ),
525
- );
526
-
527
- list.push(
528
- el('div', { class: 'row' }, [
529
- el('span', { class: 'badge ok' }, ['FACT']),
530
- el('span', { class: 'small muted' }, ['Euler’s formula: e^{ix}=cos x+i sin x; at x=π we get −1.']),
531
- ]),
532
- );
533
-
534
- checks.replaceChildren(...list);
535
- }
536
-
537
- const row = (ok, label, msg) =>
538
- el('div', { class: 'row' }, [
539
- el('span', { class: 'badge ' + (ok ? 'ok' : 'fail') }, [ok ? 'PASS' : 'FAIL']),
540
- el('span', { class: 'mono' }, [label]),
541
- document.createTextNode(' — '),
542
- el('span', { class: 'mono' }, [msg]),
543
- ]);
544
-
545
- // ---------- UI helper ----------
546
- const el = (tag, attrs = {}, children = []) => {
547
- const node = document.createElement(tag);
548
- Object.entries(attrs).forEach(([k, v]) => {
549
- if (k === 'class') node.className = v;
550
- else if (k === 'html') node.innerHTML = v;
551
- else if (k.startsWith('on')) node.addEventListener(k.slice(2).toLowerCase(), v);
552
- else node.setAttribute(k, v);
553
- });
554
- children.forEach((c) => node.appendChild(typeof c === 'string' ? document.createTextNode(c) : c));
555
- return node;
556
- };
557
-
558
- document.getElementById('solve').onclick = evaluate;
559
- document.getElementById('clear').onclick = () => {
560
- document.getElementById('kInput').value = '0';
561
- document.getElementById('epsInput').value = '1e-12';
562
- document.getElementById('NInput').value = '40';
563
- document.getElementById('answer').textContent = '—';
564
- document.getElementById('theta').textContent = '—';
565
- document.getElementById('cis').textContent = '—';
566
- document.getElementById('seriesVal').textContent = '—';
567
- document.getElementById('checks').replaceChildren();
568
- };
569
-
570
- // ---------- Preloaded harnesses (≥ 9 including one invalid) ----------
571
- const harnessList = [
572
- { k: 0, title: 'θ = π (k=0) ⇒ pass' },
573
- { k: 1, title: 'θ = π + 2π (k=1) ⇒ pass' },
574
- { k: -1, title: 'θ = π − 2π (k=−1) ⇒ pass' },
575
- { k: 6, title: 'θ = π + 12π (k=6) ⇒ pass' },
576
- { k: 123, title: 'θ = π + 2π·123 ⇒ pass' },
577
- { k: 10 ** 6, title: 'θ = π + 2π·10^6 ⇒ pass (reduced)' },
578
- { k: 0, off: Math.PI / 2, title: 'Invalid (should fail): θ = π/2', negative: true },
579
- { k: 0, off: Math.PI / 3, title: 'Invalid (should fail): θ = π/3', negative: true },
580
- { k: 0, off: 355 / 113 - Math.PI, title: 'θ ≈ 355/113 (π approx) ⇒ nearly pass' },
581
- ];
582
-
583
- const harnessDiv = document.getElementById('harnesses');
584
-
585
- function makeHarnessCard(h) {
586
- const card = el('section', { class: 'card stack' });
587
- const head = el('div', { class: 'h-title' }, [
588
- el('div', {}, [el('strong', {}, [h.title])]),
589
- el('div', { class: 'small muted' }, ['Check (harness)']),
590
- ]);
591
- const kpis = el('div', { class: 'kpi' });
592
- const ans = el('div', { class: 'card' });
593
- ans.append(el('div', { class: 'k' }, ['Answer']), el('div', { class: 'v mono' }, ['—']));
594
- const thetaCard = el('div', { class: 'card' });
595
- thetaCard.append(el('div', { class: 'k' }, ['Angle θ']), el('div', { class: 'v mono' }, ['—']));
596
- const method = el('div', { class: 'card' });
597
- method.append(el('div', { class: 'k' }, ['Method']), el('div', { class: 'v mono' }, ['cos/sin + series']));
598
- kpis.append(ans, thetaCard, method);
599
-
600
- const reason = el('p', { class: 'muted small' }, [
601
- 'We check |e^{iθ}+1| ≤ ε with ε=1e−12, also confirm real/imag parts and series agreement.',
602
- ]);
603
- const checks = el('div', { class: 'list' });
604
- const run = el('button', { class: 'secondary' }, ['Run']);
605
-
606
- run.onclick = () => {
607
- const eps = 1e-12;
608
- const N = 40;
609
- const theta = h.off !== undefined ? h.off : Math.PI + TAU * h.k;
610
- const z = cis(theta);
611
- const sRe = cosSeries(theta, N),
612
- sIm = sinSeries(theta, N);
613
- const zSeries = { re: sRe, im: sIm };
614
- const ansZ = { re: z.re + 1, im: z.im };
615
- const ansSeriesZ = { re: zSeries.re + 1, im: zSeries.im };
616
-
617
- ans.querySelector('.v').textContent = `|e^{iθ}+1| ≈ ${abs(ansZ).toExponential(6)}`;
618
- thetaCard.querySelector('.v').textContent = `θ ≈ ${theta.toPrecision(8)}`;
619
-
620
- const list = [];
621
- const eq = abs(ansZ) <= eps;
622
- list.push(row(eq, 'Equality |e^{iθ}+1| ≤ ε', `|⋅| ≈ ${abs(ansZ).toExponential(6)} ≤ ${eps}`));
623
- const reOk = Math.abs(z.re + 1) <= eps;
624
- list.push(row(reOk, 'Real ≈ −1', `|Re+1| ≈ ${Math.abs(z.re + 1).toExponential(6)}`));
625
- const imOk = Math.abs(z.im) <= eps;
626
- list.push(row(imOk, 'Imag ≈ 0', `|Im| ≈ ${Math.abs(z.im).toExponential(6)}`));
627
- const seriesOk = abs(ansSeriesZ) <= Math.max(eps, 1e-15);
628
- list.push(row(seriesOk, `Series (N=${N})`, `|series+1| ≈ ${abs(ansSeriesZ).toExponential(6)}`));
629
- const squareOk = abs(add(mul(z, z), { re: -1, im: 0 })) <= eps * 10;
630
- list.push(
631
- row(
632
- squareOk,
633
- 'Square check',
634
- `|(e^{iθ})^2 − 1| ≈ ${abs(add(mul(z, z), { re: -1, im: 0 })).toExponential(6)}`,
635
- ),
636
- );
637
- const periodicOk = abs(add(cis(theta + TAU), { re: 1, im: 0 })) <= eps;
638
- list.push(row(periodicOk, 'Periodicity', `θ→θ+2π check`));
639
-
640
- checks.replaceChildren(...list);
641
- };
642
-
643
- if (h.negative) {
644
- const warn = el('div', { class: 'small muted' }, [
645
- 'This case is intentionally invalid and should report a failure.',
646
- ]);
647
- card.append(head, kpis, reason, warn, checks, run);
648
- } else {
649
- card.append(head, kpis, reason, checks, run);
650
- }
651
- return card;
652
- }
653
-
654
- harnessList.forEach((h) => harnessDiv.appendChild(makeHarnessCard(h)));
655
- document.getElementById('runAll').onclick = () => {
656
- [...harnessDiv.querySelectorAll('button.secondary')].forEach((b) => b.click());
657
- };
658
- document.getElementById('clearHarness').onclick = () => {
659
- harnessDiv.querySelectorAll('.list').forEach((div) => div.replaceChildren());
660
- harnessDiv.querySelectorAll('.v').forEach((div) => (div.textContent = '—'));
661
- };
662
-
663
- // auto-evaluate initial sample
664
- evaluate();
665
- </script>
666
- </body>
667
- </html>