UNPKG

mathjslab

Version:

MathJSLab - An interpreter with language syntax like MATLAB®/Octave, ISBN 978-65-00-82338-7.

510 lines (509 loc) 20.4 kB
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;