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.
Files changed (51) hide show
  1. package/HANDBOOK.md +4 -0
  2. package/README.md +0 -1
  3. package/examples/ershov-mixed-computation.n3 +106 -0
  4. package/examples/output/ershov-mixed-computation.n3 +15 -0
  5. package/eyeling.js +510 -263
  6. package/lib/cli.js +22 -12
  7. package/lib/engine.js +488 -251
  8. package/package.json +2 -3
  9. package/arctifacts/README.md +0 -59
  10. package/arctifacts/ackermann.html +0 -678
  11. package/arctifacts/auroracare.html +0 -1297
  12. package/arctifacts/bike-trip.html +0 -752
  13. package/arctifacts/binomial-theorem.html +0 -631
  14. package/arctifacts/bmi.html +0 -511
  15. package/arctifacts/building-performance.html +0 -750
  16. package/arctifacts/clinical-care.html +0 -726
  17. package/arctifacts/collatz.html +0 -403
  18. package/arctifacts/complex.html +0 -321
  19. package/arctifacts/control-system.html +0 -482
  20. package/arctifacts/delfour.html +0 -849
  21. package/arctifacts/earthquake-epicenter.html +0 -982
  22. package/arctifacts/eco-route.html +0 -662
  23. package/arctifacts/euclid-infinitude.html +0 -564
  24. package/arctifacts/euler-identity.html +0 -667
  25. package/arctifacts/exoplanet-transit.html +0 -1000
  26. package/arctifacts/faltings-theorem.html +0 -1046
  27. package/arctifacts/fibonacci.html +0 -299
  28. package/arctifacts/fundamental-theorem-arithmetic.html +0 -398
  29. package/arctifacts/godel-numbering.html +0 -743
  30. package/arctifacts/gps-bike.html +0 -759
  31. package/arctifacts/gps-clinical-bench.html +0 -792
  32. package/arctifacts/graph-french.html +0 -449
  33. package/arctifacts/grass-molecular.html +0 -592
  34. package/arctifacts/group-theory.html +0 -740
  35. package/arctifacts/health-info.html +0 -833
  36. package/arctifacts/kaprekar-constant.html +0 -576
  37. package/arctifacts/lee.html +0 -805
  38. package/arctifacts/linked-lists.html +0 -502
  39. package/arctifacts/lldm.html +0 -612
  40. package/arctifacts/matrix-multiplication.html +0 -502
  41. package/arctifacts/matrix.html +0 -651
  42. package/arctifacts/newton-raphson.html +0 -944
  43. package/arctifacts/peano-factorial.html +0 -456
  44. package/arctifacts/pi.html +0 -363
  45. package/arctifacts/polynomial.html +0 -646
  46. package/arctifacts/prime.html +0 -366
  47. package/arctifacts/pythagorean-theorem.html +0 -468
  48. package/arctifacts/rest-path.html +0 -469
  49. package/arctifacts/roots-of-unity.html +0 -363
  50. package/arctifacts/turing.html +0 -409
  51. package/arctifacts/wind-turbines.html +0 -726
@@ -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>Roots of Unity</title>
7
- <style>
8
- :root {
9
- --bg: #f6f8fb;
10
- --ink: #0f172a;
11
- --sub: #334155;
12
- --line: #d5dbe7;
13
- --circle: #eaf3ff;
14
- --edge: #4f79c8;
15
- --pt: #0ea5e9;
16
- --axis: #94a3b8;
17
- --ok: #059669;
18
- --bad: #dc2626;
19
- }
20
- html,
21
- body {
22
- margin: 0;
23
- background: var(--bg);
24
- color: var(--ink);
25
- font-family:
26
- system-ui,
27
- Segoe UI,
28
- Roboto,
29
- Helvetica,
30
- Arial,
31
- sans-serif;
32
- }
33
- header {
34
- padding: 18px 20px;
35
- border-bottom: 1px solid var(--line);
36
- }
37
- h1 {
38
- margin: 0 0 6px;
39
- font-size: 22px;
40
- }
41
- h2 {
42
- margin: 18px 0 10px;
43
- font-size: 17px;
44
- }
45
- p,
46
- li,
47
- small {
48
- line-height: 1.45;
49
- }
50
- main {
51
- display: block;
52
- padding: 18px 20px 40px;
53
- }
54
- .card {
55
- background: #fff;
56
- border: 1px solid var(--line);
57
- border-radius: 12px;
58
- box-shadow: 0 1px 0 rgba(15, 23, 42, 0.04);
59
- margin: 0 0 18px;
60
- }
61
- .card header {
62
- padding: 12px 14px;
63
- border-bottom: 1px solid var(--line);
64
- border-radius: 12px 12px 0 0;
65
- }
66
- .card section {
67
- padding: 14px;
68
- }
69
- .muted {
70
- color: var(--sub);
71
- }
72
- .mono {
73
- font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
74
- }
75
- .ok {
76
- color: var(--ok);
77
- }
78
- .bad {
79
- color: var(--bad);
80
- }
81
- svg {
82
- max-width: 50%;
83
- height: auto;
84
- display: block;
85
- margin: 0 auto;
86
- shape-rendering: geometricPrecision;
87
- }
88
- </style>
89
- </head>
90
- <body>
91
- <header>
92
- <h1>Roots of Unity</h1>
93
- </header>
94
-
95
- <main>
96
- <!-- WHAT THIS IS -->
97
- <article class="card">
98
- <header><h2>What this is?</h2></header>
99
- <section>
100
- <p>
101
- An Argand diagram of the <em>n</em>-th roots of unity: points <em>z<sub>k</sub></em> = cos(2πk/n) + i
102
- sin(2πk/n) for k = 0,…,n−1. They lie on the unit circle, equally spaced, forming a regular <em>n</em>-gon.
103
- Multiplying by a unit complex number rotates; raising to the <em>n</em>-th power maps all points to 1.
104
- </p>
105
- </section>
106
- </article>
107
-
108
- <!-- ANSWER -->
109
- <article class="card">
110
- <header><h2>Answer — drawing</h2></header>
111
- <section>
112
- <svg id="fig" viewBox="0 0 240 240" aria-label="n-th roots of unity on the unit circle">
113
- <g id="grid"></g>
114
- <g id="axes"></g>
115
- <g id="poly"></g>
116
- <g id="points"></g>
117
- </svg>
118
- </section>
119
- </article>
120
-
121
- <!-- REASON -->
122
- <article class="card">
123
- <header><h2>Reason</h2></header>
124
- <section>
125
- <ol>
126
- <li>
127
- Solutions of z<sup>n</sup> = 1 are z<sub>k</sub> = cos(2πk/n) + i sin(2πk/n), k = 0,…,n−1 (De Moivre).
128
- </li>
129
- <li>All have |z<sub>k</sub>| = 1, arguments 2πk/n, hence equal spacing by 2π/n and a regular polygon.</li>
130
- <li>
131
- Sum of all roots is 0 and product is (−1)<sup>n−1</sup>. The polygon (circumradius 1) has area A = (n/2) ·
132
- sin(2π/n).
133
- </li>
134
- </ol>
135
- </section>
136
- </article>
137
-
138
- <!-- CHECK -->
139
- <article class="card">
140
- <header><h2>Check</h2></header>
141
- <section>
142
- <ul id="checks" class="mono"></ul>
143
- <div id="numbers" class="mono" style="margin-top: 8px; white-space: pre-wrap"></div>
144
- <small class="muted"
145
- >We verify z<sup>n</sup>=1, unit modulus, equal angle steps, sum/product identities, chord length
146
- 2·sin(π/n), area formula, and DFT sums Σ z<sub>k</sub><sup>m</sup> = 0 for 1 ≤ m ≤ n−1.</small
147
- >
148
- </section>
149
- </article>
150
- </main>
151
-
152
- <script>
153
- (function () {
154
- const checks = document.getElementById('checks');
155
- const numbers = document.getElementById('numbers');
156
- const ok = (t) => `<li><span class="ok">OK</span> — ${t}</li>`;
157
- const bad = (t) => `<li><span class="bad">FAIL</span> — ${t}</li>`;
158
-
159
- // ===== Parameters =====
160
- const n = 12; // number of roots (change if you like)
161
- const cx = 120,
162
- cy = 120,
163
- R = 100; // SVG center and radius (pixels)
164
- const tol = 1e-10;
165
-
166
- // ===== Build roots on the unit circle (math coords) =====
167
- const roots = [];
168
- for (let k = 0; k < n; k++) {
169
- const theta = (2 * Math.PI * k) / n;
170
- roots.push({ re: Math.cos(theta), im: Math.sin(theta), theta });
171
- }
172
-
173
- // ===== Drawing helpers (map unit circle -> SVG) =====
174
- const X = (x) => cx + R * x;
175
- const Y = (y) => cy - R * y; // flip y for SVG
176
-
177
- const gGrid = document.getElementById('grid');
178
- const gAxes = document.getElementById('axes');
179
- const gPoly = document.getElementById('poly');
180
- const gPts = document.getElementById('points');
181
-
182
- // background ring and frame ticks
183
- const ring = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
184
- ring.setAttribute('cx', cx);
185
- ring.setAttribute('cy', cy);
186
- ring.setAttribute('r', R);
187
- ring.setAttribute('fill', 'var(--circle)');
188
- ring.setAttribute('stroke', '#c7d2e5');
189
- ring.setAttribute('stroke-width', '1.2');
190
- gGrid.appendChild(ring);
191
-
192
- // axes
193
- const axH = document.createElementNS('http://www.w3.org/2000/svg', 'line');
194
- axH.setAttribute('x1', X(-1.1));
195
- axH.setAttribute('y1', Y(0));
196
- axH.setAttribute('x2', X(1.1));
197
- axH.setAttribute('y2', Y(0));
198
- axH.setAttribute('stroke', 'var(--axis)');
199
- axH.setAttribute('stroke-width', '1.2');
200
- gAxes.appendChild(axH);
201
-
202
- const axV = document.createElementNS('http://www.w3.org/2000/svg', 'line');
203
- axV.setAttribute('x1', X(0));
204
- axV.setAttribute('y1', Y(-1.1));
205
- axV.setAttribute('x2', X(0));
206
- axV.setAttribute('y2', Y(1.1));
207
- axV.setAttribute('stroke', 'var(--axis)');
208
- axV.setAttribute('stroke-width', '1.2');
209
- gAxes.appendChild(axV);
210
-
211
- // polygon through the roots (in order)
212
- const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
213
- let d = `M ${X(roots[0].re)} ${Y(roots[0].im)}`;
214
- for (let k = 1; k < n; k++) d += ` L ${X(roots[k].re)} ${Y(roots[k].im)}`;
215
- d += ' Z';
216
- path.setAttribute('d', d);
217
- path.setAttribute('fill', 'none');
218
- path.setAttribute('stroke', 'var(--edge)');
219
- path.setAttribute('stroke-width', '1.8');
220
- gPoly.appendChild(path);
221
-
222
- // points
223
- roots.forEach((z, k) => {
224
- const c = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
225
- c.setAttribute('cx', X(z.re));
226
- c.setAttribute('cy', Y(z.im));
227
- c.setAttribute('r', 2.4);
228
- c.setAttribute('fill', 'white');
229
- c.setAttribute('stroke', 'var(--pt)');
230
- c.setAttribute('stroke-width', '1.4');
231
- gPts.appendChild(c);
232
- });
233
-
234
- // ===== Checks =====
235
- // 1) z^n = 1 and |z| = 1
236
- let powOK = true,
237
- modOK = true;
238
- roots.forEach((z) => {
239
- const r = Math.hypot(z.re, z.im);
240
- if (Math.abs(r - 1) > 1e-12) modOK = false;
241
- // z^n using angle
242
- const zn = { re: Math.cos(n * Math.atan2(z.im, z.re)), im: Math.sin(n * Math.atan2(z.im, z.re)) };
243
- if (Math.hypot(zn.re - 1, zn.im - 0) > 1e-9) powOK = false;
244
- });
245
- checks.insertAdjacentHTML(
246
- 'beforeend',
247
- modOK ? ok('Every root has unit modulus |z| = 1') : bad('Some root |z| ≠ 1'),
248
- );
249
- checks.insertAdjacentHTML(
250
- 'beforeend',
251
- powOK ? ok('Every root satisfies z^n = 1') : bad('Some root does not satisfy z^n = 1'),
252
- );
253
-
254
- // 2) Equal angle steps 2π/n
255
- const ang = roots.map((z) => Math.atan2(z.im, z.re)).sort((a, b) => a - b);
256
- // unwrap continuity
257
- for (let i = 1; i < ang.length; i++) if (ang[i] - ang[i - 1] < -Math.PI) ang[i] += 2 * Math.PI;
258
- const step = (2 * Math.PI) / n;
259
- let spacingOK = true,
260
- maxDev = 0;
261
- for (let i = 0; i < n; i++) {
262
- const a0 = ang[i],
263
- a1 = ang[(i + 1) % n] + (i + 1 === n ? 2 * Math.PI : 0);
264
- const dev = Math.abs(a1 - a0 - step);
265
- if (dev > maxDev) maxDev = dev;
266
- if (dev > 1e-10) spacingOK = false;
267
- }
268
- checks.insertAdjacentHTML(
269
- 'beforeend',
270
- spacingOK
271
- ? ok('Equal angular spacing Δθ = 2π/n')
272
- : bad(`Unequal spacing (max deviation ${maxDev.toExponential(2)})`),
273
- );
274
-
275
- // 3) Sum of roots = 0
276
- const sum = roots.reduce((a, z) => ({ re: a.re + z.re, im: a.im + z.im }), { re: 0, im: 0 });
277
- const sumOK = Math.hypot(sum.re, sum.im) < 1e-9;
278
- checks.insertAdjacentHTML(
279
- 'beforeend',
280
- sumOK
281
- ? ok('Sum of all roots equals 0')
282
- : bad(`Sum of roots not 0: |Σ| = ${Math.hypot(sum.re, sum.im).toExponential(2)}`),
283
- );
284
-
285
- // 4) Product of roots = (−1)^(n−1)
286
- const prodArg = roots.reduce((a, z) => a + Math.atan2(z.im, z.re), 0); // magnitude is 1^n=1
287
- // wrap to nearest of {0, π} mod 2π
288
- let prodSign = Math.cos(prodArg) >= 0 ? 1 : -1;
289
- const expectedSign = (n - 1) % 2 === 0 ? 1 : -1;
290
- const prodOK = prodSign === expectedSign;
291
- checks.insertAdjacentHTML(
292
- 'beforeend',
293
- prodOK ? ok('Product of roots equals (−1)^(n−1)') : bad('Product check failed'),
294
- );
295
-
296
- // 5) Chord length between consecutive roots = 2 sin(π/n)
297
- const chord = 2 * Math.sin(Math.PI / n);
298
- let chordOK = true,
299
- chordMaxDev = 0;
300
- for (let k = 0; k < n; k++) {
301
- const a = roots[k],
302
- b = roots[(k + 1) % n];
303
- const d = Math.hypot(a.re - b.re, a.im - b.im);
304
- const dev = Math.abs(d - chord);
305
- if (dev > chordMaxDev) chordMaxDev = dev;
306
- if (dev > 1e-10) chordOK = false;
307
- }
308
- checks.insertAdjacentHTML(
309
- 'beforeend',
310
- chordOK
311
- ? ok('Consecutive chord length is 2·sin(π/n)')
312
- : bad(`Chord length mismatch (max deviation ${chordMaxDev.toExponential(2)})`),
313
- );
314
-
315
- // 6) Polygon area equals (n/2)·sin(2π/n)
316
- function polyArea(pts) {
317
- let s = 0;
318
- for (let i = 0; i < pts.length; i++) {
319
- const j = (i + 1) % pts.length;
320
- s += pts[i].re * pts[j].im - pts[j].re * pts[i].im;
321
- }
322
- return Math.abs(s) / 2;
323
- }
324
- const A = polyArea(roots);
325
- const Aexp = 0.5 * n * Math.sin((2 * Math.PI) / n);
326
- const areaOK = Math.abs(A - Aexp) < 1e-10;
327
- checks.insertAdjacentHTML(
328
- 'beforeend',
329
- areaOK
330
- ? ok('Polygon area matches A = (n/2)·sin(2π/n)')
331
- : bad(`Area mismatch: got ${A.toFixed(12)}, expected ${Aexp.toFixed(12)}`),
332
- );
333
-
334
- // 7) DFT property: for 1 ≤ m ≤ n−1, Σ z_k^m = 0
335
- let dftOK = true;
336
- let firstBad = null;
337
- for (let m = 1; m < n; m++) {
338
- let acc = { re: 0, im: 0 };
339
- for (const z of roots) {
340
- const t = m * Math.atan2(z.im, z.re);
341
- acc.re += Math.cos(t);
342
- acc.im += Math.sin(t);
343
- }
344
- if (Math.hypot(acc.re, acc.im) > 1e-9) {
345
- dftOK = false;
346
- firstBad = m;
347
- break;
348
- }
349
- }
350
- checks.insertAdjacentHTML(
351
- 'beforeend',
352
- dftOK ? ok('DFT sums vanish: Σ z_k^m = 0 for 1 ≤ m ≤ n−1') : bad(`DFT sum failed for m = ${firstBad}`),
353
- );
354
-
355
- numbers.textContent = `n = ${n}
356
- Equal angle step = 2π/n = ${((2 * Math.PI) / n).toFixed(6)} rad
357
- Chord length = ${chord.toFixed(6)}
358
- Area (computed) = ${A.toFixed(12)}
359
- Area (expected) = ${Aexp.toFixed(12)}`;
360
- })();
361
- </script>
362
- </body>
363
- </html>