@danielsimonjr/mathts-matrix 0.4.6 → 0.6.0
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.d.ts +136 -2
- package/dist/index.js +273 -6
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1986,8 +1986,24 @@ interface EigResult {
|
|
|
1986
1986
|
re: number;
|
|
1987
1987
|
im: number;
|
|
1988
1988
|
}>;
|
|
1989
|
-
/**
|
|
1989
|
+
/**
|
|
1990
|
+
* Eigenvectors as columns (each column is an eigenvector). For a real
|
|
1991
|
+
* eigenvalue this is the full (real) eigenvector, unit-normalised. For a
|
|
1992
|
+
* complex-conjugate eigenvalue pair this holds the REAL PART of the
|
|
1993
|
+
* corresponding complex eigenvector — see {@link vectorsIm} for the
|
|
1994
|
+
* imaginary part.
|
|
1995
|
+
*/
|
|
1990
1996
|
vectors: number[][];
|
|
1997
|
+
/**
|
|
1998
|
+
* Imaginary parts of the eigenvector columns (same shape as {@link vectors}).
|
|
1999
|
+
* All-zero for real eigenvalues. For a complex-conjugate eigenvalue pair at
|
|
2000
|
+
* indices `j`/`j+1`, the full complex eigenvectors are
|
|
2001
|
+
* `vectors[j] + i*vectorsIm[j]` (for `values[j]`) and
|
|
2002
|
+
* `vectors[j+1] - i*vectorsIm[j] === vectors[j+1] + i*vectorsIm[j+1]` (for
|
|
2003
|
+
* the conjugate `values[j+1]`), each unit-normalised by the complex 2-norm
|
|
2004
|
+
* `sqrt(sum(re_i^2 + im_i^2))`.
|
|
2005
|
+
*/
|
|
2006
|
+
vectorsIm: number[][];
|
|
1991
2007
|
/** Whether the matrix was symmetric */
|
|
1992
2008
|
isSymmetric: boolean;
|
|
1993
2009
|
}
|
|
@@ -2507,6 +2523,124 @@ interface SchurOptions {
|
|
|
2507
2523
|
*/
|
|
2508
2524
|
declare function matrixSchur(A: DenseMatrix, opts?: SchurOptions): SchurResult;
|
|
2509
2525
|
|
|
2526
|
+
/**
|
|
2527
|
+
* Rank-Revealing Pivoted QR Decomposition (Businger-Golub column pivoting)
|
|
2528
|
+
*
|
|
2529
|
+
* Computes `A[:, P] = Q · R` via Householder reflections, choosing at each
|
|
2530
|
+
* step the remaining column of largest norm as the next pivot. This is the
|
|
2531
|
+
* classical column-pivoted QR (LAPACK `dgeqp3`'s algorithm, simplified —
|
|
2532
|
+
* exact remaining-column-norm recomputation rather than the cheaper
|
|
2533
|
+
* downdating formula, since these matrices are small): it guarantees
|
|
2534
|
+
* `|R[0,0]| ≥ |R[1,1]| ≥ … ≥ |R[k-1,k-1]|`, which makes `R`'s diagonal a
|
|
2535
|
+
* reliable numerical-rank indicator — unlike the plain (unpivoted)
|
|
2536
|
+
* Gram-Schmidt `qr()` in this directory, whose diagonal can be small for an
|
|
2537
|
+
* early column purely by column order, not by rank deficiency.
|
|
2538
|
+
*
|
|
2539
|
+
* Reuses the Householder helpers in `./common.js` (already exercised by
|
|
2540
|
+
* `svd.ts`/`schur.ts`) rather than re-deriving reflection algebra here.
|
|
2541
|
+
*/
|
|
2542
|
+
|
|
2543
|
+
interface QRPivotedResult {
|
|
2544
|
+
/** Orthonormal Q factor (m × k, k = min(m, n)). */
|
|
2545
|
+
Q: DenseMatrix;
|
|
2546
|
+
/** Upper-triangular R factor (k × n) with |diag(R)| non-increasing. */
|
|
2547
|
+
R: DenseMatrix;
|
|
2548
|
+
/** Column permutation: `P[j]` is the original column index now at position `j`, so `A[:, P] = Q · R`. */
|
|
2549
|
+
P: number[];
|
|
2550
|
+
/** Numerical rank: count of `i` with `|R[i,i]| > tolerance · |R[0,0]|`. */
|
|
2551
|
+
rank: number;
|
|
2552
|
+
}
|
|
2553
|
+
interface QRPivotedOptions {
|
|
2554
|
+
/** Relative rank tolerance (default `1e-10`). */
|
|
2555
|
+
tolerance?: number;
|
|
2556
|
+
}
|
|
2557
|
+
/**
|
|
2558
|
+
* Compute the column-pivoted rank-revealing QR decomposition of `A`.
|
|
2559
|
+
*
|
|
2560
|
+
* @param A - Input matrix (m × n).
|
|
2561
|
+
* @param opts - Optional rank tolerance.
|
|
2562
|
+
*/
|
|
2563
|
+
declare function qrPivoted(A: DenseMatrix, opts?: QRPivotedOptions): QRPivotedResult;
|
|
2564
|
+
|
|
2565
|
+
/**
|
|
2566
|
+
* QR-family decompositions: LQ, RQ, QL
|
|
2567
|
+
*
|
|
2568
|
+
* Each is derived from the existing Gram-Schmidt `qr()` primitive in this
|
|
2569
|
+
* directory via the standard flip/transpose reductions (Golub & Van Loan,
|
|
2570
|
+
* *Matrix Computations*, §5.2):
|
|
2571
|
+
*
|
|
2572
|
+
* - **LQ** (`A = L·Q`, L lower-triangular): `qr(Aᵀ)` transposed — no flips
|
|
2573
|
+
* needed. If `Aᵀ = Q₁·R₁` then `A = R₁ᵀ·Q₁ᵀ`, so `L = R₁ᵀ`, `Q = Q₁ᵀ`.
|
|
2574
|
+
* - **RQ** (`A = R·Q`, R upper-triangular): reverse `A`'s row order,
|
|
2575
|
+
* transpose, run `qr()`, then un-flip the resulting factors.
|
|
2576
|
+
* - **QL** (`A = Q·L`, L lower-triangular): reverse `A`'s column order,
|
|
2577
|
+
* run `qr()`, then un-flip the resulting factors.
|
|
2578
|
+
*
|
|
2579
|
+
* All three share `qr()`'s reduced-QR convention: for an m×n input the thin
|
|
2580
|
+
* factor pairing is (m×k, k×n) with k = min(m, n).
|
|
2581
|
+
*/
|
|
2582
|
+
|
|
2583
|
+
interface LQResult {
|
|
2584
|
+
/** Lower-triangular (trapezoidal) factor. m × k, k = min(m, n). */
|
|
2585
|
+
L: DenseMatrix;
|
|
2586
|
+
/** Orthonormal-row factor (Q · Qᵀ = I). k × n. */
|
|
2587
|
+
Q: DenseMatrix;
|
|
2588
|
+
}
|
|
2589
|
+
interface RQResult {
|
|
2590
|
+
/** Upper-triangular (trapezoidal) factor. m × k, k = min(m, n). */
|
|
2591
|
+
R: DenseMatrix;
|
|
2592
|
+
/** Orthonormal-row factor (Q · Qᵀ = I). k × n. */
|
|
2593
|
+
Q: DenseMatrix;
|
|
2594
|
+
}
|
|
2595
|
+
interface QLResult {
|
|
2596
|
+
/** Orthonormal-column factor (Qᵀ · Q = I). m × k, k = min(m, n). */
|
|
2597
|
+
Q: DenseMatrix;
|
|
2598
|
+
/** Lower-triangular (trapezoidal) factor. k × n. */
|
|
2599
|
+
L: DenseMatrix;
|
|
2600
|
+
}
|
|
2601
|
+
/**
|
|
2602
|
+
* LQ decomposition: `A = L · Q` with `L` lower-triangular and `Q` having
|
|
2603
|
+
* orthonormal rows (`Q · Qᵀ = I`).
|
|
2604
|
+
*/
|
|
2605
|
+
declare function lq(A: DenseMatrix): LQResult;
|
|
2606
|
+
/**
|
|
2607
|
+
* RQ decomposition: `A = R · Q` with `R` upper-triangular and `Q` having
|
|
2608
|
+
* orthonormal rows (`Q · Qᵀ = I`).
|
|
2609
|
+
*/
|
|
2610
|
+
declare function rq(A: DenseMatrix): RQResult;
|
|
2611
|
+
/**
|
|
2612
|
+
* QL decomposition: `A = Q · L` with `Q` having orthonormal columns
|
|
2613
|
+
* (`Qᵀ · Q = I`) and `L` lower-triangular.
|
|
2614
|
+
*/
|
|
2615
|
+
declare function ql(A: DenseMatrix): QLResult;
|
|
2616
|
+
|
|
2617
|
+
/**
|
|
2618
|
+
* Condition-number ESTIMATE (Hager/Higham 1-norm power-iteration estimator)
|
|
2619
|
+
*
|
|
2620
|
+
* Estimates `‖A‖₁ · ‖A⁻¹‖₁` without ever forming `A⁻¹` explicitly — Hager's
|
|
2621
|
+
* algorithm (Hager 1984; Higham 1988's practical refinement) needs only the
|
|
2622
|
+
* ability to apply `A⁻¹` and `A⁻ᵀ` to a vector, which is done here via the
|
|
2623
|
+
* existing `lu()` primitive's triangular factors (forward/back substitution,
|
|
2624
|
+
* O(n²) per application vs. O(n³) to form `A⁻¹` or run the SVD-based exact
|
|
2625
|
+
* `cond()` in `svd.ts`). The result is an ESTIMATE — typically a lower bound
|
|
2626
|
+
* on the true `‖A⁻¹‖₁`, usually within a small constant factor — not the
|
|
2627
|
+
* exact value.
|
|
2628
|
+
*/
|
|
2629
|
+
|
|
2630
|
+
/**
|
|
2631
|
+
* Estimate the 1-norm condition number `‖A‖₁ · ‖A⁻¹‖₁` of a square matrix.
|
|
2632
|
+
*
|
|
2633
|
+
* This is an ESTIMATE (Hager/Higham power iteration), not the exact
|
|
2634
|
+
* condition number that `cond()` (in `svd.ts`) computes via a full SVD —
|
|
2635
|
+
* `condest` is O(n²)-per-iteration and avoids forming `A⁻¹`, at the cost of
|
|
2636
|
+
* being a (typically close) lower-bound estimate rather than an exact value.
|
|
2637
|
+
*
|
|
2638
|
+
* @param A - Square input matrix.
|
|
2639
|
+
* @param p - Only the 1-norm (`p = 1`, the default) is currently implemented.
|
|
2640
|
+
* @throws {Error} if `A` is not square, or `p !== 1`.
|
|
2641
|
+
*/
|
|
2642
|
+
declare function condest(A: DenseMatrix, p?: number): number;
|
|
2643
|
+
|
|
2510
2644
|
/**
|
|
2511
2645
|
* Typed Matrix Operations
|
|
2512
2646
|
*
|
|
@@ -2890,4 +3024,4 @@ declare function initializeParallelMatrix(): Promise<void>;
|
|
|
2890
3024
|
*/
|
|
2891
3025
|
declare function terminateParallelMatrix(): Promise<void>;
|
|
2892
3026
|
|
|
2893
|
-
export { BUILTIN_SHADERS, type BackendHints, BackendManager, BackendRegistry, type BackendType, BatchExecutor, type CholeskyResult, DEFAULT_BACKEND_HINTS, DEFAULT_EXTENDED_HINTS, DenseMatrix, type EigOptions, type EigResult, type ExpmOptions, type ExtendedBackendHints, GPUBackend, type GPUBackendOptions, type GPUBackendStatus, GPUMatrixBackend, type GPUMatrixBackendConfig, JSBackend, type LUResult, type LogmOptions, Matrix, type MatrixBackend, type MatrixDimensions, type MatrixEntry, type MatrixIndex, type MatrixType, type OperationType, ParallelBackend, type ParallelBackendConfig, type PinvOptions, type QROptions, type QRResult, type SVDOptions, type SVDResult, type SchurOptions, type SchurResult, type SliceSpec, SparseMatrix, type SqrtmOptions, type SyncConfig, SyncManager, type SyncStrategy, WASMBackend, type WASMBackendConfig, type WasmFeatures, abs, add, backendManager, backendRegistry, cholesky, clearFeatureCache, column, cond, createBackendManager, createGPUMatrixBackend, createParallelBackend, createSyncManager, createWASMBackend, destroyGlobalGPUBackend, detectWasmFeatures, diag, diagonal, divide, dotMultiply, eig, eigWasm, eigvals, eigvalsWasm, exp, getCachedFeatures, getGlobalGPUBackend, gpuMatrixBackend, identity, initializeGlobalGPUBackend, initializeParallelMatrix, isAtomicsAvailable, isDenseMatrix, isMatrix, isSharedMemoryAvailable, isSparseMatrix, isWasmAvailable, jsBackend, log, lowRankApprox, lu, matrix, matrixExpm, matrixLogm, pinv as matrixPinv, matrixSchur, matrixSqrtm, max, mean, min, multiply, norm, norm2, normFro, ones, parallelBackend, parallelDiag, parallelDotMultiply, parallelIdentity, parallelMatrix, parallelMatrixAbs, parallelMatrixAdd, parallelMatrixColumn, parallelMatrixCos, parallelMatrixDiagonal, parallelMatrixDistance, parallelMatrixDivide, parallelMatrixDot, parallelMatrixExp, parallelMatrixHistogram, parallelMatrixLog, parallelMatrixMatvec, parallelMatrixMax, parallelMatrixMean, parallelMatrixMin, parallelMatrixMultiply, parallelMatrixNorm, parallelMatrixOperations, parallelMatrixOuter, parallelMatrixRow, parallelMatrixSin, parallelMatrixSize, parallelMatrixSqrt, parallelMatrixSquare, parallelMatrixStd, parallelMatrixSubset, parallelMatrixSubtract, parallelMatrixSum, parallelMatrixTan, parallelMatrixTrace, parallelMatrixTranspose, parallelMatrixVariance, parallelOnes, parallelRandom, parallelUnaryMinus, parallelZeros, pinv$1 as pinv, pow, powerIteration, qr, random, row, singularValues, size, spectralRadiusWasm, sqrt, square, subset, subtract, sum, svd, svdWasm, terminateParallelMatrix, trace, transpose, typedMatrixOperations, unaryMinus, wasmBackend, zeros };
|
|
3027
|
+
export { BUILTIN_SHADERS, type BackendHints, BackendManager, BackendRegistry, type BackendType, BatchExecutor, type CholeskyResult, DEFAULT_BACKEND_HINTS, DEFAULT_EXTENDED_HINTS, DenseMatrix, type EigOptions, type EigResult, type ExpmOptions, type ExtendedBackendHints, GPUBackend, type GPUBackendOptions, type GPUBackendStatus, GPUMatrixBackend, type GPUMatrixBackendConfig, JSBackend, type LQResult, type LUResult, type LogmOptions, Matrix, type MatrixBackend, type MatrixDimensions, type MatrixEntry, type MatrixIndex, type MatrixType, type OperationType, ParallelBackend, type ParallelBackendConfig, type PinvOptions, type QLResult, type QROptions, type QRPivotedOptions, type QRPivotedResult, type QRResult, type RQResult, type SVDOptions, type SVDResult, type SchurOptions, type SchurResult, type SliceSpec, SparseMatrix, type SqrtmOptions, type SyncConfig, SyncManager, type SyncStrategy, WASMBackend, type WASMBackendConfig, type WasmFeatures, abs, add, backendManager, backendRegistry, cholesky, clearFeatureCache, column, cond, condest, createBackendManager, createGPUMatrixBackend, createParallelBackend, createSyncManager, createWASMBackend, destroyGlobalGPUBackend, detectWasmFeatures, diag, diagonal, divide, dotMultiply, eig, eigWasm, eigvals, eigvalsWasm, exp, getCachedFeatures, getGlobalGPUBackend, gpuMatrixBackend, identity, initializeGlobalGPUBackend, initializeParallelMatrix, isAtomicsAvailable, isDenseMatrix, isMatrix, isSharedMemoryAvailable, isSparseMatrix, isWasmAvailable, jsBackend, log, lowRankApprox, lq, lu, matrix, matrixExpm, matrixLogm, pinv as matrixPinv, matrixSchur, matrixSqrtm, max, mean, min, multiply, norm, norm2, normFro, ones, parallelBackend, parallelDiag, parallelDotMultiply, parallelIdentity, parallelMatrix, parallelMatrixAbs, parallelMatrixAdd, parallelMatrixColumn, parallelMatrixCos, parallelMatrixDiagonal, parallelMatrixDistance, parallelMatrixDivide, parallelMatrixDot, parallelMatrixExp, parallelMatrixHistogram, parallelMatrixLog, parallelMatrixMatvec, parallelMatrixMax, parallelMatrixMean, parallelMatrixMin, parallelMatrixMultiply, parallelMatrixNorm, parallelMatrixOperations, parallelMatrixOuter, parallelMatrixRow, parallelMatrixSin, parallelMatrixSize, parallelMatrixSqrt, parallelMatrixSquare, parallelMatrixStd, parallelMatrixSubset, parallelMatrixSubtract, parallelMatrixSum, parallelMatrixTan, parallelMatrixTrace, parallelMatrixTranspose, parallelMatrixVariance, parallelOnes, parallelRandom, parallelUnaryMinus, parallelZeros, pinv$1 as pinv, pow, powerIteration, ql, qr, qrPivoted, random, row, rq, singularValues, size, spectralRadiusWasm, sqrt, square, subset, subtract, sum, svd, svdWasm, terminateParallelMatrix, trace, transpose, typedMatrixOperations, unaryMinus, wasmBackend, zeros };
|
package/dist/index.js
CHANGED
|
@@ -5740,11 +5740,13 @@ function eigGeneral(A, computeVectors, symmetric) {
|
|
|
5740
5740
|
const values = [];
|
|
5741
5741
|
for (let j = 0; j < nn; j++) values.push({ re: d[j], im: e[j] });
|
|
5742
5742
|
let vectors;
|
|
5743
|
+
let vectorsIm;
|
|
5743
5744
|
if (computeVectors) {
|
|
5744
5745
|
vectors = [];
|
|
5745
|
-
|
|
5746
|
-
|
|
5746
|
+
vectorsIm = [];
|
|
5747
|
+
for (let j = 0; j < nn; ) {
|
|
5747
5748
|
if (e[j] === 0) {
|
|
5749
|
+
const vec = new Array(nn).fill(0);
|
|
5748
5750
|
let colNorm = 0;
|
|
5749
5751
|
for (let i = 0; i < nn; i++) colNorm += V[i * nn + j] * V[i * nn + j];
|
|
5750
5752
|
colNorm = Math.sqrt(colNorm);
|
|
@@ -5753,13 +5755,42 @@ function eigGeneral(A, computeVectors, symmetric) {
|
|
|
5753
5755
|
} else {
|
|
5754
5756
|
for (let i = 0; i < nn; i++) vec[i] = V[i * nn + j];
|
|
5755
5757
|
}
|
|
5758
|
+
vectors.push(vec);
|
|
5759
|
+
vectorsIm.push(new Array(nn).fill(0));
|
|
5760
|
+
j++;
|
|
5761
|
+
} else {
|
|
5762
|
+
const vecRe = new Array(nn).fill(0);
|
|
5763
|
+
const vecIm = new Array(nn).fill(0);
|
|
5764
|
+
let colNorm = 0;
|
|
5765
|
+
for (let i = 0; i < nn; i++) {
|
|
5766
|
+
const re = V[i * nn + j];
|
|
5767
|
+
const im = V[i * nn + (j + 1)];
|
|
5768
|
+
colNorm += re * re + im * im;
|
|
5769
|
+
}
|
|
5770
|
+
colNorm = Math.sqrt(colNorm);
|
|
5771
|
+
if (colNorm > 1e-300) {
|
|
5772
|
+
for (let i = 0; i < nn; i++) {
|
|
5773
|
+
vecRe[i] = V[i * nn + j] / colNorm;
|
|
5774
|
+
vecIm[i] = V[i * nn + (j + 1)] / colNorm;
|
|
5775
|
+
}
|
|
5776
|
+
} else {
|
|
5777
|
+
for (let i = 0; i < nn; i++) {
|
|
5778
|
+
vecRe[i] = V[i * nn + j];
|
|
5779
|
+
vecIm[i] = V[i * nn + (j + 1)];
|
|
5780
|
+
}
|
|
5781
|
+
}
|
|
5782
|
+
vectors.push(vecRe);
|
|
5783
|
+
vectorsIm.push(vecIm);
|
|
5784
|
+
vectors.push(vecRe.slice());
|
|
5785
|
+
vectorsIm.push(vecIm.map((x2) => -x2));
|
|
5786
|
+
j += 2;
|
|
5756
5787
|
}
|
|
5757
|
-
vectors.push(vec);
|
|
5758
5788
|
}
|
|
5759
5789
|
} else {
|
|
5760
5790
|
vectors = eye(nn);
|
|
5791
|
+
vectorsIm = Array.from({ length: nn }, () => new Array(nn).fill(0));
|
|
5761
5792
|
}
|
|
5762
|
-
return { values, vectors, isSymmetric: symmetric };
|
|
5793
|
+
return { values, vectors, vectorsIm, isSymmetric: symmetric };
|
|
5763
5794
|
}
|
|
5764
5795
|
function eig(matrix2, options = {}) {
|
|
5765
5796
|
const { computeVectors = true } = options;
|
|
@@ -5775,7 +5806,7 @@ function eig(matrix2, options = {}) {
|
|
|
5775
5806
|
}
|
|
5776
5807
|
const n = A.length;
|
|
5777
5808
|
if (n === 0) {
|
|
5778
|
-
return { values: [], vectors: [], isSymmetric: true };
|
|
5809
|
+
return { values: [], vectors: [], vectorsIm: [], isSymmetric: true };
|
|
5779
5810
|
}
|
|
5780
5811
|
for (let i = 0; i < n; i++) {
|
|
5781
5812
|
if (A[i].length !== n) {
|
|
@@ -5787,6 +5818,7 @@ function eig(matrix2, options = {}) {
|
|
|
5787
5818
|
return {
|
|
5788
5819
|
values: [{ re: A[0][0], im: 0 }],
|
|
5789
5820
|
vectors: [[1]],
|
|
5821
|
+
vectorsIm: [[0]],
|
|
5790
5822
|
isSymmetric: symmetric
|
|
5791
5823
|
};
|
|
5792
5824
|
}
|
|
@@ -6224,7 +6256,7 @@ function normFro(matrix2) {
|
|
|
6224
6256
|
async function eigWasm(matrix2, options) {
|
|
6225
6257
|
const n = matrix2.length;
|
|
6226
6258
|
if (n === 0) {
|
|
6227
|
-
return { values: [], vectors: [], isSymmetric: true };
|
|
6259
|
+
return { values: [], vectors: [], vectorsIm: [], isSymmetric: true };
|
|
6228
6260
|
}
|
|
6229
6261
|
for (let i = 0; i < n; i++) {
|
|
6230
6262
|
if (matrix2[i].length !== n) {
|
|
@@ -7391,6 +7423,236 @@ function isSymmetricMatrix(A, tol = 1e-8) {
|
|
|
7391
7423
|
return true;
|
|
7392
7424
|
}
|
|
7393
7425
|
|
|
7426
|
+
// src/operations/qr-pivoted.ts
|
|
7427
|
+
init_DenseMatrix();
|
|
7428
|
+
function qrPivoted(A, opts) {
|
|
7429
|
+
const m = A.rows;
|
|
7430
|
+
const n = A.cols;
|
|
7431
|
+
const tol = opts?.tolerance ?? 1e-10;
|
|
7432
|
+
const k = Math.min(m, n);
|
|
7433
|
+
if (m === 0 || n === 0) {
|
|
7434
|
+
return {
|
|
7435
|
+
Q: DenseMatrix.identity(m),
|
|
7436
|
+
R: DenseMatrix.zeros(k, n),
|
|
7437
|
+
P: Array.from({ length: n }, (_, i) => i),
|
|
7438
|
+
rank: 0
|
|
7439
|
+
};
|
|
7440
|
+
}
|
|
7441
|
+
const W = A.toArray();
|
|
7442
|
+
const Qacc = eye(m);
|
|
7443
|
+
const perm = Array.from({ length: n }, (_, i) => i);
|
|
7444
|
+
const colNormSq = new Array(n).fill(0);
|
|
7445
|
+
for (let j = 0; j < n; j++) {
|
|
7446
|
+
let s = 0;
|
|
7447
|
+
for (let i = 0; i < m; i++) s += W[i][j] * W[i][j];
|
|
7448
|
+
colNormSq[j] = s;
|
|
7449
|
+
}
|
|
7450
|
+
for (let c = 0; c < k; c++) {
|
|
7451
|
+
let pivotCol = c;
|
|
7452
|
+
let maxNorm = colNormSq[c];
|
|
7453
|
+
for (let j = c + 1; j < n; j++) {
|
|
7454
|
+
if (colNormSq[j] > maxNorm) {
|
|
7455
|
+
maxNorm = colNormSq[j];
|
|
7456
|
+
pivotCol = j;
|
|
7457
|
+
}
|
|
7458
|
+
}
|
|
7459
|
+
if (pivotCol !== c) {
|
|
7460
|
+
for (let i = 0; i < m; i++) {
|
|
7461
|
+
const t = W[i][c];
|
|
7462
|
+
W[i][c] = W[i][pivotCol];
|
|
7463
|
+
W[i][pivotCol] = t;
|
|
7464
|
+
}
|
|
7465
|
+
const tn = colNormSq[c];
|
|
7466
|
+
colNormSq[c] = colNormSq[pivotCol];
|
|
7467
|
+
colNormSq[pivotCol] = tn;
|
|
7468
|
+
const tp = perm[c];
|
|
7469
|
+
perm[c] = perm[pivotCol];
|
|
7470
|
+
perm[pivotCol] = tp;
|
|
7471
|
+
}
|
|
7472
|
+
const col = [];
|
|
7473
|
+
for (let i = c; i < m; i++) col.push(W[i][c]);
|
|
7474
|
+
const { v, beta } = householder(col, 2);
|
|
7475
|
+
if (beta !== 0) {
|
|
7476
|
+
applyHouseholderLeft(W, v, beta, c, c);
|
|
7477
|
+
applyHouseholderRight(Qacc, v, beta, 0, c);
|
|
7478
|
+
}
|
|
7479
|
+
for (let j = c + 1; j < n; j++) {
|
|
7480
|
+
let s = 0;
|
|
7481
|
+
for (let i = c + 1; i < m; i++) s += W[i][j] * W[i][j];
|
|
7482
|
+
colNormSq[j] = s;
|
|
7483
|
+
}
|
|
7484
|
+
}
|
|
7485
|
+
for (let i = 0; i < m; i++) {
|
|
7486
|
+
for (let j = 0; j < Math.min(i, n); j++) {
|
|
7487
|
+
W[i][j] = 0;
|
|
7488
|
+
}
|
|
7489
|
+
}
|
|
7490
|
+
const rData = new Float64Array(k * n);
|
|
7491
|
+
for (let i = 0; i < k; i++) {
|
|
7492
|
+
for (let j = 0; j < n; j++) rData[i * n + j] = W[i][j];
|
|
7493
|
+
}
|
|
7494
|
+
const qData = new Float64Array(m * k);
|
|
7495
|
+
for (let i = 0; i < m; i++) {
|
|
7496
|
+
for (let j = 0; j < k; j++) qData[i * k + j] = Qacc[i][j];
|
|
7497
|
+
}
|
|
7498
|
+
const r00 = Math.abs(rData[0] ?? 0);
|
|
7499
|
+
let rank = 0;
|
|
7500
|
+
if (r00 > 0) {
|
|
7501
|
+
for (let i = 0; i < k; i++) {
|
|
7502
|
+
if (Math.abs(rData[i * n + i]) > tol * r00) rank++;
|
|
7503
|
+
}
|
|
7504
|
+
}
|
|
7505
|
+
return {
|
|
7506
|
+
Q: new DenseMatrix(m, k, qData),
|
|
7507
|
+
R: new DenseMatrix(k, n, rData),
|
|
7508
|
+
P: perm,
|
|
7509
|
+
rank
|
|
7510
|
+
};
|
|
7511
|
+
}
|
|
7512
|
+
|
|
7513
|
+
// src/operations/qr-family.ts
|
|
7514
|
+
init_DenseMatrix();
|
|
7515
|
+
function flipRows(M) {
|
|
7516
|
+
const m = M.rows;
|
|
7517
|
+
const n = M.cols;
|
|
7518
|
+
const src = M.toFloat64Array();
|
|
7519
|
+
const data = new Float64Array(m * n);
|
|
7520
|
+
for (let i = 0; i < m; i++) {
|
|
7521
|
+
for (let j = 0; j < n; j++) {
|
|
7522
|
+
data[i * n + j] = src[(m - 1 - i) * n + j];
|
|
7523
|
+
}
|
|
7524
|
+
}
|
|
7525
|
+
return new DenseMatrix(m, n, data);
|
|
7526
|
+
}
|
|
7527
|
+
function flipCols(M) {
|
|
7528
|
+
const m = M.rows;
|
|
7529
|
+
const n = M.cols;
|
|
7530
|
+
const src = M.toFloat64Array();
|
|
7531
|
+
const data = new Float64Array(m * n);
|
|
7532
|
+
for (let i = 0; i < m; i++) {
|
|
7533
|
+
for (let j = 0; j < n; j++) {
|
|
7534
|
+
data[i * n + j] = src[i * n + (n - 1 - j)];
|
|
7535
|
+
}
|
|
7536
|
+
}
|
|
7537
|
+
return new DenseMatrix(m, n, data);
|
|
7538
|
+
}
|
|
7539
|
+
function lq(A) {
|
|
7540
|
+
const { Q: Q1, R: R1 } = qr(A.transpose(), { mode: "reduced" });
|
|
7541
|
+
return { L: R1.transpose(), Q: Q1.transpose() };
|
|
7542
|
+
}
|
|
7543
|
+
function rq(A) {
|
|
7544
|
+
const B2 = flipRows(A).transpose();
|
|
7545
|
+
const { Q: Q1, R: R1 } = qr(B2, { mode: "reduced" });
|
|
7546
|
+
const R = flipCols(flipRows(R1.transpose()));
|
|
7547
|
+
const Q = flipRows(Q1.transpose());
|
|
7548
|
+
return { R, Q };
|
|
7549
|
+
}
|
|
7550
|
+
function ql(A) {
|
|
7551
|
+
const B2 = flipCols(A);
|
|
7552
|
+
const { Q: Q1, R: R1 } = qr(B2, { mode: "reduced" });
|
|
7553
|
+
const L = flipCols(flipRows(R1));
|
|
7554
|
+
const Q = flipCols(Q1);
|
|
7555
|
+
return { Q, L };
|
|
7556
|
+
}
|
|
7557
|
+
|
|
7558
|
+
// src/operations/condest.ts
|
|
7559
|
+
function luSolve(L, U, perm, n, b) {
|
|
7560
|
+
const pb = new Array(n);
|
|
7561
|
+
for (let i = 0; i < n; i++) pb[i] = b[perm[i]];
|
|
7562
|
+
const y = new Array(n);
|
|
7563
|
+
for (let i = 0; i < n; i++) {
|
|
7564
|
+
let s = pb[i];
|
|
7565
|
+
for (let j = 0; j < i; j++) s -= L[i * n + j] * y[j];
|
|
7566
|
+
y[i] = s;
|
|
7567
|
+
}
|
|
7568
|
+
const x = new Array(n);
|
|
7569
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
7570
|
+
let s = y[i];
|
|
7571
|
+
for (let j = i + 1; j < n; j++) s -= U[i * n + j] * x[j];
|
|
7572
|
+
x[i] = s / U[i * n + i];
|
|
7573
|
+
}
|
|
7574
|
+
return x;
|
|
7575
|
+
}
|
|
7576
|
+
function luSolveTranspose(L, U, perm, n, b) {
|
|
7577
|
+
const z = new Array(n);
|
|
7578
|
+
for (let i = 0; i < n; i++) {
|
|
7579
|
+
let s = b[i];
|
|
7580
|
+
for (let j = 0; j < i; j++) s -= U[j * n + i] * z[j];
|
|
7581
|
+
z[i] = s / U[i * n + i];
|
|
7582
|
+
}
|
|
7583
|
+
const w = new Array(n);
|
|
7584
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
7585
|
+
let s = z[i];
|
|
7586
|
+
for (let j = i + 1; j < n; j++) s -= L[j * n + i] * w[j];
|
|
7587
|
+
w[i] = s;
|
|
7588
|
+
}
|
|
7589
|
+
const x = new Array(n);
|
|
7590
|
+
for (let i = 0; i < n; i++) x[perm[i]] = w[i];
|
|
7591
|
+
return x;
|
|
7592
|
+
}
|
|
7593
|
+
function hagerNormEstimate(applyB, applyBT, n) {
|
|
7594
|
+
let x = new Array(n).fill(1 / n);
|
|
7595
|
+
let gamma = 0;
|
|
7596
|
+
let lastIndex = -1;
|
|
7597
|
+
for (let iter = 0; iter < 5; iter++) {
|
|
7598
|
+
const y = applyB(x);
|
|
7599
|
+
let newGamma = 0;
|
|
7600
|
+
for (const v of y) newGamma += Math.abs(v);
|
|
7601
|
+
if (iter > 0 && newGamma <= gamma) break;
|
|
7602
|
+
gamma = newGamma;
|
|
7603
|
+
const xi = y.map((v) => v >= 0 ? 1 : -1);
|
|
7604
|
+
const z = applyBT(xi);
|
|
7605
|
+
let maxIndex = 0;
|
|
7606
|
+
let maxAbs = Math.abs(z[0]);
|
|
7607
|
+
for (let i = 1; i < n; i++) {
|
|
7608
|
+
if (Math.abs(z[i]) > maxAbs) {
|
|
7609
|
+
maxAbs = Math.abs(z[i]);
|
|
7610
|
+
maxIndex = i;
|
|
7611
|
+
}
|
|
7612
|
+
}
|
|
7613
|
+
if (iter > 0 && maxIndex === lastIndex) break;
|
|
7614
|
+
lastIndex = maxIndex;
|
|
7615
|
+
x = new Array(n).fill(0);
|
|
7616
|
+
x[maxIndex] = 1;
|
|
7617
|
+
}
|
|
7618
|
+
return gamma;
|
|
7619
|
+
}
|
|
7620
|
+
function condest(A, p = 1) {
|
|
7621
|
+
if (p !== 1) {
|
|
7622
|
+
throw new Error(`condest: only the 1-norm estimator (p=1) is implemented (got p=${p})`);
|
|
7623
|
+
}
|
|
7624
|
+
const n = A.rows;
|
|
7625
|
+
if (A.cols !== n) {
|
|
7626
|
+
throw new Error(`condest: matrix must be square (got ${A.rows}\xD7${A.cols})`);
|
|
7627
|
+
}
|
|
7628
|
+
if (n === 0) return 0;
|
|
7629
|
+
const flat2 = A.toFloat64Array();
|
|
7630
|
+
let norm1A = 0;
|
|
7631
|
+
for (let j = 0; j < n; j++) {
|
|
7632
|
+
let colSum = 0;
|
|
7633
|
+
for (let i = 0; i < n; i++) colSum += Math.abs(flat2[i * n + j]);
|
|
7634
|
+
if (colSum > norm1A) norm1A = colSum;
|
|
7635
|
+
}
|
|
7636
|
+
if (norm1A === 0) return 0;
|
|
7637
|
+
let L;
|
|
7638
|
+
let U;
|
|
7639
|
+
let perm;
|
|
7640
|
+
try {
|
|
7641
|
+
const factors = lu(A);
|
|
7642
|
+
L = factors.L.toFloat64Array();
|
|
7643
|
+
U = factors.U.toFloat64Array();
|
|
7644
|
+
perm = factors.P;
|
|
7645
|
+
} catch {
|
|
7646
|
+
return Infinity;
|
|
7647
|
+
}
|
|
7648
|
+
const norm1Inv = hagerNormEstimate(
|
|
7649
|
+
(v) => luSolve(L, U, perm, n, v),
|
|
7650
|
+
(v) => luSolveTranspose(L, U, perm, n, v),
|
|
7651
|
+
n
|
|
7652
|
+
);
|
|
7653
|
+
return norm1A * norm1Inv;
|
|
7654
|
+
}
|
|
7655
|
+
|
|
7394
7656
|
// src/typed-operations.ts
|
|
7395
7657
|
init_DenseMatrix();
|
|
7396
7658
|
import { mathTyped } from "@danielsimonjr/mathts-core";
|
|
@@ -8243,6 +8505,7 @@ export {
|
|
|
8243
8505
|
clearFeatureCache,
|
|
8244
8506
|
column,
|
|
8245
8507
|
cond,
|
|
8508
|
+
condest,
|
|
8246
8509
|
createBackendManager,
|
|
8247
8510
|
createGPUMatrixBackend,
|
|
8248
8511
|
createParallelBackend,
|
|
@@ -8279,6 +8542,7 @@ export {
|
|
|
8279
8542
|
jsBackend,
|
|
8280
8543
|
log,
|
|
8281
8544
|
lowRankApprox,
|
|
8545
|
+
lq,
|
|
8282
8546
|
lu,
|
|
8283
8547
|
matrix,
|
|
8284
8548
|
matrixExpm,
|
|
@@ -8338,9 +8602,12 @@ export {
|
|
|
8338
8602
|
pinv,
|
|
8339
8603
|
pow,
|
|
8340
8604
|
powerIteration,
|
|
8605
|
+
ql,
|
|
8341
8606
|
qr,
|
|
8607
|
+
qrPivoted,
|
|
8342
8608
|
random,
|
|
8343
8609
|
row,
|
|
8610
|
+
rq,
|
|
8344
8611
|
singularValues,
|
|
8345
8612
|
size,
|
|
8346
8613
|
spectralRadiusWasm,
|