@danielsimonjr/mathts-matrix 0.1.12 → 0.1.14

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/dist/index.js CHANGED
@@ -1,21 +1,3 @@
1
- import {
2
- applyHouseholderLeft,
3
- applyHouseholderRight,
4
- cloneMatrix,
5
- eig,
6
- eigvals,
7
- eye,
8
- householder,
9
- isSymmetric,
10
- matAdd,
11
- matMul,
12
- matScale,
13
- matSub,
14
- norm1,
15
- normInf,
16
- powerIteration,
17
- transpose
18
- } from "./chunk-JRSQE7LB.js";
19
1
  import {
20
2
  __esm,
21
3
  __export,
@@ -196,7 +178,7 @@ function scale(a, scalar) {
196
178
  for (let i = 0; i < ad.length; i++) result[i] = ad[i] * scalar;
197
179
  return result;
198
180
  }
199
- function transpose2(a) {
181
+ function transpose(a) {
200
182
  const ad = flat(a);
201
183
  const rows = a.rows;
202
184
  const cols = a.cols;
@@ -1301,7 +1283,7 @@ var init_DenseMatrix = __esm({
1301
1283
  * Matrix transpose
1302
1284
  */
1303
1285
  transpose() {
1304
- return new _DenseMatrix(this.cols, this.rows, transpose2(this));
1286
+ return new _DenseMatrix(this.cols, this.rows, transpose(this));
1305
1287
  }
1306
1288
  /**
1307
1289
  * Negate all elements
@@ -2485,7 +2467,7 @@ var WASMBackend = class {
2485
2467
  try {
2486
2468
  const path = this.config.wasmPath || await this.resolveAsWasmPath();
2487
2469
  const loaded = await this.loadAsModule(path);
2488
- if (typeof loaded.__new !== "function" || typeof loaded.matrix_multiply !== "function") {
2470
+ if (typeof loaded.__new !== "function" || typeof loaded.matrix_multiply_simd_ptr !== "function") {
2489
2471
  console.warn(
2490
2472
  "WASMBackend: loaded module is not the AssemblyScript artifact; falling back to JS. Pass an explicit wasmPath (the AS binary, mathts-as.wasm)."
2491
2473
  );
@@ -2559,7 +2541,15 @@ var WASMBackend = class {
2559
2541
  }
2560
2542
  return instance.exports;
2561
2543
  }
2562
- shouldUseWasm(elementCount) {
2544
+ /**
2545
+ * WASM is only worth its copy/alloc overhead for compute-dense ops. The 2026-07-01
2546
+ * backend audit (`tools/benchmarks/backend-audit`) measured element-wise / transpose
2547
+ * ops 4–6× SLOWER on WASM than JS (memory-bound; the SIMD matmul kernel is the only
2548
+ * clear win, 9–12×). So WASM is reserved for `opKind: 'matmul'`; everything else stays
2549
+ * on JS via each method's existing `jsBackend` fallback.
2550
+ */
2551
+ shouldUseWasm(elementCount, opKind = "elementwise") {
2552
+ if (opKind !== "matmul") return false;
2563
2553
  return this.wasmModule !== null && elementCount >= this.config.minElements;
2564
2554
  }
2565
2555
  getFeatures() {
@@ -2568,137 +2558,49 @@ var WASMBackend = class {
2568
2558
  // =========================================================================
2569
2559
  // Element-wise Operations
2570
2560
  // =========================================================================
2561
+ // Element-wise ops run on JS. The AS element-wise kernels (matrix_add/sub/mul/div/scale/neg,
2562
+ // array_abs) were measured 4–6× SLOWER than JS (memory-bound + copy/alloc overhead —
2563
+ // tools/benchmarks/backend-audit) and retired via `shouldUseWasm` (returns false for
2564
+ // non-matmul). These delegate to `jsBackend`; the dead WASM branches were removed 2026-07-02.
2571
2565
  add(a, b) {
2572
- const elementCount = a.rows * a.cols;
2573
- if (!this.shouldUseWasm(elementCount)) return jsBackend.add(a, b);
2574
- const mod = this.wasmModule;
2575
- const aAlloc = writeAsFloat64Array(this.allocCache, mod, a.toFloat64Array());
2576
- const bAlloc = writeAsFloat64Array(this.allocCache, mod, b.toFloat64Array());
2577
- const rAlloc = allocAsFloat64Array(this.allocCache, mod, elementCount);
2578
- try {
2579
- mod.matrix_add(aAlloc.headerPtr, bAlloc.headerPtr, rAlloc.headerPtr);
2580
- const result = readAsFloat64Array(mod, rAlloc);
2581
- return DenseMatrix.fromFlat(a.rows, a.cols, Array.from(result));
2582
- } finally {
2583
- this.allocCache.release(aAlloc);
2584
- this.allocCache.release(bAlloc);
2585
- this.allocCache.release(rAlloc);
2586
- }
2566
+ return jsBackend.add(a, b);
2587
2567
  }
2588
2568
  subtract(a, b) {
2589
- const elementCount = a.rows * a.cols;
2590
- if (!this.shouldUseWasm(elementCount)) return jsBackend.subtract(a, b);
2591
- const mod = this.wasmModule;
2592
- const aAlloc = writeAsFloat64Array(this.allocCache, mod, a.toFloat64Array());
2593
- const bAlloc = writeAsFloat64Array(this.allocCache, mod, b.toFloat64Array());
2594
- const rAlloc = allocAsFloat64Array(this.allocCache, mod, elementCount);
2595
- try {
2596
- mod.matrix_sub(aAlloc.headerPtr, bAlloc.headerPtr, rAlloc.headerPtr);
2597
- const result = readAsFloat64Array(mod, rAlloc);
2598
- return DenseMatrix.fromFlat(a.rows, a.cols, Array.from(result));
2599
- } finally {
2600
- this.allocCache.release(aAlloc);
2601
- this.allocCache.release(bAlloc);
2602
- this.allocCache.release(rAlloc);
2603
- }
2569
+ return jsBackend.subtract(a, b);
2604
2570
  }
2605
2571
  multiplyElementwise(a, b) {
2606
- const elementCount = a.rows * a.cols;
2607
- if (!this.shouldUseWasm(elementCount)) return jsBackend.multiplyElementwise(a, b);
2608
- const mod = this.wasmModule;
2609
- const aAlloc = writeAsFloat64Array(this.allocCache, mod, a.toFloat64Array());
2610
- const bAlloc = writeAsFloat64Array(this.allocCache, mod, b.toFloat64Array());
2611
- const rAlloc = allocAsFloat64Array(this.allocCache, mod, elementCount);
2612
- try {
2613
- mod.matrix_mul_elementwise(aAlloc.headerPtr, bAlloc.headerPtr, rAlloc.headerPtr);
2614
- const result = readAsFloat64Array(mod, rAlloc);
2615
- return DenseMatrix.fromFlat(a.rows, a.cols, Array.from(result));
2616
- } finally {
2617
- this.allocCache.release(aAlloc);
2618
- this.allocCache.release(bAlloc);
2619
- this.allocCache.release(rAlloc);
2620
- }
2572
+ return jsBackend.multiplyElementwise(a, b);
2621
2573
  }
2622
2574
  divideElementwise(a, b) {
2623
- const elementCount = a.rows * a.cols;
2624
- if (!this.shouldUseWasm(elementCount)) return jsBackend.divideElementwise(a, b);
2625
- const mod = this.wasmModule;
2626
- const aAlloc = writeAsFloat64Array(this.allocCache, mod, a.toFloat64Array());
2627
- const bAlloc = writeAsFloat64Array(this.allocCache, mod, b.toFloat64Array());
2628
- const rAlloc = allocAsFloat64Array(this.allocCache, mod, elementCount);
2629
- try {
2630
- mod.matrix_div_elementwise(aAlloc.headerPtr, bAlloc.headerPtr, rAlloc.headerPtr);
2631
- const result = readAsFloat64Array(mod, rAlloc);
2632
- return DenseMatrix.fromFlat(a.rows, a.cols, Array.from(result));
2633
- } finally {
2634
- this.allocCache.release(aAlloc);
2635
- this.allocCache.release(bAlloc);
2636
- this.allocCache.release(rAlloc);
2637
- }
2575
+ return jsBackend.divideElementwise(a, b);
2638
2576
  }
2639
2577
  scale(a, scalar) {
2640
- const elementCount = a.rows * a.cols;
2641
- if (!this.shouldUseWasm(elementCount)) return jsBackend.scale(a, scalar);
2642
- const mod = this.wasmModule;
2643
- const aAlloc = writeAsFloat64Array(this.allocCache, mod, a.toFloat64Array());
2644
- const rAlloc = allocAsFloat64Array(this.allocCache, mod, elementCount);
2645
- try {
2646
- mod.matrix_scale(aAlloc.headerPtr, scalar, rAlloc.headerPtr);
2647
- const result = readAsFloat64Array(mod, rAlloc);
2648
- return DenseMatrix.fromFlat(a.rows, a.cols, Array.from(result));
2649
- } finally {
2650
- this.allocCache.release(aAlloc);
2651
- this.allocCache.release(rAlloc);
2652
- }
2578
+ return jsBackend.scale(a, scalar);
2653
2579
  }
2654
2580
  abs(a) {
2655
- const elementCount = a.rows * a.cols;
2656
- if (!this.shouldUseWasm(elementCount)) return jsBackend.abs(a);
2657
- const mod = this.wasmModule;
2658
- const aAlloc = writeAsFloat64Array(this.allocCache, mod, a.toFloat64Array());
2659
- const rAlloc = allocAsFloat64Array(this.allocCache, mod, elementCount);
2660
- try {
2661
- mod.array_abs(aAlloc.headerPtr, rAlloc.headerPtr);
2662
- const result = readAsFloat64Array(mod, rAlloc);
2663
- return DenseMatrix.fromFlat(a.rows, a.cols, Array.from(result));
2664
- } finally {
2665
- this.allocCache.release(aAlloc);
2666
- this.allocCache.release(rAlloc);
2667
- }
2581
+ return jsBackend.abs(a);
2668
2582
  }
2669
2583
  negate(a) {
2670
- const elementCount = a.rows * a.cols;
2671
- if (!this.shouldUseWasm(elementCount)) return jsBackend.negate(a);
2672
- const mod = this.wasmModule;
2673
- const aAlloc = writeAsFloat64Array(this.allocCache, mod, a.toFloat64Array());
2674
- const rAlloc = allocAsFloat64Array(this.allocCache, mod, elementCount);
2675
- try {
2676
- mod.matrix_neg(aAlloc.headerPtr, rAlloc.headerPtr);
2677
- const result = readAsFloat64Array(mod, rAlloc);
2678
- return DenseMatrix.fromFlat(a.rows, a.cols, Array.from(result));
2679
- } finally {
2680
- this.allocCache.release(aAlloc);
2681
- this.allocCache.release(rAlloc);
2682
- }
2584
+ return jsBackend.negate(a);
2683
2585
  }
2684
2586
  // =========================================================================
2685
2587
  // Matrix Operations
2686
2588
  // =========================================================================
2687
2589
  multiply(a, b) {
2688
2590
  const elementCount = a.rows * a.cols + b.rows * b.cols;
2689
- if (!this.shouldUseWasm(elementCount)) return jsBackend.multiply(a, b);
2591
+ if (!this.shouldUseWasm(elementCount, "matmul")) return jsBackend.multiply(a, b);
2690
2592
  const mod = this.wasmModule;
2691
2593
  const aAlloc = writeAsFloat64Array(this.allocCache, mod, a.toFloat64Array());
2692
2594
  const bAlloc = writeAsFloat64Array(this.allocCache, mod, b.toFloat64Array());
2693
2595
  const rAlloc = allocAsFloat64Array(this.allocCache, mod, a.rows * b.cols);
2694
2596
  try {
2695
- mod.matrix_multiply(
2696
- aAlloc.headerPtr,
2597
+ mod.matrix_multiply_simd_ptr(
2598
+ aAlloc.bufferPtr,
2697
2599
  a.rows,
2698
2600
  a.cols,
2699
- bAlloc.headerPtr,
2601
+ bAlloc.bufferPtr,
2700
2602
  b.cols,
2701
- rAlloc.headerPtr
2603
+ rAlloc.bufferPtr
2702
2604
  );
2703
2605
  const result = readAsFloat64Array(mod, rAlloc);
2704
2606
  return DenseMatrix.fromFlat(a.rows, b.cols, Array.from(result));
@@ -2708,61 +2610,24 @@ var WASMBackend = class {
2708
2610
  this.allocCache.release(rAlloc);
2709
2611
  }
2710
2612
  }
2613
+ // transpose is memory-bound (like element-wise) — retired from WASM, runs on JS.
2711
2614
  transpose(a) {
2712
- const elementCount = a.rows * a.cols;
2713
- if (!this.shouldUseWasm(elementCount)) return jsBackend.transpose(a);
2714
- const mod = this.wasmModule;
2715
- const aAlloc = writeAsFloat64Array(this.allocCache, mod, a.toFloat64Array());
2716
- const rAlloc = allocAsFloat64Array(this.allocCache, mod, elementCount);
2717
- try {
2718
- mod.matrix_transpose(aAlloc.headerPtr, a.rows, a.cols, rAlloc.headerPtr);
2719
- const result = readAsFloat64Array(mod, rAlloc);
2720
- return DenseMatrix.fromFlat(a.cols, a.rows, Array.from(result));
2721
- } finally {
2722
- this.allocCache.release(aAlloc);
2723
- this.allocCache.release(rAlloc);
2724
- }
2615
+ return jsBackend.transpose(a);
2725
2616
  }
2726
2617
  // =========================================================================
2727
- // Reduction Operations
2618
+ // Reduction Operations — memory-bound (single pass), retired from WASM → JS.
2728
2619
  // =========================================================================
2729
2620
  sum(a) {
2730
- const elementCount = a.rows * a.cols;
2731
- if (!this.shouldUseWasm(elementCount)) return jsBackend.sum(a);
2732
- const mod = this.wasmModule;
2733
- const aAlloc = writeAsFloat64Array(this.allocCache, mod, a.toFloat64Array());
2734
- try {
2735
- return mod.matrix_sum(aAlloc.headerPtr);
2736
- } finally {
2737
- this.allocCache.release(aAlloc);
2738
- }
2621
+ return jsBackend.sum(a);
2739
2622
  }
2740
2623
  sumAxis(a, axis) {
2741
2624
  return jsBackend.sumAxis(a, axis);
2742
2625
  }
2743
2626
  norm(a) {
2744
- const elementCount = a.rows * a.cols;
2745
- if (!this.shouldUseWasm(elementCount)) return jsBackend.norm(a);
2746
- const mod = this.wasmModule;
2747
- const aAlloc = writeAsFloat64Array(this.allocCache, mod, a.toFloat64Array());
2748
- try {
2749
- return mod.matrix_norm_frobenius(aAlloc.headerPtr);
2750
- } finally {
2751
- this.allocCache.release(aAlloc);
2752
- }
2627
+ return jsBackend.norm(a);
2753
2628
  }
2754
2629
  dot(a, b) {
2755
- const elementCount = a.rows * a.cols;
2756
- if (!this.shouldUseWasm(elementCount)) return jsBackend.dot(a, b);
2757
- const mod = this.wasmModule;
2758
- const aAlloc = writeAsFloat64Array(this.allocCache, mod, a.toFloat64Array());
2759
- const bAlloc = writeAsFloat64Array(this.allocCache, mod, b.toFloat64Array());
2760
- try {
2761
- return mod.array_dot(aAlloc.headerPtr, bAlloc.headerPtr);
2762
- } finally {
2763
- this.allocCache.release(aAlloc);
2764
- this.allocCache.release(bAlloc);
2765
- }
2630
+ return jsBackend.dot(a, b);
2766
2631
  }
2767
2632
  // =========================================================================
2768
2633
  // LU / QR / Cholesky / Inverse / Determinant
@@ -5070,8 +4935,13 @@ backendRegistry.register(wasmBackend);
5070
4935
  var DEFAULT_EXTENDED_HINTS = {
5071
4936
  ...DEFAULT_BACKEND_HINTS,
5072
4937
  operationThresholds: {
5073
- multiply: { wasm: 500, gpu: 5e4 },
4938
+ // matmul: the SIMD-WASM kernel wins from ~256 elems (16²), solidly 1.3–2.2× (measured,
4939
+ // tools/benchmarks/matmul-threshold.mjs); below that copy/alloc overhead dominates (8²
4940
+ // loses, 12² marginal). Dropped 500→256 to stop forcing 16²–22² matmuls onto JS.
4941
+ multiply: { wasm: 256, gpu: 5e4 },
5074
4942
  decomposition: { wasm: 100, gpu: 1e4 },
4943
+ // transpose WASM is retired (memory-bound, lost 4–6×) — WASMBackend.transpose always uses
4944
+ // JS regardless of this gate; kept high so the manager doesn't even select the WASM backend.
5075
4945
  transpose: { wasm: 2e3, gpu: 2e5 }
5076
4946
  },
5077
4947
  autoSIMD: true,
@@ -5760,7 +5630,7 @@ var WasmLoader = class _WasmLoader {
5760
5630
  }
5761
5631
  /**
5762
5632
  * Decode a managed Float64Array RETURNED by an AssemblyScript export
5763
- * (e.g. `matrix_svd`, `matrix_eig_symmetric`) into a fresh JS copy.
5633
+ * (e.g. the `matrix_lu_decompose` / `matrix_qr_decompose` outputs) into a fresh JS copy.
5764
5634
  *
5765
5635
  * AS exports that return a `Float64Array` hand back the typed-array
5766
5636
  * *header* pointer. The header is a 12-byte block laid out as
@@ -5972,6 +5842,590 @@ var WasmLoader = class _WasmLoader {
5972
5842
  };
5973
5843
  var wasmLoader = WasmLoader.getInstance();
5974
5844
 
5845
+ // src/operations/common.ts
5846
+ function eye(n) {
5847
+ return Array.from(
5848
+ { length: n },
5849
+ (_, i) => Array.from({ length: n }, (_2, j) => i === j ? 1 : 0)
5850
+ );
5851
+ }
5852
+ function cloneMatrix(A) {
5853
+ return A.map((row2) => [...row2]);
5854
+ }
5855
+ function transpose2(A) {
5856
+ const m = A.length;
5857
+ const n = A[0].length;
5858
+ return Array.from({ length: n }, (_, j) => Array.from({ length: m }, (_2, i) => A[i][j]));
5859
+ }
5860
+ function isSymmetric(matrix2, tolerance = 1e-10) {
5861
+ const n = matrix2.length;
5862
+ if (n === 0) return true;
5863
+ if (matrix2[0].length !== n) return false;
5864
+ for (let i = 0; i < n; i++) {
5865
+ for (let j = i + 1; j < n; j++) {
5866
+ if (Math.abs(matrix2[i][j] - matrix2[j][i]) > tolerance) {
5867
+ return false;
5868
+ }
5869
+ }
5870
+ }
5871
+ return true;
5872
+ }
5873
+ function matMul(A, B2) {
5874
+ const m = A.length;
5875
+ const p = A[0].length;
5876
+ const n = B2[0].length;
5877
+ const C = Array.from({ length: m }, () => new Array(n).fill(0));
5878
+ for (let i = 0; i < m; i++) {
5879
+ for (let k = 0; k < p; k++) {
5880
+ const aik = A[i][k];
5881
+ if (aik === 0) continue;
5882
+ for (let j = 0; j < n; j++) C[i][j] += aik * B2[k][j];
5883
+ }
5884
+ }
5885
+ return C;
5886
+ }
5887
+ function matAdd(A, B2) {
5888
+ const n = A.length;
5889
+ return Array.from(
5890
+ { length: n },
5891
+ (_, i) => Array.from({ length: n }, (_2, j) => A[i][j] + B2[i][j])
5892
+ );
5893
+ }
5894
+ function matSub(A, B2) {
5895
+ const n = A.length;
5896
+ return Array.from(
5897
+ { length: n },
5898
+ (_, i) => Array.from({ length: n }, (_2, j) => A[i][j] - B2[i][j])
5899
+ );
5900
+ }
5901
+ function matScale(A, c) {
5902
+ return A.map((row2) => row2.map((v) => v * c));
5903
+ }
5904
+ function normInf(A) {
5905
+ let mx = 0;
5906
+ for (const row2 of A) for (const v of row2) if (Math.abs(v) > mx) mx = Math.abs(v);
5907
+ return mx;
5908
+ }
5909
+ function norm1(A) {
5910
+ const m = A.length;
5911
+ const n = A[0].length;
5912
+ let maxColSum = 0;
5913
+ for (let j = 0; j < n; j++) {
5914
+ let colSum = 0;
5915
+ for (let i = 0; i < m; i++) colSum += Math.abs(A[i][j]);
5916
+ if (colSum > maxColSum) maxColSum = colSum;
5917
+ }
5918
+ return maxColSum;
5919
+ }
5920
+ function householder(x, degenerateBeta = -2) {
5921
+ const n = x.length;
5922
+ let sigma = 0;
5923
+ for (let i = 1; i < n; i++) {
5924
+ sigma += x[i] * x[i];
5925
+ }
5926
+ const v = [...x];
5927
+ v[0] = 1;
5928
+ if (sigma === 0 && x[0] >= 0) {
5929
+ return { v, beta: 0 };
5930
+ } else if (sigma === 0 && x[0] < 0) {
5931
+ return { v, beta: degenerateBeta };
5932
+ } else {
5933
+ const mu = Math.sqrt(x[0] * x[0] + sigma);
5934
+ if (x[0] <= 0) {
5935
+ v[0] = x[0] - mu;
5936
+ } else {
5937
+ v[0] = -sigma / (x[0] + mu);
5938
+ }
5939
+ const beta = 2 * v[0] * v[0] / (sigma + v[0] * v[0]);
5940
+ const v0 = v[0];
5941
+ for (let i = 0; i < n; i++) {
5942
+ v[i] /= v0;
5943
+ }
5944
+ return { v, beta };
5945
+ }
5946
+ }
5947
+ function applyHouseholderLeft(A, v, beta, startRow, startCol) {
5948
+ const n = A[0].length;
5949
+ const len = v.length;
5950
+ for (let j = startCol; j < n; j++) {
5951
+ let dot = 0;
5952
+ for (let i = 0; i < len; i++) {
5953
+ dot += v[i] * A[startRow + i][j];
5954
+ }
5955
+ dot *= beta;
5956
+ for (let i = 0; i < len; i++) {
5957
+ A[startRow + i][j] -= dot * v[i];
5958
+ }
5959
+ }
5960
+ }
5961
+ function applyHouseholderRight(A, v, beta, startRow, startCol) {
5962
+ const m = A.length;
5963
+ const len = v.length;
5964
+ for (let i = startRow; i < m; i++) {
5965
+ let dot = 0;
5966
+ for (let j = 0; j < len; j++) {
5967
+ dot += A[i][startCol + j] * v[j];
5968
+ }
5969
+ dot *= beta;
5970
+ for (let j = 0; j < len; j++) {
5971
+ A[i][startCol + j] -= dot * v[j];
5972
+ }
5973
+ }
5974
+ }
5975
+
5976
+ // src/operations/eig.ts
5977
+ var EIG_GEN_EPS = 2220446049250313e-31;
5978
+ function cdiv(xr, xi, yr, yi) {
5979
+ let rr;
5980
+ let d;
5981
+ if (Math.abs(yr) > Math.abs(yi)) {
5982
+ rr = yi / yr;
5983
+ d = yr + rr * yi;
5984
+ return { r: (xr + rr * xi) / d, i: (xi - rr * xr) / d };
5985
+ } else {
5986
+ rr = yr / yi;
5987
+ d = yi + rr * yr;
5988
+ return { r: (rr * xr + xi) / d, i: (rr * xi - xr) / d };
5989
+ }
5990
+ }
5991
+ function orthesGeneral(H, V, ort, nn) {
5992
+ const low = 0;
5993
+ const high = nn - 1;
5994
+ for (let m = low + 1; m <= high - 1; m++) {
5995
+ let scale2 = 0;
5996
+ for (let i = m; i <= high; i++) {
5997
+ scale2 += Math.abs(H[i * nn + (m - 1)]);
5998
+ }
5999
+ if (scale2 !== 0) {
6000
+ let h = 0;
6001
+ for (let i = high; i >= m; i--) {
6002
+ ort[i] = H[i * nn + (m - 1)] / scale2;
6003
+ h += ort[i] * ort[i];
6004
+ }
6005
+ let g = Math.sqrt(h);
6006
+ if (ort[m] > 0) g = -g;
6007
+ h = h - ort[m] * g;
6008
+ ort[m] = ort[m] - g;
6009
+ for (let j = m; j < nn; j++) {
6010
+ let f = 0;
6011
+ for (let i = high; i >= m; i--) f += ort[i] * H[i * nn + j];
6012
+ f = f / h;
6013
+ for (let i = m; i <= high; i++) H[i * nn + j] -= f * ort[i];
6014
+ }
6015
+ for (let i = 0; i <= high; i++) {
6016
+ let f = 0;
6017
+ for (let j = high; j >= m; j--) f += ort[j] * H[i * nn + j];
6018
+ f = f / h;
6019
+ for (let j = m; j <= high; j++) H[i * nn + j] -= f * ort[j];
6020
+ }
6021
+ ort[m] = scale2 * ort[m];
6022
+ H[m * nn + (m - 1)] = scale2 * g;
6023
+ }
6024
+ }
6025
+ for (let m = high - 1; m >= low + 1; m--) {
6026
+ if (H[m * nn + (m - 1)] !== 0) {
6027
+ for (let i = m + 1; i <= high; i++) ort[i] = H[i * nn + (m - 1)];
6028
+ for (let j = m; j <= high; j++) {
6029
+ let g = 0;
6030
+ for (let i = m; i <= high; i++) g += ort[i] * V[i * nn + j];
6031
+ g = g / ort[m] / H[m * nn + (m - 1)];
6032
+ for (let i = m; i <= high; i++) V[i * nn + j] += g * ort[i];
6033
+ }
6034
+ }
6035
+ }
6036
+ }
6037
+ function eigGeneral(A, computeVectors, symmetric) {
6038
+ const nn = A.length;
6039
+ const eps = EIG_GEN_EPS;
6040
+ const H = new Float64Array(nn * nn);
6041
+ for (let i = 0; i < nn; i++) {
6042
+ for (let j = 0; j < nn; j++) H[i * nn + j] = A[i][j];
6043
+ }
6044
+ const V = new Float64Array(nn * nn);
6045
+ for (let i = 0; i < nn; i++) V[i * nn + i] = 1;
6046
+ const d = new Float64Array(nn);
6047
+ const e = new Float64Array(nn);
6048
+ const ort = new Float64Array(nn);
6049
+ orthesGeneral(H, V, ort, nn);
6050
+ const low = 0;
6051
+ const high = nn - 1;
6052
+ let exshift = 0;
6053
+ let p = 0;
6054
+ let q = 0;
6055
+ let r = 0;
6056
+ let s = 0;
6057
+ let z = 0;
6058
+ let t;
6059
+ let w;
6060
+ let x;
6061
+ let y;
6062
+ let norm4 = 0;
6063
+ for (let i = 0; i < nn; i++) {
6064
+ for (let j = Math.max(i - 1, 0); j < nn; j++) {
6065
+ norm4 += Math.abs(H[i * nn + j]);
6066
+ }
6067
+ }
6068
+ let nIdx = nn - 1;
6069
+ let iter = 0;
6070
+ while (nIdx >= low) {
6071
+ let l = nIdx;
6072
+ while (l > low) {
6073
+ s = Math.abs(H[(l - 1) * nn + (l - 1)]) + Math.abs(H[l * nn + l]);
6074
+ if (s === 0) s = norm4;
6075
+ if (Math.abs(H[l * nn + (l - 1)]) < eps * s) break;
6076
+ l--;
6077
+ }
6078
+ if (l === nIdx) {
6079
+ H[nIdx * nn + nIdx] = H[nIdx * nn + nIdx] + exshift;
6080
+ d[nIdx] = H[nIdx * nn + nIdx];
6081
+ e[nIdx] = 0;
6082
+ nIdx--;
6083
+ iter = 0;
6084
+ } else if (l === nIdx - 1) {
6085
+ w = H[nIdx * nn + (nIdx - 1)] * H[(nIdx - 1) * nn + nIdx];
6086
+ p = (H[(nIdx - 1) * nn + (nIdx - 1)] - H[nIdx * nn + nIdx]) / 2;
6087
+ q = p * p + w;
6088
+ z = Math.sqrt(Math.abs(q));
6089
+ H[nIdx * nn + nIdx] = H[nIdx * nn + nIdx] + exshift;
6090
+ H[(nIdx - 1) * nn + (nIdx - 1)] = H[(nIdx - 1) * nn + (nIdx - 1)] + exshift;
6091
+ x = H[nIdx * nn + nIdx];
6092
+ if (q >= 0) {
6093
+ z = p >= 0 ? p + z : p - z;
6094
+ d[nIdx - 1] = x + z;
6095
+ d[nIdx] = d[nIdx - 1];
6096
+ if (z !== 0) d[nIdx] = x - w / z;
6097
+ e[nIdx - 1] = 0;
6098
+ e[nIdx] = 0;
6099
+ x = H[nIdx * nn + (nIdx - 1)];
6100
+ s = Math.abs(x) + Math.abs(z);
6101
+ p = x / s;
6102
+ q = z / s;
6103
+ r = Math.sqrt(p * p + q * q);
6104
+ p = p / r;
6105
+ q = q / r;
6106
+ for (let j = nIdx - 1; j < nn; j++) {
6107
+ z = H[(nIdx - 1) * nn + j];
6108
+ H[(nIdx - 1) * nn + j] = q * z + p * H[nIdx * nn + j];
6109
+ H[nIdx * nn + j] = q * H[nIdx * nn + j] - p * z;
6110
+ }
6111
+ for (let i = 0; i <= nIdx; i++) {
6112
+ z = H[i * nn + (nIdx - 1)];
6113
+ H[i * nn + (nIdx - 1)] = q * z + p * H[i * nn + nIdx];
6114
+ H[i * nn + nIdx] = q * H[i * nn + nIdx] - p * z;
6115
+ }
6116
+ for (let i = low; i <= high; i++) {
6117
+ z = V[i * nn + (nIdx - 1)];
6118
+ V[i * nn + (nIdx - 1)] = q * z + p * V[i * nn + nIdx];
6119
+ V[i * nn + nIdx] = q * V[i * nn + nIdx] - p * z;
6120
+ }
6121
+ } else {
6122
+ d[nIdx - 1] = x + p;
6123
+ d[nIdx] = x + p;
6124
+ e[nIdx - 1] = z;
6125
+ e[nIdx] = -z;
6126
+ }
6127
+ nIdx = nIdx - 2;
6128
+ iter = 0;
6129
+ } else {
6130
+ x = H[nIdx * nn + nIdx];
6131
+ y = 0;
6132
+ w = 0;
6133
+ if (l < nIdx) {
6134
+ y = H[(nIdx - 1) * nn + (nIdx - 1)];
6135
+ w = H[nIdx * nn + (nIdx - 1)] * H[(nIdx - 1) * nn + nIdx];
6136
+ }
6137
+ if (iter === 10) {
6138
+ exshift += x;
6139
+ for (let i = low; i <= nIdx; i++) H[i * nn + i] -= x;
6140
+ s = Math.abs(H[nIdx * nn + (nIdx - 1)]) + Math.abs(H[(nIdx - 1) * nn + (nIdx - 2)]);
6141
+ x = y = 0.75 * s;
6142
+ w = -0.4375 * s * s;
6143
+ }
6144
+ if (iter === 30) {
6145
+ s = (y - x) / 2;
6146
+ s = s * s + w;
6147
+ if (s > 0) {
6148
+ s = Math.sqrt(s);
6149
+ if (y < x) s = -s;
6150
+ s = x - w / ((y - x) / 2 + s);
6151
+ for (let i = low; i <= nIdx; i++) H[i * nn + i] -= s;
6152
+ exshift += s;
6153
+ x = y = w = 0.964;
6154
+ }
6155
+ }
6156
+ iter = iter + 1;
6157
+ let m = nIdx - 2;
6158
+ while (m >= l) {
6159
+ z = H[m * nn + m];
6160
+ r = x - z;
6161
+ s = y - z;
6162
+ p = (r * s - w) / H[(m + 1) * nn + m] + H[m * nn + (m + 1)];
6163
+ q = H[(m + 1) * nn + (m + 1)] - z - r - s;
6164
+ r = H[(m + 2) * nn + (m + 1)];
6165
+ s = Math.abs(p) + Math.abs(q) + Math.abs(r);
6166
+ p = p / s;
6167
+ q = q / s;
6168
+ r = r / s;
6169
+ if (m === l) break;
6170
+ if (Math.abs(H[m * nn + (m - 1)]) * (Math.abs(q) + Math.abs(r)) < eps * (Math.abs(p) * (Math.abs(H[(m - 1) * nn + (m - 1)]) + Math.abs(z) + Math.abs(H[(m + 1) * nn + (m + 1)])))) {
6171
+ break;
6172
+ }
6173
+ m--;
6174
+ }
6175
+ for (let i = m + 2; i <= nIdx; i++) {
6176
+ H[i * nn + (i - 2)] = 0;
6177
+ if (i > m + 2) H[i * nn + (i - 3)] = 0;
6178
+ }
6179
+ for (let k = m; k <= nIdx - 1; k++) {
6180
+ const notlast = k !== nIdx - 1;
6181
+ if (k !== m) {
6182
+ p = H[k * nn + (k - 1)];
6183
+ q = H[(k + 1) * nn + (k - 1)];
6184
+ r = notlast ? H[(k + 2) * nn + (k - 1)] : 0;
6185
+ x = Math.abs(p) + Math.abs(q) + Math.abs(r);
6186
+ if (x !== 0) {
6187
+ p = p / x;
6188
+ q = q / x;
6189
+ r = r / x;
6190
+ }
6191
+ }
6192
+ if (x === 0) break;
6193
+ s = Math.sqrt(p * p + q * q + r * r);
6194
+ if (p < 0) s = -s;
6195
+ if (s !== 0) {
6196
+ if (k !== m) {
6197
+ H[k * nn + (k - 1)] = -s * x;
6198
+ } else if (l !== m) {
6199
+ H[k * nn + (k - 1)] = -H[k * nn + (k - 1)];
6200
+ }
6201
+ p = p + s;
6202
+ x = p / s;
6203
+ y = q / s;
6204
+ z = r / s;
6205
+ q = q / p;
6206
+ r = r / p;
6207
+ for (let j = k; j < nn; j++) {
6208
+ p = H[k * nn + j] + q * H[(k + 1) * nn + j];
6209
+ if (notlast) {
6210
+ p = p + r * H[(k + 2) * nn + j];
6211
+ H[(k + 2) * nn + j] = H[(k + 2) * nn + j] - p * z;
6212
+ }
6213
+ H[k * nn + j] = H[k * nn + j] - p * x;
6214
+ H[(k + 1) * nn + j] = H[(k + 1) * nn + j] - p * y;
6215
+ }
6216
+ const colEnd = Math.min(nIdx, k + 3);
6217
+ for (let i = 0; i <= colEnd; i++) {
6218
+ p = x * H[i * nn + k] + y * H[i * nn + (k + 1)];
6219
+ if (notlast) {
6220
+ p = p + z * H[i * nn + (k + 2)];
6221
+ H[i * nn + (k + 2)] = H[i * nn + (k + 2)] - p * r;
6222
+ }
6223
+ H[i * nn + k] = H[i * nn + k] - p;
6224
+ H[i * nn + (k + 1)] = H[i * nn + (k + 1)] - p * q;
6225
+ }
6226
+ for (let i = low; i <= high; i++) {
6227
+ p = x * V[i * nn + k] + y * V[i * nn + (k + 1)];
6228
+ if (notlast) {
6229
+ p = p + z * V[i * nn + (k + 2)];
6230
+ V[i * nn + (k + 2)] = V[i * nn + (k + 2)] - p * r;
6231
+ }
6232
+ V[i * nn + k] = V[i * nn + k] - p;
6233
+ V[i * nn + (k + 1)] = V[i * nn + (k + 1)] - p * q;
6234
+ }
6235
+ }
6236
+ }
6237
+ }
6238
+ }
6239
+ if (norm4 !== 0) {
6240
+ for (nIdx = nn - 1; nIdx >= 0; nIdx--) {
6241
+ p = d[nIdx];
6242
+ q = e[nIdx];
6243
+ if (q === 0) {
6244
+ let l = nIdx;
6245
+ H[nIdx * nn + nIdx] = 1;
6246
+ for (let i = nIdx - 1; i >= 0; i--) {
6247
+ w = H[i * nn + i] - p;
6248
+ r = 0;
6249
+ for (let j = l; j <= nIdx; j++) r += H[i * nn + j] * H[j * nn + nIdx];
6250
+ if (e[i] < 0) {
6251
+ z = w;
6252
+ s = r;
6253
+ } else {
6254
+ l = i;
6255
+ if (e[i] === 0) {
6256
+ H[i * nn + nIdx] = w !== 0 ? -r / w : -r / (eps * norm4);
6257
+ } else {
6258
+ x = H[i * nn + (i + 1)];
6259
+ y = H[(i + 1) * nn + i];
6260
+ q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
6261
+ t = (x * s - z * r) / q;
6262
+ H[i * nn + nIdx] = t;
6263
+ if (Math.abs(x) > Math.abs(z)) {
6264
+ H[(i + 1) * nn + nIdx] = (-r - w * t) / x;
6265
+ } else {
6266
+ H[(i + 1) * nn + nIdx] = (-s - y * t) / z;
6267
+ }
6268
+ }
6269
+ t = Math.abs(H[i * nn + nIdx]);
6270
+ if (eps * t * t > 1) {
6271
+ for (let j = i; j <= nIdx; j++) H[j * nn + nIdx] = H[j * nn + nIdx] / t;
6272
+ }
6273
+ }
6274
+ }
6275
+ } else if (q < 0) {
6276
+ let l = nIdx - 1;
6277
+ if (Math.abs(H[nIdx * nn + (nIdx - 1)]) > Math.abs(H[(nIdx - 1) * nn + nIdx])) {
6278
+ H[(nIdx - 1) * nn + (nIdx - 1)] = q / H[nIdx * nn + (nIdx - 1)];
6279
+ H[(nIdx - 1) * nn + nIdx] = -(H[nIdx * nn + nIdx] - p) / H[nIdx * nn + (nIdx - 1)];
6280
+ } else {
6281
+ const cd = cdiv(0, -H[(nIdx - 1) * nn + nIdx], H[(nIdx - 1) * nn + (nIdx - 1)] - p, q);
6282
+ H[(nIdx - 1) * nn + (nIdx - 1)] = cd.r;
6283
+ H[(nIdx - 1) * nn + nIdx] = cd.i;
6284
+ }
6285
+ H[nIdx * nn + (nIdx - 1)] = 0;
6286
+ H[nIdx * nn + nIdx] = 1;
6287
+ for (let i = nIdx - 2; i >= 0; i--) {
6288
+ let ra = 0;
6289
+ let sa = 0;
6290
+ for (let j = l; j <= nIdx; j++) {
6291
+ ra += H[i * nn + j] * H[j * nn + (nIdx - 1)];
6292
+ sa += H[i * nn + j] * H[j * nn + nIdx];
6293
+ }
6294
+ w = H[i * nn + i] - p;
6295
+ if (e[i] < 0) {
6296
+ z = w;
6297
+ r = ra;
6298
+ s = sa;
6299
+ } else {
6300
+ l = i;
6301
+ if (e[i] === 0) {
6302
+ const cd = cdiv(-ra, -sa, w, q);
6303
+ H[i * nn + (nIdx - 1)] = cd.r;
6304
+ H[i * nn + nIdx] = cd.i;
6305
+ } else {
6306
+ x = H[i * nn + (i + 1)];
6307
+ y = H[(i + 1) * nn + i];
6308
+ let vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
6309
+ const vi = (d[i] - p) * 2 * q;
6310
+ if (vr === 0 && vi === 0) {
6311
+ vr = eps * norm4 * (Math.abs(w) + Math.abs(q) + Math.abs(x) + Math.abs(y) + Math.abs(z));
6312
+ }
6313
+ const cd = cdiv(x * r - z * ra + q * sa, x * s - z * sa - q * ra, vr, vi);
6314
+ H[i * nn + (nIdx - 1)] = cd.r;
6315
+ H[i * nn + nIdx] = cd.i;
6316
+ if (Math.abs(x) > Math.abs(z) + Math.abs(q)) {
6317
+ H[(i + 1) * nn + (nIdx - 1)] = (-ra - w * H[i * nn + (nIdx - 1)] + q * H[i * nn + nIdx]) / x;
6318
+ H[(i + 1) * nn + nIdx] = (-sa - w * H[i * nn + nIdx] - q * H[i * nn + (nIdx - 1)]) / x;
6319
+ } else {
6320
+ const cd2 = cdiv(-r - y * H[i * nn + (nIdx - 1)], -s - y * H[i * nn + nIdx], z, q);
6321
+ H[(i + 1) * nn + (nIdx - 1)] = cd2.r;
6322
+ H[(i + 1) * nn + nIdx] = cd2.i;
6323
+ }
6324
+ }
6325
+ t = Math.max(Math.abs(H[i * nn + (nIdx - 1)]), Math.abs(H[i * nn + nIdx]));
6326
+ if (eps * t * t > 1) {
6327
+ for (let j = i; j <= nIdx; j++) {
6328
+ H[j * nn + (nIdx - 1)] = H[j * nn + (nIdx - 1)] / t;
6329
+ H[j * nn + nIdx] = H[j * nn + nIdx] / t;
6330
+ }
6331
+ }
6332
+ }
6333
+ }
6334
+ }
6335
+ }
6336
+ for (let j = nn - 1; j >= low; j--) {
6337
+ for (let i = low; i <= high; i++) {
6338
+ z = 0;
6339
+ const kEnd = Math.min(j, high);
6340
+ for (let k = low; k <= kEnd; k++) z += V[i * nn + k] * H[k * nn + j];
6341
+ V[i * nn + j] = z;
6342
+ }
6343
+ }
6344
+ }
6345
+ const values = [];
6346
+ for (let j = 0; j < nn; j++) values.push({ re: d[j], im: e[j] });
6347
+ let vectors;
6348
+ if (computeVectors) {
6349
+ vectors = [];
6350
+ for (let j = 0; j < nn; j++) {
6351
+ const vec = new Array(nn).fill(0);
6352
+ if (e[j] === 0) {
6353
+ let colNorm = 0;
6354
+ for (let i = 0; i < nn; i++) colNorm += V[i * nn + j] * V[i * nn + j];
6355
+ colNorm = Math.sqrt(colNorm);
6356
+ if (colNorm > 1e-300) {
6357
+ for (let i = 0; i < nn; i++) vec[i] = V[i * nn + j] / colNorm;
6358
+ } else {
6359
+ for (let i = 0; i < nn; i++) vec[i] = V[i * nn + j];
6360
+ }
6361
+ }
6362
+ vectors.push(vec);
6363
+ }
6364
+ } else {
6365
+ vectors = eye(nn);
6366
+ }
6367
+ return { values, vectors, isSymmetric: symmetric };
6368
+ }
6369
+ function eig(matrix2, options = {}) {
6370
+ const { computeVectors = true } = options;
6371
+ let A;
6372
+ if (matrix2 instanceof Float64Array) {
6373
+ const n2 = Math.sqrt(matrix2.length);
6374
+ if (n2 !== Math.floor(n2)) {
6375
+ throw new Error("Float64Array length must be a perfect square");
6376
+ }
6377
+ A = Array.from({ length: n2 }, (_, i) => Array.from({ length: n2 }, (_2, j) => matrix2[i * n2 + j]));
6378
+ } else {
6379
+ A = matrix2;
6380
+ }
6381
+ const n = A.length;
6382
+ if (n === 0) {
6383
+ return { values: [], vectors: [], isSymmetric: true };
6384
+ }
6385
+ for (let i = 0; i < n; i++) {
6386
+ if (A[i].length !== n) {
6387
+ throw new Error("Matrix must be square");
6388
+ }
6389
+ }
6390
+ const symmetric = isSymmetric(A);
6391
+ if (n === 1) {
6392
+ return {
6393
+ values: [{ re: A[0][0], im: 0 }],
6394
+ vectors: [[1]],
6395
+ isSymmetric: symmetric
6396
+ };
6397
+ }
6398
+ return eigGeneral(A, computeVectors, symmetric);
6399
+ }
6400
+ function eigvals(matrix2, options) {
6401
+ return eig(matrix2, { ...options, computeVectors: false }).values;
6402
+ }
6403
+ function powerIteration(matrix2, options = {}) {
6404
+ const { maxIterations = 1e3, tolerance = 1e-12 } = options;
6405
+ const n = matrix2.length;
6406
+ let v = Array.from({ length: n }, () => Math.random() - 0.5);
6407
+ let norm4 = Math.sqrt(v.reduce((sum3, x) => sum3 + x * x, 0));
6408
+ v = v.map((x) => x / norm4);
6409
+ let eigenvalue = 0;
6410
+ let prevEigenvalue = 0;
6411
+ for (let iter = 0; iter < maxIterations; iter++) {
6412
+ const w = new Array(n).fill(0);
6413
+ for (let i = 0; i < n; i++) {
6414
+ for (let j = 0; j < n; j++) {
6415
+ w[i] += matrix2[i][j] * v[j];
6416
+ }
6417
+ }
6418
+ eigenvalue = v.reduce((sum3, vi, i) => sum3 + vi * w[i], 0);
6419
+ norm4 = Math.sqrt(w.reduce((sum3, x) => sum3 + x * x, 0));
6420
+ v = w.map((x) => x / norm4);
6421
+ if (Math.abs(eigenvalue - prevEigenvalue) < tolerance * Math.abs(eigenvalue)) {
6422
+ break;
6423
+ }
6424
+ prevEigenvalue = eigenvalue;
6425
+ }
6426
+ return { value: eigenvalue, vector: v };
6427
+ }
6428
+
5975
6429
  // src/operations/svd.ts
5976
6430
  var DEFAULT_MAX_ITERATIONS = 1e3;
5977
6431
  var DEFAULT_TOLERANCE = 1e-12;
@@ -6090,6 +6544,84 @@ function handleZero(d, e, _U, V, zeroIdx, isDiagonal, _tolerance) {
6090
6544
  }
6091
6545
  }
6092
6546
  }
6547
+ function jacobiSVD(A) {
6548
+ const m = A.length;
6549
+ const n = A[0].length;
6550
+ const W = A.map((row2) => row2.slice());
6551
+ const V = eye(n);
6552
+ const EPS = 1e-15;
6553
+ const MAX_SWEEPS = 60;
6554
+ for (let sweep = 0; sweep < MAX_SWEEPS; sweep++) {
6555
+ let rotated = false;
6556
+ for (let p = 0; p < n - 1; p++) {
6557
+ for (let q = p + 1; q < n; q++) {
6558
+ let alpha = 0;
6559
+ let beta = 0;
6560
+ let gamma = 0;
6561
+ for (let i = 0; i < m; i++) {
6562
+ alpha += W[i][p] * W[i][p];
6563
+ gamma += W[i][q] * W[i][q];
6564
+ beta += W[i][p] * W[i][q];
6565
+ }
6566
+ if (Math.abs(beta) <= EPS * Math.sqrt(alpha * gamma) || alpha === 0 && gamma === 0) {
6567
+ continue;
6568
+ }
6569
+ rotated = true;
6570
+ const zeta = (gamma - alpha) / (2 * beta);
6571
+ const sign = zeta >= 0 ? 1 : -1;
6572
+ const t = sign / (Math.abs(zeta) + Math.sqrt(1 + zeta * zeta));
6573
+ const c = 1 / Math.sqrt(1 + t * t);
6574
+ const s = c * t;
6575
+ for (let i = 0; i < m; i++) {
6576
+ const wip = W[i][p];
6577
+ const wiq = W[i][q];
6578
+ W[i][p] = c * wip - s * wiq;
6579
+ W[i][q] = s * wip + c * wiq;
6580
+ }
6581
+ for (let i = 0; i < n; i++) {
6582
+ const vip = V[i][p];
6583
+ const viq = V[i][q];
6584
+ V[i][p] = c * vip - s * viq;
6585
+ V[i][q] = s * vip + c * viq;
6586
+ }
6587
+ }
6588
+ }
6589
+ if (!rotated) break;
6590
+ }
6591
+ const d = new Array(n).fill(0);
6592
+ const U = Array.from({ length: m }, () => new Array(n).fill(0));
6593
+ for (let j = 0; j < n; j++) {
6594
+ let norm4 = 0;
6595
+ for (let i = 0; i < m; i++) norm4 += W[i][j] * W[i][j];
6596
+ norm4 = Math.sqrt(norm4);
6597
+ d[j] = norm4;
6598
+ if (norm4 > 1e-300) {
6599
+ for (let i = 0; i < m; i++) U[i][j] = W[i][j] / norm4;
6600
+ }
6601
+ }
6602
+ for (let j = 0; j < n; j++) {
6603
+ if (d[j] > 1e-300) continue;
6604
+ const col = new Array(m).fill(0);
6605
+ for (let seed = 0; seed < m; seed++) {
6606
+ col.fill(0);
6607
+ col[seed] = 1;
6608
+ for (let c = 0; c < n; c++) {
6609
+ if (c === j) continue;
6610
+ let dot = 0;
6611
+ for (let i = 0; i < m; i++) dot += col[i] * U[i][c];
6612
+ for (let i = 0; i < m; i++) col[i] -= dot * U[i][c];
6613
+ }
6614
+ let nrm = 0;
6615
+ for (let i = 0; i < m; i++) nrm += col[i] * col[i];
6616
+ nrm = Math.sqrt(nrm);
6617
+ if (nrm > 1e-8) {
6618
+ for (let i = 0; i < m; i++) U[i][j] = col[i] / nrm;
6619
+ break;
6620
+ }
6621
+ }
6622
+ }
6623
+ return { d, U, V };
6624
+ }
6093
6625
  function svd(matrix2, options = {}) {
6094
6626
  const {
6095
6627
  maxIterations = DEFAULT_MAX_ITERATIONS,
@@ -6161,19 +6693,29 @@ function svd(matrix2, options = {}) {
6161
6693
  }
6162
6694
  svdStep(d, e, U, V, start, end);
6163
6695
  }
6164
- for (let i = 0; i < d.length; i++) {
6165
- if (d[i] < 0) {
6166
- d[i] = -d[i];
6167
- for (let j = 0; j < V.length; j++) {
6168
- V[j][i] = -V[j][i];
6169
- }
6170
- }
6171
- }
6172
- const indices = Array.from({ length: d.length }, (_, i) => i);
6173
- indices.sort((a, b) => d[b] - d[a]);
6174
- const sortedS = indices.map((i) => d[i]);
6175
- const sortedU = U.map((row2) => indices.map((i) => row2[i]));
6176
- const sortedV = V.map((row2) => indices.map((i) => row2[i]));
6696
+ let dFinal = d;
6697
+ let uFinal = U;
6698
+ let vFinal = V;
6699
+ const maxAbsD = d.reduce((mx, x) => Math.max(mx, Math.abs(x)), 0);
6700
+ if (maxAbsD > 0 && d.some((x) => Math.abs(x) <= rankTolerance * maxAbsD)) {
6701
+ const jac = jacobiSVD(A);
6702
+ dFinal = jac.d;
6703
+ uFinal = jac.U;
6704
+ vFinal = jac.V;
6705
+ }
6706
+ for (let i = 0; i < dFinal.length; i++) {
6707
+ if (dFinal[i] < 0) {
6708
+ dFinal[i] = -dFinal[i];
6709
+ for (let j = 0; j < vFinal.length; j++) {
6710
+ vFinal[j][i] = -vFinal[j][i];
6711
+ }
6712
+ }
6713
+ }
6714
+ const indices = Array.from({ length: dFinal.length }, (_, i) => i);
6715
+ indices.sort((a, b) => dFinal[b] - dFinal[a]);
6716
+ const sortedS = indices.map((i) => dFinal[i]);
6717
+ const sortedU = uFinal.map((row2) => indices.map((i) => row2[i]));
6718
+ const sortedV = vFinal.map((row2) => indices.map((i) => row2[i]));
6177
6719
  const maxS = sortedS[0] || 0;
6178
6720
  let rank = 0;
6179
6721
  for (const s of sortedS) {
@@ -6263,17 +6805,6 @@ function normFro(matrix2) {
6263
6805
  }
6264
6806
 
6265
6807
  // src/operations/eig-wasm.ts
6266
- var WASM_EIG_THRESHOLD = 8;
6267
- function flattenMatrix(matrix2) {
6268
- const n = matrix2.length;
6269
- const flat2 = new Float64Array(n * n);
6270
- for (let i = 0; i < n; i++) {
6271
- for (let j = 0; j < n; j++) {
6272
- flat2[i * n + j] = matrix2[i][j];
6273
- }
6274
- }
6275
- return flat2;
6276
- }
6277
6808
  async function eigWasm(matrix2, options) {
6278
6809
  const n = matrix2.length;
6279
6810
  if (n === 0) {
@@ -6284,113 +6815,14 @@ async function eigWasm(matrix2, options) {
6284
6815
  throw new Error("Matrix must be square");
6285
6816
  }
6286
6817
  }
6287
- let module = wasmLoader.getModule();
6288
- if (!module) {
6289
- try {
6290
- module = await wasmLoader.load();
6291
- } catch {
6292
- module = null;
6293
- }
6294
- }
6295
- const symmetric = isSymmetric(matrix2);
6296
- const useSymWasm = !!module && n >= WASM_EIG_THRESHOLD && symmetric && typeof module.matrix_eig_symmetric === "function";
6297
- const useGenWasm = !!module && n >= WASM_EIG_THRESHOLD && !symmetric && typeof module.matrix_eig_general === "function";
6298
- if (!useSymWasm && !useGenWasm) {
6299
- return eig(matrix2, options);
6300
- }
6301
- const computeVectors = options?.computeVectors ?? true;
6302
- const identityVectors = () => Array.from({ length: n }, (_, i) => {
6303
- const row2 = new Array(n).fill(0);
6304
- row2[i] = 1;
6305
- return row2;
6306
- });
6307
- const flatMatrix = flattenMatrix(matrix2);
6308
- const matrixAlloc = wasmLoader.allocateFloat64Array(Array.from(flatMatrix));
6309
- try {
6310
- if (useSymWasm) {
6311
- const packedPtr2 = module.matrix_eig_symmetric(matrixAlloc.ptr, n);
6312
- const packed2 = wasmLoader.readReturnedFloat64Array(packedPtr2);
6313
- if (packed2.length < n + n * n) {
6314
- return eig(matrix2, options);
6315
- }
6316
- const values2 = [];
6317
- for (let j = 0; j < n; j++) {
6318
- values2.push({ re: packed2[j], im: 0 });
6319
- }
6320
- let vectors2;
6321
- if (computeVectors) {
6322
- vectors2 = [];
6323
- for (let j = 0; j < n; j++) {
6324
- const vec = [];
6325
- for (let i = 0; i < n; i++) {
6326
- vec.push(packed2[n + i * n + j]);
6327
- }
6328
- vectors2.push(vec);
6329
- }
6330
- } else {
6331
- vectors2 = identityVectors();
6332
- }
6333
- return { values: values2, vectors: vectors2, isSymmetric: true };
6334
- }
6335
- const packedPtr = module.matrix_eig_general(matrixAlloc.ptr, n);
6336
- const packed = wasmLoader.readReturnedFloat64Array(packedPtr);
6337
- if (packed.length < 2 * n + n * n) {
6338
- return eig(matrix2, options);
6339
- }
6340
- const values = [];
6341
- for (let j = 0; j < n; j++) {
6342
- values.push({ re: packed[j], im: packed[n + j] });
6343
- }
6344
- let vectors;
6345
- if (computeVectors) {
6346
- vectors = [];
6347
- for (let j = 0; j < n; j++) {
6348
- const vec = [];
6349
- for (let i = 0; i < n; i++) {
6350
- vec.push(packed[2 * n + i * n + j]);
6351
- }
6352
- vectors.push(vec);
6353
- }
6354
- } else {
6355
- vectors = identityVectors();
6356
- }
6357
- return { values, vectors, isSymmetric: false };
6358
- } catch {
6359
- return eig(matrix2, options);
6360
- } finally {
6361
- wasmLoader.free(matrixAlloc.ptr);
6362
- }
6818
+ return eig(matrix2, options);
6363
6819
  }
6364
6820
  async function eigvalsWasm(matrix2, options) {
6365
- const result = await eigWasm(matrix2, { ...options, computeVectors: false });
6366
- return result.values;
6821
+ return eigvals(matrix2, options);
6367
6822
  }
6368
6823
  async function spectralRadiusWasm(matrix2, options) {
6369
- const n = matrix2.length;
6370
- let module = wasmLoader.getModule();
6371
- if (!module) {
6372
- try {
6373
- module = await wasmLoader.load();
6374
- } catch {
6375
- module = null;
6376
- }
6377
- }
6378
- if (!module || n < WASM_EIG_THRESHOLD || typeof module.matrix_spectral_radius !== "function") {
6379
- const { powerIteration: powerIteration2 } = await import("./eig-PIFFHFJF.js");
6380
- const result = powerIteration2(matrix2, options);
6381
- return Math.abs(result.value);
6382
- }
6383
- const flatMatrix = flattenMatrix(matrix2);
6384
- const matrixAlloc = wasmLoader.allocateFloat64Array(Array.from(flatMatrix));
6385
- try {
6386
- return module.matrix_spectral_radius(matrixAlloc.ptr, n);
6387
- } catch {
6388
- const { powerIteration: powerIteration2 } = await import("./eig-PIFFHFJF.js");
6389
- const result = powerIteration2(matrix2, options);
6390
- return Math.abs(result.value);
6391
- } finally {
6392
- wasmLoader.free(matrixAlloc.ptr);
6393
- }
6824
+ const result = powerIteration(matrix2, options);
6825
+ return Math.abs(result.value);
6394
6826
  }
6395
6827
 
6396
6828
  // src/operations/svd-wasm.ts
@@ -6418,46 +6850,7 @@ async function svdWasm(matrix2, options) {
6418
6850
  }
6419
6851
  const k = Math.min(m, n);
6420
6852
  const rankTolerance = options?.rankTolerance ?? 1e-10;
6421
- let module = wasmLoader.getModule();
6422
- if (!module) {
6423
- try {
6424
- module = await wasmLoader.load();
6425
- } catch {
6426
- module = null;
6427
- }
6428
- }
6429
- if (!module || typeof module.matrix_svd !== "function") {
6430
- return toThin(svd(matrix2, options), k, rankTolerance);
6431
- }
6432
- const flat2 = new Float64Array(m * n);
6433
- for (let i = 0; i < m; i++) {
6434
- for (let j = 0; j < n; j++) flat2[i * n + j] = matrix2[i][j];
6435
- }
6436
- const aAlloc = wasmLoader.allocateFloat64Array(flat2);
6437
- try {
6438
- const packedPtr = module.matrix_svd(aAlloc.ptr, m, n);
6439
- const packed = wasmLoader.readReturnedFloat64Array(packedPtr);
6440
- if (packed.length < m * k + k + n * k) {
6441
- return toThin(svd(matrix2, options), k, rankTolerance);
6442
- }
6443
- const uFlat = packed.subarray(0, m * k);
6444
- const sFlat = packed.subarray(m * k, m * k + k);
6445
- const vFlat = packed.subarray(m * k + k, m * k + k + n * k);
6446
- const U = [];
6447
- for (let i = 0; i < m; i++) {
6448
- U.push(Array.from(uFlat.subarray(i * k, i * k + k)));
6449
- }
6450
- const V = [];
6451
- for (let i = 0; i < n; i++) {
6452
- V.push(Array.from(vFlat.subarray(i * k, i * k + k)));
6453
- }
6454
- const S = Array.from(sFlat);
6455
- return { U, S, V, rank: estimateRank(S, rankTolerance) };
6456
- } catch {
6457
- return toThin(svd(matrix2, options), k, rankTolerance);
6458
- } finally {
6459
- wasmLoader.free(aAlloc.ptr);
6460
- }
6853
+ return toThin(svd(matrix2, options), k, rankTolerance);
6461
6854
  }
6462
6855
 
6463
6856
  // src/operations/pinv.ts
@@ -6806,8 +7199,7 @@ function hessenbergReduce(A) {
6806
7199
  applyHouseholderRight(Q, v, beta, 0, k + 1);
6807
7200
  }
6808
7201
  }
6809
- for (let i = 0; i < n; i++)
6810
- for (let j = 0; j < i - 1; j++) H[i][j] = 0;
7202
+ for (let i = 0; i < n; i++) for (let j = 0; j < i - 1; j++) H[i][j] = 0;
6811
7203
  return { H, Q };
6812
7204
  }
6813
7205
  function givensParams(a, b) {
@@ -6912,6 +7304,57 @@ function qrStepDouble(H, Q, start, end) {
6912
7304
  applyGivensRight(H, gc, gs, end - 1, end, 0);
6913
7305
  applyGivensRight(Q, gc, gs, end - 1, end, 0);
6914
7306
  }
7307
+ function qrStepSingleShift(H, Q, start, end, shift) {
7308
+ let x = H[start][start] - shift;
7309
+ let y = H[start + 1][start];
7310
+ for (let k = start; k < end; k++) {
7311
+ const { c: gc, s: gs } = givensParams(x, y);
7312
+ applyGivensLeft(H, gc, gs, k, k + 1, Math.max(0, k - 1));
7313
+ applyGivensRight(H, gc, gs, k, k + 1, 0);
7314
+ applyGivensRight(Q, gc, gs, k, k + 1, 0);
7315
+ if (k < end - 1) {
7316
+ x = H[k + 1][k];
7317
+ y = H[k + 2][k];
7318
+ }
7319
+ }
7320
+ }
7321
+ function exceptionalShift(H, start, end) {
7322
+ const sub1 = Math.abs(H[end][end - 1]);
7323
+ const sub2 = end - 1 > start ? Math.abs(H[end - 1][end - 2]) : 0;
7324
+ return H[end][end] + 0.75 * (sub1 + sub2);
7325
+ }
7326
+ function standardize2x2Block(H, Q, p) {
7327
+ const q = p + 1;
7328
+ const a = H[p][p];
7329
+ const b = H[p][q];
7330
+ const c = H[q][p];
7331
+ const d = H[q][q];
7332
+ if (c === 0) return;
7333
+ const half = (a - d) / 2;
7334
+ const disc = half * half + b * c;
7335
+ if (disc < 0) return;
7336
+ const z = Math.sqrt(disc);
7337
+ const lambda = (a + d) / 2 + (half >= 0 ? z : -z);
7338
+ const r0 = Math.hypot(a - lambda, b);
7339
+ const r1 = Math.hypot(c, d - lambda);
7340
+ let u0;
7341
+ let u1;
7342
+ if (r0 >= r1) {
7343
+ u0 = b;
7344
+ u1 = lambda - a;
7345
+ } else {
7346
+ u0 = lambda - d;
7347
+ u1 = c;
7348
+ }
7349
+ const norm4 = Math.hypot(u0, u1);
7350
+ if (norm4 === 0) return;
7351
+ const cs = u0 / norm4;
7352
+ const sn = -u1 / norm4;
7353
+ applyGivensLeft(H, cs, sn, p, q, 0);
7354
+ applyGivensRight(H, cs, sn, p, q, 0);
7355
+ applyGivensRight(Q, cs, sn, p, q, 0);
7356
+ H[q][p] = 0;
7357
+ }
6915
7358
  function schurRaw(A, maxIterations, tolerance) {
6916
7359
  const n = A.length;
6917
7360
  if (n === 1) {
@@ -6920,7 +7363,10 @@ function schurRaw(A, maxIterations, tolerance) {
6920
7363
  const { H, Q } = hessenbergReduce(A);
6921
7364
  let end = n - 1;
6922
7365
  let iter = 0;
7366
+ let iterSinceDeflation = 0;
7367
+ const EXCEPTIONAL_EVERY = 10;
6923
7368
  while (end > 0 && iter < maxIterations) {
7369
+ const endBefore = end;
6924
7370
  let start = end;
6925
7371
  while (start > 0) {
6926
7372
  const scale2 = Math.abs(H[start - 1][start - 1]) + Math.abs(H[start][start]);
@@ -6933,14 +7379,16 @@ function schurRaw(A, maxIterations, tolerance) {
6933
7379
  if (start === end) {
6934
7380
  end--;
6935
7381
  } else if (start === end - 1) {
7382
+ standardize2x2Block(H, Q, start);
6936
7383
  end -= 2;
7384
+ } else if (iterSinceDeflation > 0 && iterSinceDeflation % EXCEPTIONAL_EVERY === 0) {
7385
+ qrStepSingleShift(H, Q, start, end, exceptionalShift(H, start, end));
7386
+ } else if (end - start >= 2) {
7387
+ qrStepDouble(H, Q, start, end);
6937
7388
  } else {
6938
- if (end - start >= 2) {
6939
- qrStepDouble(H, Q, start, end);
6940
- } else {
6941
- qrStepSingle(H, Q, start, end);
6942
- }
7389
+ qrStepSingle(H, Q, start, end);
6943
7390
  }
7391
+ iterSinceDeflation = end < endBefore ? 0 : iterSinceDeflation + 1;
6944
7392
  iter++;
6945
7393
  }
6946
7394
  return { H, Q };
@@ -7155,7 +7603,7 @@ function logmSchur(A, tol) {
7155
7603
  const scale2 = Math.pow(2, numSqrt);
7156
7604
  logT = logT.map((row2) => row2.map((v) => v * scale2));
7157
7605
  }
7158
- const Qt = transpose(Q);
7606
+ const Qt = transpose2(Q);
7159
7607
  return matMul(matMul(Q, logT), Qt);
7160
7608
  }
7161
7609
  function validateEigenvalues(A) {
@@ -7189,7 +7637,7 @@ function logmEig(A) {
7189
7637
  }
7190
7638
  }
7191
7639
  const V = vectors;
7192
- const Q = transpose(V);
7640
+ const Q = transpose2(V);
7193
7641
  const Qinv = matInv(Q);
7194
7642
  if (Qinv === null) {
7195
7643
  throw new Error(
@@ -7314,9 +7762,9 @@ function sqrtmSymmetric(A) {
7314
7762
  }
7315
7763
  const Ynewton = sqrtmNewton(Asym);
7316
7764
  if (Ynewton !== null) return Ynewton;
7317
- const Qraw = transpose(vectors);
7765
+ const Qraw = transpose2(vectors);
7318
7766
  const Q = gramSchmidt(Qraw);
7319
- const Qt = transpose(Q);
7767
+ const Qt = transpose2(Q);
7320
7768
  const Dsqrt = eye(n);
7321
7769
  for (let i = 0; i < n; i++) Dsqrt[i][i] = Math.sqrt(Math.max(values[i].re, 0));
7322
7770
  return matMul(matMul(Q, Dsqrt), Qt);
@@ -7362,7 +7810,7 @@ function sqrtmGeneral(A) {
7362
7810
  const Ynewton = sqrtmNewton(A);
7363
7811
  if (Ynewton !== null) return Ynewton;
7364
7812
  const V = vectors;
7365
- const Q = transpose(V);
7813
+ const Q = transpose2(V);
7366
7814
  const Qinv = matInv2(Q);
7367
7815
  if (Qinv === null) {
7368
7816
  throw new Error(
@@ -7490,7 +7938,7 @@ function sqrtmSchur(A) {
7490
7938
  const { H: T, Q } = schurInternal(A);
7491
7939
  const U = sqrtmQuasiTriangular(T);
7492
7940
  if (U === null) return null;
7493
- const Qt = transpose(Q);
7941
+ const Qt = transpose2(Q);
7494
7942
  return matMul(matMul(Q, U), Qt);
7495
7943
  }
7496
7944
  function matrixSqrtm(A, opts) {