mathjslab
Version:
MathJSLab - An interpreter with language syntax like MATLAB®/Octave, ISBN 978-65-00-82338-7.
510 lines (509 loc) • 20.4 kB
TypeScript
import { ComplexType } from './Complex';
import { type ElementType, MultiArray } from './MultiArray';
/**
* # LAPACK (Linear Algebra PACKage)
*
* ## References
* - https://en.wikipedia.org/wiki/LAPACK
* - https://www.netlib.org/lapack/
* - https://github.com/Reference-LAPACK/lapack
*/
declare abstract class LAPACK {
/**
* Apply a sequence of row interchanges to a MultiArray.
* LAPACK-like signature: laswp(A, k1, k2, ipiv, incx, colStart = 0, colEnd = numCols-1)
* @param A Multidimensional matrix.
* @param k1 1-based start index of rows to process (inclusive).
* @param k2 1-based end index of rows to process (inclusive).
* @param ipiv Integer array of pivot indices (LAPACK convention: 1-based). The routine will auto-detect if ipiv looks 0-based and adapt.
* @param incx Increment (typically +1 or -1). When incx > 0 loop i=k1..k2 step incx; when incx<0 loop i=k1..k2 step incx.
* @param colStart Optional 0-based column start to which the swaps are applied (inclusive).
* @param colEnd Optional 0-based column end to which the swaps are applied (inclusive).
* @returns
*/
static readonly laswp: (A: MultiArray, k1: number, k2: number, ipiv: number[], incx: number, colStart?: number, colEnd?: number) => void;
/**
* Swap two rows of an N-dimensional MultiArray across all pages in place.
* It is `LAPACK.laswp` for a single pivot applied across slices). `row1`,
* `row2` are 0-based indices within the first dimension.
* @param M Matrix.
* @param row1 First row index to swap.
* @param row2 Second row index to swap.
*/
static readonly laswp_rows: (M: MultiArray, row1: number, row2: number) => void;
/**
* Swap two columns of an N-dimensional MultiArray across all pages in
* place. There is no direct equivalent to LAPACK, but it is symmetrical
* to `laswp_rows`.
* @param M Matrix.
* @param col1 First column index to swap.
* @param col2 Second column index to swap.
*/
static readonly laswp_cols: (M: MultiArray, col1: number, col2: number) => void;
/**
* Returns a 2D or ND-aware identity matrix generator (`ComplexType[][]`), row-major.
* Optimized for internal `BLAS`/`LAPACK` operations.
* Supports arbitrary number of dimensions.
*
* Usage:
* `LAPACK.eye(2,3,5,4)` -> MultiArray with dims [2,3,5,4]
* `LAPACK.eye([2,3,5,4])` -> same as above
*
* Diagonal filled with `1` (`Complex.one()`), rest zeros.
* Each 2-D page `[m,n]` in `ND` array gets its own identity.
* @param dims `number[] | ...number`
*/
static readonly eye: (...dims: any[]) => ComplexType[][];
/**
* Return the squared Euclidean norm of the slice R[startRow..m-1, col].
* Result is returned as a ComplexType whose imaginary part is zero (real value).
*
* Equivalent (conceptually) to (ZNRM2(R[startRow: m-1, col]))^2 but computed directly.
*
* @param R MultiArray
* @param col column index
* @param startRow starting row (inclusive)
* @param m number of rows in R (or row limit)
* @returns ComplexType representing the real value sum_i |R[i,col]|^2
*/
static readonly nrm2sq: (R: MultiArray, col: number, startRow: number, m: number) => ComplexType;
/**
* Return the Euclidean norm (sqrt of sum |x_i|^2) as a ComplexType whose imaginary part is zero.
* This is the direct analogue of LAPACK's ZNRM2 (but returning ComplexType to fit your engine).
*
* @param R MultiArray
* @param col column index
* @param startRow starting row (inclusive)
* @param m number of rows in R (or row limit)
*/
static readonly nrm2: (R: MultiArray, col: number, startRow: number, m: number) => ComplexType;
/**
* Zero the lower triangular part (i > j), keeping only the upper triangle. LAPACK-like TRIU operation.
* @param M
*/
static readonly triu_inplace: (M: MultiArray) => void;
/**
* Zero the upper triangular part (j > i), keeping only the lower triangle. LAPACK-like TRIL operation.
* @param M
*/
static readonly tril_inplace: (M: MultiArray) => void;
/**
* Solve for X in U * X = B where U is upper triangular k x k stored at
* A[kblock]. We implement in-place update of Bblock (A12 region). Block
* target at rows k..k+kb-1, cols k+kb..n-1
* @param A full MultiArray; U is at rows k..k+kb-1, cols k..k+kb-1
* @param k
* @param kb
*/
static readonly trsm_left_upper: (A: MultiArray, k: number, kb: number) => void;
/**
*
* @param jpvt
* @returns
*/
static readonly lapmt_matrix: (jpvt: number[]) => MultiArray;
/**
* ## `LAPACK.larfg_left`
* LAPACK-style LARFG - Compute Householder vector and tau for complex
* vectors `x = A[k:m-1, k]`. It's a complex householder generator for
* left-side application. Generates `tau`, `v`, `phi` and `alpha` for
* `H = I - tau*v*v^H`.
* ### Notes:
* - Uses `BLAS.dotc_col(A, k, k)` to compute `sigma = sum_{i>k} |x_i|^2`.
* - Follows the ZLARFG convention (`alpha = -phi * ||x||`, with `phi = x0/|x0|` when `x0!=0`).
* @param A Target MultiArray (only used for shape reference).
* @param m Number of rows
* @param k Start index of reflector
* @returns object { tau, v, phi, alpha } where:
* - `v` is a ComplexType[] with `v[0] = 1` and `length = m-k`.
* - `tau` is ComplexType.
* - `phi` is ComplexType.
* - `alpha` is the resulting leading value (the value that replaces `A[k,k]`)
*/
static readonly larfg_left: (A: MultiArray, m: number, k: number) => {
tau: ComplexType;
v: ComplexType[];
phi: ComplexType;
alpha: ComplexType;
};
/**
* ## `LAPACK.larfg_right`
* LAPACK-style LARFG - build a Householder reflector acting **on the right**.
*
* Computes tau, v, phi, alpha for the vector
* x = A[k, k:n-1]^T (row segment)
*
* Equivalent to generating H = I - tau * v * v^H
* such that H * x = [ alpha ; 0 ; ... ].
*
* ### Notes:
* - Uses BLAS-style dotc over the *row* (sigma = sum |x_j|^2 over j>k).
* - Follows ZLARFG conventions: alpha = -phi * ||x||, with
* phi = x0 / |x0| when x0 != 0, otherwise phi = 1.
*
* @param A Target MultiArray (shape reference only)
* @param n Number of columns
* @param k Starting index of reflector (col index)
* @returns { tau, v, phi, alpha }:
* - v: ComplexType[] with v[0]=1, length = n-k
* - tau: ComplexType
* - phi: ComplexType
* - alpha: ComplexType (value that replaces A[k][k])
*/
static readonly larfg_right: (A: MultiArray, n: number, k: number) => {
tau: ComplexType;
v: ComplexType[];
phi: ComplexType;
alpha: ComplexType;
};
/**
* Generalized LAPACK-style complex Householder generator.
* Delegates to left or right version.
* @param side
* @param A
* @param m
* @param k
* @returns Object { tau, v, alpha }
*/
static readonly larfg: (side: "L" | "R", A: MultiArray, m: number, k: number) => {
tau: ComplexType;
v: ComplexType[];
alpha: ComplexType;
};
/**
* Generate Householder vector and apply it immediately to A.
* LAPACK-style: side-aware (left/right), complex.
* @param side 'L' for left, 'R' for right
* @param A Matrix to transform (modified in place)
* @param k Index for the reflector (row/column start)
*/
/**
*
* @param side
* @param A
* @param k
* @returns Object { tau, v, alpha }
*/
static readonly larfg_apply: (side: "L" | "R", A: MultiArray, k: number) => {
tau: ComplexType;
v: ComplexType[];
alpha: ComplexType;
};
/**
*
* @param A
* @param k
* @returns Object { tau, v, alpha }
*/
static readonly larfg_left_nd: (A: MultiArray, k: number) => {
tau: ComplexType;
v: ComplexType[];
alpha: ComplexType;
};
/**
*
* @param A
* @param k
* @returns Object { tau, v, alpha }
*/
static readonly larfg_right_nd: (A: MultiArray, k: number) => {
tau: ComplexType;
v: ComplexType[];
alpha: ComplexType;
};
/**
*
* @param side
* @param A
* @param k
* @returns
*/
static readonly larfg_nd: (side: "L" | "R", A: MultiArray, k: number) => {
tau: ComplexType;
v: ComplexType[];
alpha: ComplexType;
};
/**
* Apply an elementary reflector H = I - tau * v * v^H to a matrix A from the left.
* Equivalent to A := H * A for rows rowStart..m-1 and columns colStart..n-1.
*
* @param A Matrix to modify in-place.
* @param v Householder vector (ComplexType[]), v[0] == 1, length = m - rowStart.
* @param tau Complex scalar (possibly 0).
* @param rowStart Row index k (start of the reflector).
* @param colStart Column index (first column to update; usually k+1 or 0).
*/
static readonly larf_left: (A: MultiArray, v: ComplexType[], tau: ComplexType, rowStart: number, colStart: number) => void;
/**
* Apply an elementary reflector H = I - tau * v * v^H to A from the left,
* but restricted to columns colStart .. colEnd-1.
*
* A: MultiArray (row-major)
* v: ComplexType[] (v[0] == 1, length = m - rowStart)
* tau: ComplexType
* rowStart: starting row index of the reflector (k)
* colStart: first column to update (usually k+1)
* colEnd: (optional) one-past-last column to update (default = A.dimension[1])
*/
static readonly larf_left_block: (A: MultiArray, v: ComplexType[], tau: ComplexType, rowStart: number, colStart: number, colEnd?: number) => void;
/**
* Apply a complex Householder reflector from the RIGHT:
*
* A := A * (I - tau * v * v^H)
*
* This operates on the block:
* rows i = rowStart .. A.dimension[0]-1
* columns j = colStart .. colStart + v.length - 1
*
* Exactly matches LAPACK xLARF(side='R') behaviour.
*
* @param A MultiArray
* @param v Householder vector (length = block size)
* @param tau Householder scalar
* @param rowStart first row of the block
* @param colStart first column of the block
*/
static readonly larf_right: (A: MultiArray, v: ComplexType[], tau: ComplexType, rowStart: number, colStart: number) => void;
/**
*
* @param side
* @param A
* @param v
* @param tau
* @param rowStart
* @param colStart
* @returns
*/
static readonly larf: (side: "L" | "R", A: MultiArray, v: ComplexType[], tau: ComplexType, rowStart: number, colStart: number) => void;
/**
*
* @param A
* @param v
* @param tau
* @param rowStart
* @param colStart
* @returns
*/
static readonly larf_left_nd: (A: MultiArray, v: ComplexType[], tau: ComplexType, rowStart: number, colStart: number) => void;
/**
*
* @param A
* @param v
* @param tau
* @param rowStart
* @param colStart
* @returns
*/
static readonly larf_right_nd: (A: MultiArray, v: ComplexType[], tau: ComplexType, rowStart: number, colStart: number) => void;
static readonly larf_nd: (side: "L" | "R", A: MultiArray, v: ComplexType[], tau: ComplexType, rowStart: number, colStart: number) => void;
/**
* Unblocked QR factorization (GEQR2-like), complex version.
* Overwrites a copy of A and returns { R, taus }.
*/
/**
* Unblocked QR factorization (GEQR2-like), complex version.
* Overwrites a COPY of A and returns { R, taus }.
*/
/**
* ZGEQR2-like: unblocked QR (complex). Returns R (copy of A overwritten) and taus[].
*/
/**
* GEQR2 (unblocked) - QR factorization without pivoting (complex), MATLAB/Octave style.
*
* Produces:
* - R: copy of A with R[k,k] = alpha and R[k+1:m,k] = tau * v[1:]
* - taus: array of taus (one per reflector) to be used by orgqr
*
* Phase normalization is applied only when the input matrix contains complex entries.
* Order of operations:
* 1) compute (tau,v,phi,alpha) = larfg_left
* 2) store alpha at R[k,k]
* 3) apply H (with original tau,v) to trailing columns
* 4) if matrix is complex: scale R[k,:] by conj(phi), reparametrize v and tau
* 5) store R[k+1:m,k] = tau * v[1:]
*/
/**
* GEQR2 (unblocked) - QR factorization without pivoting (complex), LAPACK-style.
* - R is a copy de A com reflectors armazenados compactados (MATLAB/Octave-style):
* R[k,k] = alpha
* R[k+1:m,k] = tau * v[1:]
* - taus[k] guarda tau para cada reflector (usado por orgqr).
*/
/**
* Unblocked QR factorization without pivoting.
* - stores Householder vectors compactly in the strict lower part of R
* (below diagonal).
* - returns taus[] (one per reflector).
* @param A
* @returns
*/
static readonly geqr2: (A: MultiArray) => {
R: MultiArray;
taus: ComplexType[];
phis: ComplexType[];
};
/**
* QR factorization with column pivoting (GEQP2 equivalent).
* A is overwritten with:
* - Householder vectors in the lower trapezoid
* - R in the upper triangle
*
* Returns:
* R : MultiArray containing Householder vectors + R
* taus: Householder scalars
* jpvt: column permutation vector
*/
static readonly geqp2: (A: MultiArray) => {
R: MultiArray;
taus: ComplexType[];
phis: ComplexType[];
jpvt: number[];
};
/**
* Computes the QR factorization of a real or complex matrix A with
* column pivoting, using Householder reflectors (LAPACK-style GEQP3).
*
* Given an m-by-n matrix A, this routine computes a factorization
*
* `A * P = Q * R`
*
* where:
* - `Q` is an m-by-m unitary/orthogonal matrix represented implicitly
* by a sequence of Householder reflectors defined by the vectors
* stored in the lower trapezoid of R and the scalar factors `taus`;
*
* - `R` is the m-by-n upper-triangular (or upper-trapezoidal) factor
* returned explicitly in the output array;
*
* - `P` is an n-by-n permutation matrix encoded by the pivot array `jpvt`,
* representing the reordering of columns chosen via column pivoting;
*
* - `taus[k]` is the scalar coefficient of the k-th Householder
* reflector `Hₖ = I − τ v vᴴ`, where `v` is stored in column `k` of the
* modified `A` matrix (now part of `R`);
*
* - `phis[k]` corresponds to the signed norm (or “alpha”) returned by
* the Householder generator for the k-th reflector, matching LAPACK’s
* internal convention for reconstructing the reflector explicitly.
*
* The routine follows the numerical strategy of xGEQP3 in LAPACK:
* - Computes initial column norms;
* - Uses partial column norm downdating to avoid recomputation;
* - Selects pivot columns based on remaining norms;
* - Applies Householder reflectors to update the trailing matrix.
*
* @param A The input matrix (real or complex), given as a `MultiArray`.
* It is overwritten in-place with the `R` factor and the
* Householder vectors in its lower trapezoid.
* @returns An object containing:
* - `R`: The resulting `R` factor (with embedded Householder vectors).
* - `taus`: The array of Householder scalar factors τₖ.
* - `phis`: The signed norm/alpha values for each step of the factorization.
* - `jpvt`: The pivot array encoding the column permutation matrix `P`.
*/
static readonly geqp3: (A: MultiArray) => {
R: MultiArray;
taus: ComplexType[];
phis: ComplexType[];
jpvt: number[];
};
/**
* ## `LAPACK.orgqr`
* Construct `Q` explicitly from `R` (with MATLAB/Octave-style storage
* `tau*v` in subdiagonal) and `taus[]` produced by `LAPACK.geqr2`.
* We reconstruct each `v` from `R` (`v[0]=1`, `v[1..]` from `R[k+1..,k]`) then
* apply `Q := Q * H^H` using accumulation. Adapted to row-major
* MultiArray and using `LAPACK.larf_left` for left application.
*
* IMPORTANT: loop in reverse order (`kMax-1` downto `0`) applying `H = I - tau * v * v^H` to match LAPACK
* ZUNGQR semantics.
* @param R
* @param taus
* @returns Q matrix
*/
static readonly orgqr: (R: MultiArray, taus: ComplexType[]) => MultiArray;
/**
* Unblocked LU factorization (panel) - modifies A in place.
* A is m x n stored as MultiArray (row-major physical layout).
* Performs LU on A[k..m-1, k..n-1] and writes pivots into piv starting at offset k.
* Returns number of pivots performed (panel width) or info.
*
* This is analogous to LAPACK's xGETF2 applied to the submatrix.
*
* This routine will update A in-place (compact LU) and fill piv[k..k+panelWidth-1].
*
* @param A MultiArray (m x n)
* @param k starting column/row index for panel
* @param panelWidth number of columns to factor (<= min(m-k, n-k))
* @param piv global pivot array (zero-based), length >= min(m,n)
*/
static readonly getf2: (A: MultiArray, k: number, panelWidth: number, piv: number[]) => void;
/**
* Blocked GETRF for complex matrices (LU with partial pivoting).
* This routine will modify A in-place, writing LU (L below diag, U on and above diag).
* @param A
* @returns { LU: MultiArray (same reference as input A, modified), piv: number[], swaps: number }
*/
static readonly getrf: (A: MultiArray) => {
LU: MultiArray;
piv: number[];
swaps: number;
};
/**
* Unblocked panel factorization for columns k .. k+panelWidth-1.
* Writes pivots into piv (global, zero-based) for indices i=k..k+panelWidth-1.
* @param A MultiArray (modified in-place)
* @param k
* @param panelWidth
* @param piv number[] (length >= min(m,n)), receives zero-based pivot row indices
* @param swapsObj { swaps: number } (accumulates swaps)
* @param infoObj { info: number } (LAPACK-style 1-based info)
*/
static readonly getf2_unblocked: (A: MultiArray, k: number, panelWidth: number, piv: number[], swapsObj: {
swaps: number;
}, infoObj: {
info: number;
}) => void;
/**
* Compute A22 := A22 - A21 * A12 (standard update in GETRF).
* All indices are absolute within A.array.
* A21: rows (k+kb .. m-1) x cols (k .. k+kb-1)
* A12: rows (k .. k+kb-1) x cols (k+kb .. n-1)
* A22: rows (k+kb .. m-1) x cols (k+kb .. n-1)
* @param A
* @param k
* @param kb
* @param blockSizeInner
*/
static readonly gemm_blocked: (A: MultiArray, k: number, kb: number, blockSizeInner?: number) => void;
/**
* Blocked LU factorization that calls getf2_unblocked for panel factorization,
* then solves and updates the trailing submatrix.
* @param A
* @returns Object { LU: A, piv, info, swaps }
*/
static readonly getrf_blocked: (A: MultiArray) => {
LU: MultiArray;
piv: number[];
info: number;
swaps: number;
};
/**
* Solve systems A X = B given LU factorization in-place and pivots.
* This follows LAPACK GETRS semantics (no transpose).
* @param LU MultiArray containing LU as returned by getrf
* @param piv pivot vector (zero-based) length = min(m,n)
* @param B MultiArray of size m x nrhs (modified in place)
* @returns new MultiArray (`B`) with solution
*/
static readonly getrs: (LU: MultiArray, piv: number[], B: MultiArray) => MultiArray;
static functions: {
[F in keyof LAPACK]: Function;
};
}
export type { ElementType };
export { LAPACK };
declare const _default: {
LAPACK: typeof LAPACK;
};
export default _default;