@danielsimonjr/mathts-matrix 0.5.0 → 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 +119 -1
- package/dist/index.js +235 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2523,6 +2523,124 @@ interface SchurOptions {
|
|
|
2523
2523
|
*/
|
|
2524
2524
|
declare function matrixSchur(A: DenseMatrix, opts?: SchurOptions): SchurResult;
|
|
2525
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
|
+
|
|
2526
2644
|
/**
|
|
2527
2645
|
* Typed Matrix Operations
|
|
2528
2646
|
*
|
|
@@ -2906,4 +3024,4 @@ declare function initializeParallelMatrix(): Promise<void>;
|
|
|
2906
3024
|
*/
|
|
2907
3025
|
declare function terminateParallelMatrix(): Promise<void>;
|
|
2908
3026
|
|
|
2909
|
-
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
|
@@ -7423,6 +7423,236 @@ function isSymmetricMatrix(A, tol = 1e-8) {
|
|
|
7423
7423
|
return true;
|
|
7424
7424
|
}
|
|
7425
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
|
+
|
|
7426
7656
|
// src/typed-operations.ts
|
|
7427
7657
|
init_DenseMatrix();
|
|
7428
7658
|
import { mathTyped } from "@danielsimonjr/mathts-core";
|
|
@@ -8275,6 +8505,7 @@ export {
|
|
|
8275
8505
|
clearFeatureCache,
|
|
8276
8506
|
column,
|
|
8277
8507
|
cond,
|
|
8508
|
+
condest,
|
|
8278
8509
|
createBackendManager,
|
|
8279
8510
|
createGPUMatrixBackend,
|
|
8280
8511
|
createParallelBackend,
|
|
@@ -8311,6 +8542,7 @@ export {
|
|
|
8311
8542
|
jsBackend,
|
|
8312
8543
|
log,
|
|
8313
8544
|
lowRankApprox,
|
|
8545
|
+
lq,
|
|
8314
8546
|
lu,
|
|
8315
8547
|
matrix,
|
|
8316
8548
|
matrixExpm,
|
|
@@ -8370,9 +8602,12 @@ export {
|
|
|
8370
8602
|
pinv,
|
|
8371
8603
|
pow,
|
|
8372
8604
|
powerIteration,
|
|
8605
|
+
ql,
|
|
8373
8606
|
qr,
|
|
8607
|
+
qrPivoted,
|
|
8374
8608
|
random,
|
|
8375
8609
|
row,
|
|
8610
|
+
rq,
|
|
8376
8611
|
singularValues,
|
|
8377
8612
|
size,
|
|
8378
8613
|
spectralRadiusWasm,
|