@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
- if (!symmetric) {
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;
@@ -2,7 +2,7 @@ import {
2
2
  eig,
3
3
  eigvals,
4
4
  powerIteration
5
- } from "./chunk-HT4ZF3LN.js";
5
+ } from "./chunk-JRSQE7LB.js";
6
6
  import "./chunk-4VMDO6W2.js";
7
7
  export {
8
8
  eig,
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  normInf,
16
16
  powerIteration,
17
17
  transpose
18
- } from "./chunk-HT4ZF3LN.js";
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-G72TLEBA.js");
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-G72TLEBA.js");
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.10",
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.1.4",
35
+ "@danielsimonjr/mathts-core": "^0.2.0",
36
36
  "@danielsimonjr/mathts-parallel": "^0.3.0"
37
37
  },
38
38
  "devDependencies": {