@danielsimonjr/mathts-matrix 0.1.10 → 0.1.11
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.
|
@@ -130,201 +130,6 @@ function applyHouseholderRight(A, v, beta, startRow, startCol) {
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
// src/operations/eig.ts
|
|
133
|
-
var DEFAULT_MAX_ITERATIONS = 1e3;
|
|
134
|
-
var DEFAULT_TOLERANCE = 1e-12;
|
|
135
|
-
function hessenberg(A) {
|
|
136
|
-
const n = A.length;
|
|
137
|
-
const H = cloneMatrix(A);
|
|
138
|
-
const Q = eye(n);
|
|
139
|
-
for (let k = 0; k < n - 2; k++) {
|
|
140
|
-
const x = [];
|
|
141
|
-
for (let i = k + 1; i < n; i++) {
|
|
142
|
-
x.push(H[i][k]);
|
|
143
|
-
}
|
|
144
|
-
const { v, beta } = householder(x);
|
|
145
|
-
if (beta !== 0) {
|
|
146
|
-
applyHouseholderLeft(H, v, beta, k + 1, k);
|
|
147
|
-
applyHouseholderRight(H, v, beta, 0, k + 1);
|
|
148
|
-
applyHouseholderRight(Q, v, beta, 0, k + 1);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
for (let i = 0; i < n; i++) {
|
|
152
|
-
for (let j = 0; j < i - 1; j++) {
|
|
153
|
-
H[i][j] = 0;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
return { H, Q };
|
|
157
|
-
}
|
|
158
|
-
function givens(a, b) {
|
|
159
|
-
if (b === 0) {
|
|
160
|
-
return { c: 1, s: 0 };
|
|
161
|
-
} else if (Math.abs(b) > Math.abs(a)) {
|
|
162
|
-
const t = -a / b;
|
|
163
|
-
const s = 1 / Math.sqrt(1 + t * t);
|
|
164
|
-
return { c: s * t, s };
|
|
165
|
-
} else {
|
|
166
|
-
const t = -b / a;
|
|
167
|
-
const c = 1 / Math.sqrt(1 + t * t);
|
|
168
|
-
return { c, s: c * t };
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
function applyGivensLeft(A, c, s, i, k, startCol) {
|
|
172
|
-
const n = A[0].length;
|
|
173
|
-
for (let j = startCol; j < n; j++) {
|
|
174
|
-
const temp = c * A[i][j] - s * A[k][j];
|
|
175
|
-
A[k][j] = s * A[i][j] + c * A[k][j];
|
|
176
|
-
A[i][j] = temp;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
function applyGivensRight(A, c, s, i, k, startRow) {
|
|
180
|
-
const m = A.length;
|
|
181
|
-
for (let j = startRow; j < m; j++) {
|
|
182
|
-
const temp = c * A[j][i] - s * A[j][k];
|
|
183
|
-
A[j][k] = s * A[j][i] + c * A[j][k];
|
|
184
|
-
A[j][i] = temp;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
function qrStep(H, Q, start, end) {
|
|
188
|
-
const n = end - start + 1;
|
|
189
|
-
if (n < 2) return;
|
|
190
|
-
const a = H[end - 1][end - 1];
|
|
191
|
-
const b = H[end - 1][end];
|
|
192
|
-
const c = H[end][end - 1];
|
|
193
|
-
const d = H[end][end];
|
|
194
|
-
const trace = a + d;
|
|
195
|
-
const det = a * d - b * c;
|
|
196
|
-
const disc = trace * trace - 4 * det;
|
|
197
|
-
let shift;
|
|
198
|
-
if (disc >= 0) {
|
|
199
|
-
const sqrtDisc = Math.sqrt(disc);
|
|
200
|
-
const e1 = (trace + sqrtDisc) / 2;
|
|
201
|
-
const e2 = (trace - sqrtDisc) / 2;
|
|
202
|
-
shift = Math.abs(e1 - d) < Math.abs(e2 - d) ? e1 : e2;
|
|
203
|
-
} else {
|
|
204
|
-
shift = d;
|
|
205
|
-
}
|
|
206
|
-
let x = H[start][start] - shift;
|
|
207
|
-
let y = H[start + 1][start];
|
|
208
|
-
for (let k = start; k < end; k++) {
|
|
209
|
-
const { c: c2, s } = givens(x, y);
|
|
210
|
-
applyGivensLeft(H, c2, s, k, k + 1, Math.max(0, k - 1));
|
|
211
|
-
applyGivensRight(H, c2, s, k, k + 1, 0);
|
|
212
|
-
applyGivensRight(Q, c2, s, k, k + 1, 0);
|
|
213
|
-
if (k < end - 1) {
|
|
214
|
-
x = H[k + 1][k];
|
|
215
|
-
y = H[k + 2][k];
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
function extractEigenvalues(H, tolerance) {
|
|
220
|
-
const n = H.length;
|
|
221
|
-
const eigenvalues = [];
|
|
222
|
-
let i = 0;
|
|
223
|
-
while (i < n) {
|
|
224
|
-
if (i === n - 1 || Math.abs(H[i + 1][i]) <= tolerance) {
|
|
225
|
-
eigenvalues.push({ re: H[i][i], im: 0 });
|
|
226
|
-
i++;
|
|
227
|
-
} else {
|
|
228
|
-
const a = H[i][i];
|
|
229
|
-
const b = H[i][i + 1];
|
|
230
|
-
const c = H[i + 1][i];
|
|
231
|
-
const d = H[i + 1][i + 1];
|
|
232
|
-
const trace = a + d;
|
|
233
|
-
const det = a * d - b * c;
|
|
234
|
-
const disc = trace * trace - 4 * det;
|
|
235
|
-
if (disc >= 0) {
|
|
236
|
-
const sqrtDisc = Math.sqrt(disc);
|
|
237
|
-
eigenvalues.push({ re: (trace + sqrtDisc) / 2, im: 0 });
|
|
238
|
-
eigenvalues.push({ re: (trace - sqrtDisc) / 2, im: 0 });
|
|
239
|
-
} else {
|
|
240
|
-
const realPart = trace / 2;
|
|
241
|
-
const imagPart = Math.sqrt(-disc) / 2;
|
|
242
|
-
eigenvalues.push({ re: realPart, im: imagPart });
|
|
243
|
-
eigenvalues.push({ re: realPart, im: -imagPart });
|
|
244
|
-
}
|
|
245
|
-
i += 2;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
return eigenvalues;
|
|
249
|
-
}
|
|
250
|
-
function inverseIteration(A, eigenvalue, tolerance, maxIterations) {
|
|
251
|
-
const n = A.length;
|
|
252
|
-
if (eigenvalue.im !== 0) {
|
|
253
|
-
return new Array(n).fill(0);
|
|
254
|
-
}
|
|
255
|
-
const lambda = eigenvalue.re;
|
|
256
|
-
const shifted = cloneMatrix(A);
|
|
257
|
-
for (let i = 0; i < n; i++) {
|
|
258
|
-
shifted[i][i] -= lambda;
|
|
259
|
-
}
|
|
260
|
-
for (let i = 0; i < n; i++) {
|
|
261
|
-
shifted[i][i] += tolerance * 1e3;
|
|
262
|
-
}
|
|
263
|
-
const LU = cloneMatrix(shifted);
|
|
264
|
-
const perm = Array.from({ length: n }, (_, i) => i);
|
|
265
|
-
for (let k = 0; k < n; k++) {
|
|
266
|
-
let maxVal = Math.abs(LU[k][k]);
|
|
267
|
-
let maxIdx = k;
|
|
268
|
-
for (let i = k + 1; i < n; i++) {
|
|
269
|
-
if (Math.abs(LU[i][k]) > maxVal) {
|
|
270
|
-
maxVal = Math.abs(LU[i][k]);
|
|
271
|
-
maxIdx = i;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
if (maxIdx !== k) {
|
|
275
|
-
[LU[k], LU[maxIdx]] = [LU[maxIdx], LU[k]];
|
|
276
|
-
[perm[k], perm[maxIdx]] = [perm[maxIdx], perm[k]];
|
|
277
|
-
}
|
|
278
|
-
if (Math.abs(LU[k][k]) < tolerance) {
|
|
279
|
-
LU[k][k] = tolerance;
|
|
280
|
-
}
|
|
281
|
-
for (let i = k + 1; i < n; i++) {
|
|
282
|
-
LU[i][k] /= LU[k][k];
|
|
283
|
-
for (let j = k + 1; j < n; j++) {
|
|
284
|
-
LU[i][j] -= LU[i][k] * LU[k][j];
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
const v = new Array(n).fill(1);
|
|
289
|
-
let prevNorm = 0;
|
|
290
|
-
for (let iter = 0; iter < maxIterations; iter++) {
|
|
291
|
-
const y = new Array(n).fill(0);
|
|
292
|
-
const b = new Array(n);
|
|
293
|
-
for (let i = 0; i < n; i++) {
|
|
294
|
-
b[i] = v[perm[i]];
|
|
295
|
-
}
|
|
296
|
-
for (let i = 0; i < n; i++) {
|
|
297
|
-
y[i] = b[i];
|
|
298
|
-
for (let j = 0; j < i; j++) {
|
|
299
|
-
y[i] -= LU[i][j] * y[j];
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
const x = new Array(n).fill(0);
|
|
303
|
-
for (let i = n - 1; i >= 0; i--) {
|
|
304
|
-
x[i] = y[i];
|
|
305
|
-
for (let j = i + 1; j < n; j++) {
|
|
306
|
-
x[i] -= LU[i][j] * x[j];
|
|
307
|
-
}
|
|
308
|
-
x[i] /= LU[i][i];
|
|
309
|
-
}
|
|
310
|
-
let norm = 0;
|
|
311
|
-
for (let i = 0; i < n; i++) {
|
|
312
|
-
norm += x[i] * x[i];
|
|
313
|
-
}
|
|
314
|
-
norm = Math.sqrt(norm);
|
|
315
|
-
if (norm < tolerance) {
|
|
316
|
-
return x;
|
|
317
|
-
}
|
|
318
|
-
for (let i = 0; i < n; i++) {
|
|
319
|
-
v[i] = x[i] / norm;
|
|
320
|
-
}
|
|
321
|
-
if (Math.abs(norm - prevNorm) < tolerance * norm) {
|
|
322
|
-
break;
|
|
323
|
-
}
|
|
324
|
-
prevNorm = norm;
|
|
325
|
-
}
|
|
326
|
-
return v;
|
|
327
|
-
}
|
|
328
133
|
var EIG_GEN_EPS = 2220446049250313e-31;
|
|
329
134
|
function cdiv(xr, xi, yr, yi) {
|
|
330
135
|
let rr;
|
|
@@ -723,11 +528,7 @@ function eigGeneral(A, computeVectors, symmetric) {
|
|
|
723
528
|
return { values, vectors, isSymmetric: symmetric };
|
|
724
529
|
}
|
|
725
530
|
function eig(matrix, options = {}) {
|
|
726
|
-
const {
|
|
727
|
-
maxIterations = DEFAULT_MAX_ITERATIONS,
|
|
728
|
-
tolerance = DEFAULT_TOLERANCE,
|
|
729
|
-
computeVectors = true
|
|
730
|
-
} = options;
|
|
531
|
+
const { computeVectors = true } = options;
|
|
731
532
|
let A;
|
|
732
533
|
if (matrix instanceof Float64Array) {
|
|
733
534
|
const n2 = Math.sqrt(matrix.length);
|
|
@@ -755,87 +556,7 @@ function eig(matrix, options = {}) {
|
|
|
755
556
|
isSymmetric: symmetric
|
|
756
557
|
};
|
|
757
558
|
}
|
|
758
|
-
|
|
759
|
-
return eigGeneral(A, computeVectors, symmetric);
|
|
760
|
-
}
|
|
761
|
-
if (n === 2) {
|
|
762
|
-
const a = A[0][0], b = A[0][1], c = A[1][0], d = A[1][1];
|
|
763
|
-
const trace = a + d;
|
|
764
|
-
const det = a * d - b * c;
|
|
765
|
-
const disc = trace * trace - 4 * det;
|
|
766
|
-
let values2;
|
|
767
|
-
let vectors2;
|
|
768
|
-
if (disc >= 0) {
|
|
769
|
-
const sqrtDisc = Math.sqrt(disc);
|
|
770
|
-
const e1 = (trace + sqrtDisc) / 2;
|
|
771
|
-
const e2 = (trace - sqrtDisc) / 2;
|
|
772
|
-
values2 = [
|
|
773
|
-
{ re: e1, im: 0 },
|
|
774
|
-
{ re: e2, im: 0 }
|
|
775
|
-
];
|
|
776
|
-
if (computeVectors) {
|
|
777
|
-
vectors2 = [];
|
|
778
|
-
for (const e of [e1, e2]) {
|
|
779
|
-
if (Math.abs(b) > tolerance) {
|
|
780
|
-
const v = [b, e - a];
|
|
781
|
-
const norm = Math.sqrt(v[0] * v[0] + v[1] * v[1]);
|
|
782
|
-
vectors2.push([v[0] / norm, v[1] / norm]);
|
|
783
|
-
} else if (Math.abs(c) > tolerance) {
|
|
784
|
-
const v = [e - d, c];
|
|
785
|
-
const norm = Math.sqrt(v[0] * v[0] + v[1] * v[1]);
|
|
786
|
-
vectors2.push([v[0] / norm, v[1] / norm]);
|
|
787
|
-
} else {
|
|
788
|
-
vectors2.push(e === a ? [1, 0] : [0, 1]);
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
} else {
|
|
792
|
-
vectors2 = eye(2);
|
|
793
|
-
}
|
|
794
|
-
} else {
|
|
795
|
-
const realPart = trace / 2;
|
|
796
|
-
const imagPart = Math.sqrt(-disc) / 2;
|
|
797
|
-
values2 = [
|
|
798
|
-
{ re: realPart, im: imagPart },
|
|
799
|
-
{ re: realPart, im: -imagPart }
|
|
800
|
-
];
|
|
801
|
-
vectors2 = eye(2);
|
|
802
|
-
}
|
|
803
|
-
return { values: values2, vectors: vectors2, isSymmetric: symmetric };
|
|
804
|
-
}
|
|
805
|
-
const { H, Q } = hessenberg(A);
|
|
806
|
-
let end = n - 1;
|
|
807
|
-
let iter = 0;
|
|
808
|
-
while (end > 0 && iter < maxIterations) {
|
|
809
|
-
let start = end;
|
|
810
|
-
while (start > 0) {
|
|
811
|
-
const scale = Math.abs(H[start - 1][start - 1]) + Math.abs(H[start][start]);
|
|
812
|
-
if (Math.abs(H[start][start - 1]) <= tolerance * scale) {
|
|
813
|
-
H[start][start - 1] = 0;
|
|
814
|
-
break;
|
|
815
|
-
}
|
|
816
|
-
start--;
|
|
817
|
-
}
|
|
818
|
-
if (start === end) {
|
|
819
|
-
end--;
|
|
820
|
-
} else if (start === end - 1) {
|
|
821
|
-
end -= 2;
|
|
822
|
-
} else {
|
|
823
|
-
qrStep(H, Q, start, end);
|
|
824
|
-
}
|
|
825
|
-
iter++;
|
|
826
|
-
}
|
|
827
|
-
const values = extractEigenvalues(H, tolerance);
|
|
828
|
-
let vectors;
|
|
829
|
-
if (computeVectors) {
|
|
830
|
-
vectors = [];
|
|
831
|
-
for (const eigenvalue of values) {
|
|
832
|
-
const v = inverseIteration(A, eigenvalue, tolerance, 100);
|
|
833
|
-
vectors.push(v);
|
|
834
|
-
}
|
|
835
|
-
} else {
|
|
836
|
-
vectors = eye(n);
|
|
837
|
-
}
|
|
838
|
-
return { values, vectors, isSymmetric: symmetric };
|
|
559
|
+
return eigGeneral(A, computeVectors, symmetric);
|
|
839
560
|
}
|
|
840
561
|
function eigvals(matrix, options) {
|
|
841
562
|
return eig(matrix, { ...options, computeVectors: false }).values;
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
normInf,
|
|
16
16
|
powerIteration,
|
|
17
17
|
transpose
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-JRSQE7LB.js";
|
|
19
19
|
import {
|
|
20
20
|
__esm,
|
|
21
21
|
__export,
|
|
@@ -6376,7 +6376,7 @@ async function spectralRadiusWasm(matrix2, options) {
|
|
|
6376
6376
|
}
|
|
6377
6377
|
}
|
|
6378
6378
|
if (!module || n < WASM_EIG_THRESHOLD || typeof module.matrix_spectral_radius !== "function") {
|
|
6379
|
-
const { powerIteration: powerIteration2 } = await import("./eig-
|
|
6379
|
+
const { powerIteration: powerIteration2 } = await import("./eig-PIFFHFJF.js");
|
|
6380
6380
|
const result = powerIteration2(matrix2, options);
|
|
6381
6381
|
return Math.abs(result.value);
|
|
6382
6382
|
}
|
|
@@ -6385,7 +6385,7 @@ async function spectralRadiusWasm(matrix2, options) {
|
|
|
6385
6385
|
try {
|
|
6386
6386
|
return module.matrix_spectral_radius(matrixAlloc.ptr, n);
|
|
6387
6387
|
} catch {
|
|
6388
|
-
const { powerIteration: powerIteration2 } = await import("./eig-
|
|
6388
|
+
const { powerIteration: powerIteration2 } = await import("./eig-PIFFHFJF.js");
|
|
6389
6389
|
const result = powerIteration2(matrix2, options);
|
|
6390
6390
|
return Math.abs(result.value);
|
|
6391
6391
|
} finally {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danielsimonjr/mathts-matrix",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Matrix operations for MathTS with WASM/WebGPU backend support",
|
|
5
5
|
"author": "Daniel Simon Jr.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"build:prod": "tsup src/index.ts --format esm --dts --clean --minify --treeshake && node scripts/copy-wasm.mjs"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@danielsimonjr/mathts-core": "^0.
|
|
35
|
+
"@danielsimonjr/mathts-core": "^0.2.0",
|
|
36
36
|
"@danielsimonjr/mathts-parallel": "^0.3.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|