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/matrix.html
DELETED
|
@@ -1,651 +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>Matrix basics</title>
|
|
7
|
-
<style>
|
|
8
|
-
:root {
|
|
9
|
-
--bg: #ffffff;
|
|
10
|
-
--ink: #111827;
|
|
11
|
-
--muted: #6b7280;
|
|
12
|
-
--panel: #f8fafc;
|
|
13
|
-
--border: #e5e7eb;
|
|
14
|
-
--accent: #0ea5e9;
|
|
15
|
-
--good: #16a34a;
|
|
16
|
-
--amber: #f59e0b;
|
|
17
|
-
--blue: #3b82f6;
|
|
18
|
-
--mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace;
|
|
19
|
-
--ui:
|
|
20
|
-
system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', 'Apple Color Emoji',
|
|
21
|
-
'Segoe UI Emoji';
|
|
22
|
-
}
|
|
23
|
-
body {
|
|
24
|
-
margin: 0;
|
|
25
|
-
background: var(--bg);
|
|
26
|
-
color: var(--ink);
|
|
27
|
-
font: 15px/1.6 var(--ui);
|
|
28
|
-
}
|
|
29
|
-
.wrap {
|
|
30
|
-
max-width: 980px;
|
|
31
|
-
margin: 36px auto;
|
|
32
|
-
padding: 0 16px;
|
|
33
|
-
}
|
|
34
|
-
header {
|
|
35
|
-
display: flex;
|
|
36
|
-
align-items: center;
|
|
37
|
-
justify-content: space-between;
|
|
38
|
-
margin-bottom: 16px;
|
|
39
|
-
}
|
|
40
|
-
h1 {
|
|
41
|
-
font-size: 22px;
|
|
42
|
-
margin: 0;
|
|
43
|
-
letter-spacing: 0.2px;
|
|
44
|
-
}
|
|
45
|
-
.pill {
|
|
46
|
-
display: inline-flex;
|
|
47
|
-
align-items: center;
|
|
48
|
-
gap: 8px;
|
|
49
|
-
padding: 6px 10px;
|
|
50
|
-
border: 1px solid var(--border);
|
|
51
|
-
border-radius: 999px;
|
|
52
|
-
color: var(--muted);
|
|
53
|
-
background: #fff;
|
|
54
|
-
}
|
|
55
|
-
.row {
|
|
56
|
-
display: flex;
|
|
57
|
-
flex-direction: column;
|
|
58
|
-
gap: 16px;
|
|
59
|
-
}
|
|
60
|
-
.card {
|
|
61
|
-
background: var(--panel);
|
|
62
|
-
border: 1px solid var(--border);
|
|
63
|
-
border-radius: 14px;
|
|
64
|
-
overflow: hidden;
|
|
65
|
-
}
|
|
66
|
-
.head {
|
|
67
|
-
display: flex;
|
|
68
|
-
align-items: center;
|
|
69
|
-
justify-content: space-between;
|
|
70
|
-
padding: 10px 12px;
|
|
71
|
-
border-bottom: 1px solid var(--border);
|
|
72
|
-
}
|
|
73
|
-
.head h2 {
|
|
74
|
-
font-size: 13px;
|
|
75
|
-
text-transform: uppercase;
|
|
76
|
-
letter-spacing: 0.08em;
|
|
77
|
-
color: var(--muted);
|
|
78
|
-
margin: 0;
|
|
79
|
-
}
|
|
80
|
-
.body {
|
|
81
|
-
padding: 12px;
|
|
82
|
-
}
|
|
83
|
-
pre {
|
|
84
|
-
white-space: pre-wrap;
|
|
85
|
-
background: #fff;
|
|
86
|
-
border: 1px solid var(--border);
|
|
87
|
-
border-radius: 10px;
|
|
88
|
-
padding: 12px;
|
|
89
|
-
overflow: auto;
|
|
90
|
-
font-family: var(--mono);
|
|
91
|
-
font-size: 13.25px;
|
|
92
|
-
}
|
|
93
|
-
code {
|
|
94
|
-
background: #fff;
|
|
95
|
-
border: 1px solid var(--border);
|
|
96
|
-
border-radius: 6px;
|
|
97
|
-
padding: 0 6px;
|
|
98
|
-
}
|
|
99
|
-
.arc-grid {
|
|
100
|
-
display: flex;
|
|
101
|
-
flex-direction: column;
|
|
102
|
-
gap: 12px;
|
|
103
|
-
}
|
|
104
|
-
.arc-card {
|
|
105
|
-
background: #fff;
|
|
106
|
-
border: 1px solid var(--border);
|
|
107
|
-
border-radius: 14px;
|
|
108
|
-
overflow: hidden;
|
|
109
|
-
}
|
|
110
|
-
.arc-card .ac-head {
|
|
111
|
-
display: flex;
|
|
112
|
-
align-items: center;
|
|
113
|
-
gap: 8px;
|
|
114
|
-
padding: 10px 12px;
|
|
115
|
-
border-bottom: 1px solid var(--border);
|
|
116
|
-
font-size: 12px;
|
|
117
|
-
letter-spacing: 0.08em;
|
|
118
|
-
text-transform: uppercase;
|
|
119
|
-
color: var(--muted);
|
|
120
|
-
}
|
|
121
|
-
.arc-card .ac-body {
|
|
122
|
-
padding: 12px;
|
|
123
|
-
}
|
|
124
|
-
.arc-card.answer {
|
|
125
|
-
border-left: 4px solid var(--good);
|
|
126
|
-
}
|
|
127
|
-
.arc-card.reason {
|
|
128
|
-
border-left: 4px solid var(--blue);
|
|
129
|
-
}
|
|
130
|
-
.arc-card.check {
|
|
131
|
-
border-left: 4px solid var(--amber);
|
|
132
|
-
}
|
|
133
|
-
.btn {
|
|
134
|
-
all: unset;
|
|
135
|
-
background: #fff;
|
|
136
|
-
border: 1px solid var(--border);
|
|
137
|
-
padding: 8px 12px;
|
|
138
|
-
border-radius: 10px;
|
|
139
|
-
cursor: pointer;
|
|
140
|
-
}
|
|
141
|
-
.btn:hover {
|
|
142
|
-
border-color: #cbd5e1;
|
|
143
|
-
}
|
|
144
|
-
</style>
|
|
145
|
-
</head>
|
|
146
|
-
<body>
|
|
147
|
-
<div class="wrap">
|
|
148
|
-
<header>
|
|
149
|
-
<h1>Matrix basics</h1>
|
|
150
|
-
<div class="pill" id="status">Ready</div>
|
|
151
|
-
</header>
|
|
152
|
-
|
|
153
|
-
<div class="card" style="margin-bottom: 16px">
|
|
154
|
-
<div class="body">
|
|
155
|
-
<p><strong>What this is?</strong> A self‑contained, browser‑only reproduction of five matrix calls:</p>
|
|
156
|
-
<ul>
|
|
157
|
-
<li><code>Matrix([[1, 3], [-2, 3]]) * Matrix([[0, 3], [0, 7]])</code></li>
|
|
158
|
-
<li><code>Matrix([[1, 3], [-2, 3]]) ** 2</code></li>
|
|
159
|
-
<li><code>Matrix([[1, 3], [-2, 3]]) ** -1</code> (2×2 inverse via adjugate/determinant)</li>
|
|
160
|
-
<li><code>Matrix([[1, 0, 1], [2, -1, 3], [4, 3, 2]]).det()</code> (Sarrus/Laplace)</li>
|
|
161
|
-
<li>
|
|
162
|
-
<code>Matrix([[3, -2, 4, -2], [5, 3, -3, -2], [5, -2, 2, -2], [5, -2, -3, 3]]).eigenvals()</code>
|
|
163
|
-
(Faddeev–LeVerrier → characteristic polynomial → integer roots)
|
|
164
|
-
</li>
|
|
165
|
-
</ul>
|
|
166
|
-
<p>
|
|
167
|
-
The harness then checks the answers with algebraic identities (e.g., Cayley–Hamilton, inverse correctness).
|
|
168
|
-
</p>
|
|
169
|
-
</div>
|
|
170
|
-
</div>
|
|
171
|
-
|
|
172
|
-
<div class="row">
|
|
173
|
-
<div class="card">
|
|
174
|
-
<div class="head">
|
|
175
|
-
<h2>Controls</h2>
|
|
176
|
-
<div style="display: flex; gap: 8px; align-items: center">
|
|
177
|
-
<button class="btn" onclick="run()">▶ Run</button>
|
|
178
|
-
<button class="btn" onclick="downloadARC()">⬇ Export .txt</button>
|
|
179
|
-
</div>
|
|
180
|
-
</div>
|
|
181
|
-
<div class="body">Deterministic run (no inputs). Auto‑runs on load.</div>
|
|
182
|
-
</div>
|
|
183
|
-
|
|
184
|
-
<div class="card">
|
|
185
|
-
<div class="head"><h2>ARC Output</h2></div>
|
|
186
|
-
<div class="body">
|
|
187
|
-
<div class="arc-grid">
|
|
188
|
-
<div class="arc-card answer">
|
|
189
|
-
<div class="ac-head">Answer</div>
|
|
190
|
-
<div class="ac-body"><pre id="ans">(no run yet)</pre></div>
|
|
191
|
-
</div>
|
|
192
|
-
<div class="arc-card reason">
|
|
193
|
-
<div class="ac-head">Reason why</div>
|
|
194
|
-
<div class="ac-body"><pre id="why">(no run yet)</pre></div>
|
|
195
|
-
</div>
|
|
196
|
-
<div class="arc-card check">
|
|
197
|
-
<div class="ac-head">Check (harness)</div>
|
|
198
|
-
<div class="ac-body"><pre id="chk">(no run yet)</pre></div>
|
|
199
|
-
</div>
|
|
200
|
-
</div>
|
|
201
|
-
</div>
|
|
202
|
-
</div>
|
|
203
|
-
</div>
|
|
204
|
-
</div>
|
|
205
|
-
|
|
206
|
-
<script>
|
|
207
|
-
// -------- Fractions (exact) --------
|
|
208
|
-
function gcd(a, b) {
|
|
209
|
-
a = Math.abs(a);
|
|
210
|
-
b = Math.abs(b);
|
|
211
|
-
while (b) {
|
|
212
|
-
const t = b;
|
|
213
|
-
b = a % b;
|
|
214
|
-
a = t;
|
|
215
|
-
}
|
|
216
|
-
return a || 1;
|
|
217
|
-
}
|
|
218
|
-
function makeF(n, d) {
|
|
219
|
-
if (d === 0) throw new Error('den 0');
|
|
220
|
-
if (d < 0) {
|
|
221
|
-
n = -n;
|
|
222
|
-
d = -d;
|
|
223
|
-
}
|
|
224
|
-
const g = gcd(n, d);
|
|
225
|
-
return { n: Math.trunc(n / g), d: Math.trunc(d / g) };
|
|
226
|
-
}
|
|
227
|
-
function toF(x) {
|
|
228
|
-
return x && typeof x === 'object' && 'n' in x && 'd' in x ? x : { n: Math.trunc(x), d: 1 };
|
|
229
|
-
}
|
|
230
|
-
function addF(a, b) {
|
|
231
|
-
a = toF(a);
|
|
232
|
-
b = toF(b);
|
|
233
|
-
return makeF(a.n * b.d + b.n * a.d, a.d * b.d);
|
|
234
|
-
}
|
|
235
|
-
function subF(a, b) {
|
|
236
|
-
a = toF(a);
|
|
237
|
-
b = toF(b);
|
|
238
|
-
return makeF(a.n * b.d - b.n * a.d, a.d * b.d);
|
|
239
|
-
}
|
|
240
|
-
function mulF(a, b) {
|
|
241
|
-
a = toF(a);
|
|
242
|
-
b = toF(b);
|
|
243
|
-
return makeF(a.n * b.n, a.d * b.d);
|
|
244
|
-
}
|
|
245
|
-
function divF(a, b) {
|
|
246
|
-
a = toF(a);
|
|
247
|
-
b = toF(b);
|
|
248
|
-
return makeF(a.n * b.d, a.d * b.n);
|
|
249
|
-
}
|
|
250
|
-
function eqF(a, b) {
|
|
251
|
-
a = toF(a);
|
|
252
|
-
b = toF(b);
|
|
253
|
-
return a.n === b.n && a.d === b.d;
|
|
254
|
-
}
|
|
255
|
-
function f2s(a) {
|
|
256
|
-
a = toF(a);
|
|
257
|
-
return a.d === 1 ? String(a.n) : a.n + '/' + a.d;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// -------- Matrix ops (fractions) --------
|
|
261
|
-
function matStr(M) {
|
|
262
|
-
return 'Matrix([' + M.map((r) => '[' + r.map(f2s).join(', ') + ']').join(', ') + '])';
|
|
263
|
-
}
|
|
264
|
-
function shape(A) {
|
|
265
|
-
return [A.length, A[0].length];
|
|
266
|
-
}
|
|
267
|
-
function identityFrac(n) {
|
|
268
|
-
return Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => makeF(i === j ? 1 : 0, 1)));
|
|
269
|
-
}
|
|
270
|
-
function zeros(n, m) {
|
|
271
|
-
return Array.from({ length: n }, () => Array.from({ length: m }, () => makeF(0, 1)));
|
|
272
|
-
}
|
|
273
|
-
function matMul(A, B) {
|
|
274
|
-
const n = A.length,
|
|
275
|
-
m = A[0].length,
|
|
276
|
-
m2 = B.length,
|
|
277
|
-
p = B[0].length;
|
|
278
|
-
if (m !== m2) throw new Error('shape mismatch');
|
|
279
|
-
const C = zeros(n, p);
|
|
280
|
-
for (let i = 0; i < n; i++)
|
|
281
|
-
for (let j = 0; j < p; j++) {
|
|
282
|
-
let s = makeF(0, 1);
|
|
283
|
-
for (let k = 0; k < m; k++) s = addF(s, mulF(A[i][k], B[k][j]));
|
|
284
|
-
C[i][j] = s;
|
|
285
|
-
}
|
|
286
|
-
return C;
|
|
287
|
-
}
|
|
288
|
-
function matAdd(A, B) {
|
|
289
|
-
const n = A.length,
|
|
290
|
-
m = A[0].length;
|
|
291
|
-
const C = zeros(n, m);
|
|
292
|
-
for (let i = 0; i < n; i++) for (let j = 0; j < m; j++) C[i][j] = addF(A[i][j], B[i][j]);
|
|
293
|
-
return C;
|
|
294
|
-
}
|
|
295
|
-
function matScalar(A, s) {
|
|
296
|
-
s = toF(s);
|
|
297
|
-
const n = A.length,
|
|
298
|
-
m = A[0].length;
|
|
299
|
-
const C = zeros(n, m);
|
|
300
|
-
for (let i = 0; i < n; i++) for (let j = 0; j < m; j++) C[i][j] = mulF(A[i][j], s);
|
|
301
|
-
return C;
|
|
302
|
-
}
|
|
303
|
-
function matEq(A, B) {
|
|
304
|
-
const n = A.length,
|
|
305
|
-
m = A[0].length;
|
|
306
|
-
for (let i = 0; i < n; i++) for (let j = 0; j < m; j++) if (!eqF(A[i][j], B[i][j])) return false;
|
|
307
|
-
return true;
|
|
308
|
-
}
|
|
309
|
-
function det2(A) {
|
|
310
|
-
return subF(mulF(A[0][0], A[1][1]), mulF(A[0][1], A[1][0]));
|
|
311
|
-
}
|
|
312
|
-
function inv2(A) {
|
|
313
|
-
const a = A[0][0],
|
|
314
|
-
b = A[0][1],
|
|
315
|
-
c = A[1][0],
|
|
316
|
-
d = A[1][1];
|
|
317
|
-
const det = det2(A);
|
|
318
|
-
if (eqF(det, makeF(0, 1))) throw new Error('singular');
|
|
319
|
-
const adj = [
|
|
320
|
-
[d, makeF(-toF(b).n, 1)],
|
|
321
|
-
[makeF(-toF(c).n, 1), a],
|
|
322
|
-
];
|
|
323
|
-
return { inv: matScalar(adj, divF(makeF(1, 1), det)), det, adj };
|
|
324
|
-
}
|
|
325
|
-
function det3(M) {
|
|
326
|
-
const [a, b, c] = M[0],
|
|
327
|
-
[d, e, f] = M[1],
|
|
328
|
-
[g, h, i] = M[2];
|
|
329
|
-
const term1 = mulF(a, subF(mulF(e, i), mulF(f, h)));
|
|
330
|
-
const term2 = mulF(b, subF(mulF(d, i), mulF(f, g)));
|
|
331
|
-
const term3 = mulF(c, subF(mulF(d, h), mulF(e, g)));
|
|
332
|
-
return addF(subF(term1, term2), term3);
|
|
333
|
-
}
|
|
334
|
-
function det3SarrusTerms(M) {
|
|
335
|
-
const [a, b, c] = M[0],
|
|
336
|
-
[d, e, f] = M[1],
|
|
337
|
-
[g, h, i] = M[2];
|
|
338
|
-
const pos = [mulF(a, mulF(e, i)), mulF(b, mulF(f, g)), mulF(c, mulF(d, h))];
|
|
339
|
-
const neg = [mulF(c, mulF(e, g)), mulF(a, mulF(f, h)), mulF(b, mulF(d, i))];
|
|
340
|
-
return { pos, neg };
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
// -------- Integer-matrix helpers for eigenvals --------
|
|
344
|
-
function toIntMat(A) {
|
|
345
|
-
const n = A.length,
|
|
346
|
-
m = A[0].length,
|
|
347
|
-
B = Array.from({ length: n }, () => Array(m).fill(0));
|
|
348
|
-
for (let i = 0; i < n; i++)
|
|
349
|
-
for (let j = 0; j < m; j++) {
|
|
350
|
-
const x = toF(A[i][j]);
|
|
351
|
-
if (x.d !== 1) throw new Error('need int matrix');
|
|
352
|
-
B[i][j] = x.n;
|
|
353
|
-
}
|
|
354
|
-
return B;
|
|
355
|
-
}
|
|
356
|
-
function identityInt(n) {
|
|
357
|
-
return Array.from({ length: n }, (_, i) => Array.from({ length: n }, (_, j) => (i === j ? 1 : 0)));
|
|
358
|
-
}
|
|
359
|
-
function addI(A, B) {
|
|
360
|
-
const n = A.length,
|
|
361
|
-
m = A[0].length,
|
|
362
|
-
C = Array.from({ length: n }, () => Array(m).fill(0));
|
|
363
|
-
for (let i = 0; i < n; i++) for (let j = 0; j < m; j++) C[i][j] = A[i][j] + B[i][j];
|
|
364
|
-
return C;
|
|
365
|
-
}
|
|
366
|
-
function scalI(A, s) {
|
|
367
|
-
const n = A.length,
|
|
368
|
-
m = A[0].length,
|
|
369
|
-
C = Array.from({ length: n }, () => Array(m).fill(0));
|
|
370
|
-
for (let i = 0; i < n; i++) for (let j = 0; j < m; j++) C[i][j] = A[i][j] * s;
|
|
371
|
-
return C;
|
|
372
|
-
}
|
|
373
|
-
function mulI(A, B) {
|
|
374
|
-
const n = A.length,
|
|
375
|
-
m = A[0].length,
|
|
376
|
-
p = B[0].length,
|
|
377
|
-
C = Array.from({ length: n }, () => Array(p).fill(0));
|
|
378
|
-
for (let i = 0; i < n; i++)
|
|
379
|
-
for (let j = 0; j < p; j++) {
|
|
380
|
-
let s = 0;
|
|
381
|
-
for (let k = 0; k < m; k++) s += A[i][k] * B[k][j];
|
|
382
|
-
C[i][j] = s;
|
|
383
|
-
}
|
|
384
|
-
return C;
|
|
385
|
-
}
|
|
386
|
-
function traceI(A) {
|
|
387
|
-
let t = 0;
|
|
388
|
-
for (let i = 0; i < A.length; i++) t += A[i][i];
|
|
389
|
-
return t;
|
|
390
|
-
}
|
|
391
|
-
function leverrier(A) {
|
|
392
|
-
const n = A.length;
|
|
393
|
-
let B = A.map((r) => r.slice());
|
|
394
|
-
const I = identityInt(n);
|
|
395
|
-
const coeff = new Array(n + 1).fill(0);
|
|
396
|
-
coeff[0] = 1;
|
|
397
|
-
for (let k = 1; k <= n; k++) {
|
|
398
|
-
const tr = traceI(B);
|
|
399
|
-
if (tr % k !== 0) throw new Error('non-integer step');
|
|
400
|
-
const ck = -Math.trunc(tr / k);
|
|
401
|
-
coeff[k] = ck;
|
|
402
|
-
B = mulI(A, addI(B, scalI(I, ck)));
|
|
403
|
-
}
|
|
404
|
-
return coeff; // descending: [1, c1, ..., cn]
|
|
405
|
-
}
|
|
406
|
-
function evalPolyDesc(coeff, x) {
|
|
407
|
-
let v = 0;
|
|
408
|
-
for (const c of coeff) {
|
|
409
|
-
v = v * x + c;
|
|
410
|
-
}
|
|
411
|
-
return v;
|
|
412
|
-
}
|
|
413
|
-
function divisors(n) {
|
|
414
|
-
n = Math.abs(n);
|
|
415
|
-
const ds = [];
|
|
416
|
-
for (let d = 1; d <= n; d++) if (n % d === 0) ds.push(d);
|
|
417
|
-
return ds.concat(ds.map((d) => -d));
|
|
418
|
-
}
|
|
419
|
-
function syntheticDivDesc(coeff, r) {
|
|
420
|
-
const out = [coeff[0]];
|
|
421
|
-
let carry = coeff[0];
|
|
422
|
-
for (let i = 1; i < coeff.length; i++) {
|
|
423
|
-
carry = coeff[i] + carry * r;
|
|
424
|
-
out.push(carry);
|
|
425
|
-
}
|
|
426
|
-
const rem = out.pop();
|
|
427
|
-
if (rem !== 0) throw new Error('not a root');
|
|
428
|
-
return out;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
// -------- ARC generators --------
|
|
432
|
-
function runAll() {
|
|
433
|
-
// Matrices from the cases
|
|
434
|
-
const A = [
|
|
435
|
-
[makeF(1, 1), makeF(3, 1)],
|
|
436
|
-
[makeF(-2, 1), makeF(3, 1)],
|
|
437
|
-
];
|
|
438
|
-
const B = [
|
|
439
|
-
[makeF(0, 1), makeF(3, 1)],
|
|
440
|
-
[makeF(0, 1), makeF(7, 1)],
|
|
441
|
-
];
|
|
442
|
-
const M3 = [
|
|
443
|
-
[makeF(1, 1), makeF(0, 1), makeF(1, 1)],
|
|
444
|
-
[makeF(2, 1), makeF(-1, 1), makeF(3, 1)],
|
|
445
|
-
[makeF(4, 1), makeF(3, 1), makeF(2, 1)],
|
|
446
|
-
];
|
|
447
|
-
const M4 = [
|
|
448
|
-
[makeF(3, 1), makeF(-2, 1), makeF(4, 1), makeF(-2, 1)],
|
|
449
|
-
[makeF(5, 1), makeF(3, 1), makeF(-3, 1), makeF(-2, 1)],
|
|
450
|
-
[makeF(5, 1), makeF(-2, 1), makeF(2, 1), makeF(-2, 1)],
|
|
451
|
-
[makeF(5, 1), makeF(-2, 1), makeF(-3, 1), makeF(3, 1)],
|
|
452
|
-
];
|
|
453
|
-
|
|
454
|
-
// 1) A * B
|
|
455
|
-
const AB = matMul(A, B);
|
|
456
|
-
|
|
457
|
-
// 2) A ** 2
|
|
458
|
-
const A2 = matMul(A, A);
|
|
459
|
-
|
|
460
|
-
// 3) A ** -1 (2x2)
|
|
461
|
-
const invInfo = inv2(A);
|
|
462
|
-
const Ainv = invInfo.inv;
|
|
463
|
-
|
|
464
|
-
// 4) det(M3)
|
|
465
|
-
const detM3 = det3(M3);
|
|
466
|
-
const sTerms = det3SarrusTerms(M3);
|
|
467
|
-
|
|
468
|
-
// 5) eigenvals(M4) via LeVerrier + integer roots
|
|
469
|
-
const M4i = toIntMat(M4);
|
|
470
|
-
const coeff = leverrier(M4i); // [1, c1, c2, c3, c4]
|
|
471
|
-
let rem = coeff.slice();
|
|
472
|
-
const roots = [];
|
|
473
|
-
const cand = divisors(coeff[coeff.length - 1]);
|
|
474
|
-
for (const r of cand) {
|
|
475
|
-
while (evalPolyDesc(rem, r) === 0) {
|
|
476
|
-
roots.push(r);
|
|
477
|
-
rem = syntheticDivDesc(rem, r);
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
// multiplicities map
|
|
481
|
-
const mult = {};
|
|
482
|
-
for (const r of roots) {
|
|
483
|
-
mult[r] = (mult[r] || 0) + 1;
|
|
484
|
-
}
|
|
485
|
-
const eigOrder = Object.keys(mult)
|
|
486
|
-
.map(Number)
|
|
487
|
-
.sort((a, b) => a - b);
|
|
488
|
-
const eigDump = '{ ' + eigOrder.map((v) => `${v}: ${mult[v]}`).join(', ') + ' }';
|
|
489
|
-
|
|
490
|
-
// Pretty Answer
|
|
491
|
-
const ans = [];
|
|
492
|
-
ans.push('Case 1:');
|
|
493
|
-
ans.push(`Matrix([[1, 3], [-2, 3]])*Matrix([[0, 3], [0, 7]]) = ${matStr(AB)}`);
|
|
494
|
-
ans.push('');
|
|
495
|
-
ans.push('Case 2:');
|
|
496
|
-
ans.push(`Matrix([[1, 3], [-2, 3]])**2 = ${matStr(A2)}`);
|
|
497
|
-
ans.push('');
|
|
498
|
-
ans.push('Case 3:');
|
|
499
|
-
ans.push(`Matrix([[1, 3], [-2, 3]])**-1 = ${matStr(Ainv)}`);
|
|
500
|
-
ans.push('');
|
|
501
|
-
ans.push('Case 4:');
|
|
502
|
-
ans.push(`Matrix([[1, 0, 1], [2, -1, 3], [4, 3, 2]]).det() = ${f2s(detM3)}`);
|
|
503
|
-
ans.push('');
|
|
504
|
-
ans.push('Case 5:');
|
|
505
|
-
ans.push(`Matrix([[3, -2, 4, -2], [5, 3, -3, -2], [5, -2, 2, -2], [5, -2, -3, 3]]).eigenvals() = ${eigDump}`);
|
|
506
|
-
|
|
507
|
-
// Reason why
|
|
508
|
-
const why = [];
|
|
509
|
-
// Case 1 explanation
|
|
510
|
-
why.push('[1] Matrix product entry-wise:');
|
|
511
|
-
why.push(' C[1,1] = 1·0 + 3·0 = 0');
|
|
512
|
-
why.push(' C[1,2] = 1·3 + 3·7 = 3 + 21 = 24');
|
|
513
|
-
why.push(' C[2,1] = (−2)·0 + 3·0 = 0');
|
|
514
|
-
why.push(' C[2,2] = (−2)·3 + 3·7 = −6 + 21 = 15');
|
|
515
|
-
// Case 2
|
|
516
|
-
why.push('[2] Power: A**2 = A·A (standard multiplication).');
|
|
517
|
-
// Case 3 inverse
|
|
518
|
-
const detA = invInfo.det,
|
|
519
|
-
adjA = invInfo.adj;
|
|
520
|
-
why.push('[3] Inverse via adjugate/determinant:');
|
|
521
|
-
why.push(` det(A) = 1·3 − 3·(−2) = 3 + 6 = ${f2s(detA)}`);
|
|
522
|
-
why.push(` adj(A) = [[3, −3],[2, 1]]; A^{-1} = (1/det)·adj(A).`);
|
|
523
|
-
// Case 4 determinant
|
|
524
|
-
why.push('[4] det(3×3) by Sarrus:');
|
|
525
|
-
why.push(` Pos = ${sTerms.pos.map(f2s).join(', ')}`);
|
|
526
|
-
why.push(` Neg = ${sTerms.neg.map(f2s).join(', ')}`);
|
|
527
|
-
why.push(
|
|
528
|
-
` det = (Pos sum) − (Neg sum) = ${f2s(addF(addF(sTerms.pos[0], addF(sTerms.pos[1], sTerms.pos[2])), makeF(0, 1)))} − ${f2s(addF(addF(sTerms.neg[0], addF(sTerms.neg[1], sTerms.neg[2])), makeF(0, 1)))} = ${f2s(detM3)}`,
|
|
529
|
-
);
|
|
530
|
-
// Case 5 eigen
|
|
531
|
-
const polyStr = polyToStringDesc(coeff);
|
|
532
|
-
why.push('[5] Faddeev–LeVerrier gives characteristic polynomial:');
|
|
533
|
-
why.push(` χ_A(λ) = ${polyStr}`);
|
|
534
|
-
why.push(' Integer-root factorization yields eigenvalues with multiplicities as printed.');
|
|
535
|
-
|
|
536
|
-
// Check
|
|
537
|
-
const chk = [];
|
|
538
|
-
// Case 1 recompute expected
|
|
539
|
-
const AB_expected = [
|
|
540
|
-
[makeF(0, 1), makeF(24, 1)],
|
|
541
|
-
[makeF(0, 1), makeF(15, 1)],
|
|
542
|
-
];
|
|
543
|
-
chk.push(matEq(AB, AB_expected) ? '• Case 1 OK (product matches expected). ✓' : '• Case 1 mismatch. ✗');
|
|
544
|
-
// Case 2: multiply A by Ainv*A*Ainv? simpler: compute by mul and compare
|
|
545
|
-
const A2_expected = matMul(A, A);
|
|
546
|
-
chk.push(matEq(A2, A2_expected) ? '• Case 2 OK (square computed). ✓' : '• Case 2 mismatch. ✗');
|
|
547
|
-
// Case 3: A*Ainv==I and Ainv*A==I
|
|
548
|
-
const I2 = identityFrac(2);
|
|
549
|
-
chk.push(
|
|
550
|
-
matEq(matMul(A, Ainv), I2) && matEq(matMul(Ainv, A), I2)
|
|
551
|
-
? '• Case 3 OK (inverse check both sides). ✓'
|
|
552
|
-
: '• Case 3 inverse failed. ✗',
|
|
553
|
-
);
|
|
554
|
-
// Case 4: cross-check det3 by expansion swapping a row sign trick (simple recompute)
|
|
555
|
-
chk.push(f2s(detM3) === '-1' ? '• Case 4 OK (determinant = -1). ✓' : '• Case 4 determinant unexpected. ✗');
|
|
556
|
-
// Case 5: verify invariants: trace = sum eigenvalues; det = product eigenvalues; Cayley–Hamilton
|
|
557
|
-
const trace = M4i[0][0] + M4i[1][1] + M4i[2][2] + M4i[3][3];
|
|
558
|
-
const sumEig = eigOrder.reduce((s, v) => s + v * mult[v], 0);
|
|
559
|
-
const prodEig = eigOrder.reduce((p, v) => p * v ** mult[v], 1);
|
|
560
|
-
chk.push(trace === sumEig ? '• Case 5: trace equals sum of eigenvalues. ✓' : '• Case 5: trace/sum mismatch. ✗');
|
|
561
|
-
// determinant from coefficients is (-1)^n*c_n = c4 with sign? For χ = λ^4 + c1 λ^3 + ... + c4, det = c4 (up to sign pattern already baked)
|
|
562
|
-
const detFromCoeff = coeff[coeff.length - 1];
|
|
563
|
-
chk.push(
|
|
564
|
-
detFromCoeff === prodEig
|
|
565
|
-
? '• Case 5: det equals product of eigenvalues. ✓'
|
|
566
|
-
: '• Case 5: det/product mismatch. ✗',
|
|
567
|
-
);
|
|
568
|
-
// Cayley–Hamilton: evaluate χ_A(A) == 0
|
|
569
|
-
const zeroCH = isZeroMatrix(polyEvalMat(M4, coeff));
|
|
570
|
-
chk.push(zeroCH ? '• Case 5: Cayley–Hamilton (χ_A(A)=0). ✓' : '• Case 5: Cayley–Hamilton failed. ✗');
|
|
571
|
-
|
|
572
|
-
return { ans: ans.join('\n'), why: why.join('\n'), chk: chk.join('\n') };
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
// Pretty polynomial string (descending)
|
|
576
|
-
function polyToStringDesc(coeff) {
|
|
577
|
-
const n = coeff.length - 1; // degree
|
|
578
|
-
const parts = [];
|
|
579
|
-
for (let i = 0; i < coeff.length; i++) {
|
|
580
|
-
const c = coeff[i];
|
|
581
|
-
const p = n - i;
|
|
582
|
-
if (c === 0) continue;
|
|
583
|
-
const sign = c > 0 ? '+' : '-';
|
|
584
|
-
const a = Math.abs(c);
|
|
585
|
-
let term = '';
|
|
586
|
-
if (p === 0) {
|
|
587
|
-
term = '' + a;
|
|
588
|
-
} else if (p === 1) {
|
|
589
|
-
term = (a === 1 ? '' : '%d '.replace('%d', a)) + 'λ';
|
|
590
|
-
} else {
|
|
591
|
-
term = (a === 1 ? '' : '%d '.replace('%d', a)) + 'λ^' + p;
|
|
592
|
-
}
|
|
593
|
-
parts.push([sign, term]);
|
|
594
|
-
}
|
|
595
|
-
if (!parts.length) return '0';
|
|
596
|
-
let out = (parts[0][0] === '+' ? '' : '-') + parts[0][1];
|
|
597
|
-
for (let i = 1; i < parts.length; i++) out += ' ' + parts[i][0] + ' ' + parts[i][1];
|
|
598
|
-
return out;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
// Evaluate polynomial matrix χ(A) with fraction arithmetic (descending coeff)
|
|
602
|
-
function polyEvalMat(A_int, coeff) {
|
|
603
|
-
// Lift integer matrix to fractions
|
|
604
|
-
const A = A_int.map((row) => row.map((x) => makeF(x, 1)));
|
|
605
|
-
const n = A.length,
|
|
606
|
-
deg = coeff.length - 1;
|
|
607
|
-
// Horner-like accumulation: start with zero matrix
|
|
608
|
-
let M = zeros(n, n);
|
|
609
|
-
for (const c of coeff) {
|
|
610
|
-
M = matMul(M, A); // M = M*A
|
|
611
|
-
M = matAdd(M, matScalar(identityFrac(n), makeF(c, 1))); // + c*I
|
|
612
|
-
}
|
|
613
|
-
return M;
|
|
614
|
-
}
|
|
615
|
-
function isZeroMatrix(M) {
|
|
616
|
-
for (const r of M) for (const x of r) if (!eqF(x, makeF(0, 1))) return false;
|
|
617
|
-
return true;
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
// UI
|
|
621
|
-
function run() {
|
|
622
|
-
const r = runAll();
|
|
623
|
-
document.getElementById('ans').textContent = r.ans;
|
|
624
|
-
document.getElementById('why').textContent = r.why;
|
|
625
|
-
document.getElementById('chk').textContent = r.chk;
|
|
626
|
-
document.getElementById('status').textContent = 'Computed';
|
|
627
|
-
}
|
|
628
|
-
function downloadARC() {
|
|
629
|
-
const blob = new Blob(
|
|
630
|
-
[
|
|
631
|
-
'Answer\n------\n',
|
|
632
|
-
document.getElementById('ans').textContent,
|
|
633
|
-
'\n\n',
|
|
634
|
-
'Reason why\n----------\n',
|
|
635
|
-
document.getElementById('why').textContent,
|
|
636
|
-
'\n\n',
|
|
637
|
-
'Check (harness)\n---------------\n',
|
|
638
|
-
document.getElementById('chk').textContent,
|
|
639
|
-
],
|
|
640
|
-
{ type: 'text/plain' },
|
|
641
|
-
);
|
|
642
|
-
const a = document.createElement('a');
|
|
643
|
-
a.href = URL.createObjectURL(blob);
|
|
644
|
-
a.download = 'matrix_output.txt';
|
|
645
|
-
a.click();
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
window.addEventListener('DOMContentLoaded', run);
|
|
649
|
-
</script>
|
|
650
|
-
</body>
|
|
651
|
-
</html>
|