mathjslab
Version:
MathJSLab - An interpreter with language syntax like MATLAB®/Octave, ISBN 978-65-00-82338-7.
676 lines (675 loc) • 27 kB
TypeScript
import { type ComplexType } from './Complex';
import { CharString } from './CharString';
import { type ElementType, MultiArray } from './MultiArray';
import { type BuiltInFunctionSignature, type NodeReturnList, type FunctionSignatureEntry } from './AST';
/**
* Runtime configuration for higher-level linear algebra algorithms.
*/
type LinearAlgebraConfig = {
/**
* Numerical tolerance used to treat small LU pivots/residuals as zero.
*/
wasteLU: number;
/**
* Small phase-normalization threshold used by QR/LQ decompositions.
*/
qrPhaseEpsilon: number;
};
type CrossDimensionArgument = ElementType | number;
/** Public list of accepted `LinearAlgebra.set` configuration keys. */
export declare const LinearAlgebraConfigKeyTable: (keyof LinearAlgebraConfig)[];
/**
* # LinearAlgebra
*
* MATLAB/Octave-facing linear algebra built-ins and decomposition helpers.
*
* This layer adapts `MultiArray` values to the lower-level BLAS/LAPACK-style
* routines and publishes built-in signature metadata used by interpreter call
* validation. Keep public methods aligned with MATLAB/Octave behavior first;
* internal helper methods may expose more algorithm-specific shapes.
*
* ## References
*
* * [Linear Algebra at Wolfram MathWorld](https://mathworld.wolfram.com/LinearAlgebra.html)
* * [Fundamental Theorem of Linear Algebra at Wolfram MathWorld](https://mathworld.wolfram.com/FundamentalTheoremofLinearAlgebra.html)
* * [Linear algebra at Wikipedia](https://en.wikipedia.org/wiki/Linear_algebra)
*/
declare abstract class LinearAlgebra {
/**
* Immutable snapshot of default linear-algebra settings.
*/
static readonly defaultSettings: LinearAlgebraConfig;
/**
* Mutable current linear-algebra settings.
*/
static readonly settings: LinearAlgebraConfig;
/**
* Update linear-algebra runtime configuration.
*
* @param config Partial configuration object.
* @throws Error when a configuration key is unknown.
*/
static readonly set: (config: Partial<LinearAlgebraConfig>) => void;
/**
* Signature metadata for the MATLAB/Octave `eye` built-in.
*/
static readonly eyeSignature: BuiltInFunctionSignature;
/**
* Create an identity matrix or scalar identity value.
*
* Supported forms mirror MATLAB/Octave: `eye()`, `eye(n)`, `eye([m n])`,
* and `eye(m, n)`.
*
* @param args
* Dimension arguments.
* @returns Identity scalar or matrix.
*/
static readonly eye: (...args: MultiArray[] | ComplexType[]) => MultiArray | ComplexType;
/**
* Signature metadata for the MATLAB/Octave `diag` built-in.
*/
static readonly diagSignature: BuiltInFunctionSignature;
/**
* Extract a diagonal vector from a matrix or create a diagonal matrix from
* a vector/scalar.
*
* The one- and two-argument forms follow MATLAB/Octave `diag`; the
* three-argument form creates an explicit `m` by `n` diagonal matrix.
*
* @param args Value, optional offset, and optional explicit dimensions.
* @returns Diagonal vector or matrix.
*/
static readonly diag: (...args: MultiArray[] | ComplexType[]) => MultiArray;
static readonly traceSignature: BuiltInFunctionSignature;
/**
* Sum of diagonal elements.
* @param M Matrix.
* @returns Trace of matrix.
*/
static readonly trace: (M: MultiArray) => ComplexType;
/**
* Transpose and apply function.
* @param M Matrix.
* @returns Transpose matrix with `func` applied to each element.
*/
private static readonly applyTranspose;
/**
* Transpose each two-dimensional page of an array, preserving higher
* dimensions.
*
* `MultiArray` stores pages stacked in the physical row axis. This helper
* therefore maps through the canonical logical subscript translators
* instead of assuming that a page is contiguous in ordinary row-major
* storage.
*
* @param M Input array.
* @param func Optional element transform applied after page transposition.
* @returns Array with the first two dimensions swapped.
*/
private static readonly applyPageTranspose;
static readonly transposeSignature: BuiltInFunctionSignature;
/**
* Transpose scalar, character, or matrix values.
* @param M Value to transpose.
* @returns Transposed value.
*/
static readonly transpose: <T extends ElementType>(M: T) => T extends CharString ? MultiArray : T;
static readonly ctransposeSignature: BuiltInFunctionSignature;
/**
* Complex conjugate transpose scalar, character, or matrix values.
* @param M Value to conjugate-transpose.
* @returns Complex conjugate transpose value.
*/
static readonly ctranspose: <T extends ElementType>(M: T) => T extends CharString ? MultiArray : T;
static readonly pagetransposeSignature: BuiltInFunctionSignature;
/**
* Page-wise nonconjugate transpose.
*
* MATLAB defines this as `permute(X,[2 1 3:ndims(X)])`.
*
* @param M Value to transpose page-wise.
* @returns Page-wise transposed value.
*/
static readonly pagetranspose: <T extends ElementType>(M: T) => T extends CharString ? MultiArray : T;
static readonly pagectransposeSignature: BuiltInFunctionSignature;
/**
* Page-wise complex conjugate transpose.
*
* MATLAB defines this as `permute(conj(X),[2 1 3:ndims(X)])`.
*
* @param M Value to conjugate-transpose page-wise.
* @returns Page-wise conjugate-transposed value.
*/
static readonly pagectranspose: <T extends ElementType>(M: T) => T extends CharString ? MultiArray : T;
static readonly pagemtimesSignature: BuiltInFunctionSignature;
/**
* Parse a page-wise multiplication transposition option.
*
* @param option Option value.
* @returns Normalized transposition option.
*/
private static readonly pageTransposeOption;
/**
* Normalize a numeric page-wise multiplication input.
*
* @param value Input scalar or array.
* @returns Dense numeric array representation.
*/
private static readonly pageNumericArray;
/**
* Apply a page-wise transposition option to an array.
*
* @param value Input array.
* @param option Transposition option.
* @returns Transformed array.
*/
private static readonly applyPageTransposeOption;
/**
* Read one element from a logical page.
*
* @param value Source array.
* @param dimensions Padded source dimensions.
* @param row One-based row subscript.
* @param column One-based column subscript.
* @param pageSubscript One-based subscripts for dimensions three and above.
* @returns Numeric element.
*/
private static readonly pageElement;
/**
* Extract a two-dimensional matrix page from an N-D array.
*
* @param value Source array.
* @param dimensions Padded source dimensions.
* @param pageSubscript One-based subscripts for dimensions three and above.
* @returns Dense matrix containing the requested page.
*/
private static readonly pageMatrix;
/**
* Store a two-dimensional matrix page in an N-D result array.
*
* @param target Target array.
* @param pageSubscript One-based subscripts for dimensions three and above.
* @param page Page matrix.
*/
private static readonly setPageMatrix;
/**
* Compute singleton-expanded page dimensions for two page-wise operands.
*
* @param functionName Function name used in diagnostics.
* @param leftDimensions Padded left operand dimensions.
* @param rightDimensions Padded right operand dimensions.
* @param pageRank Common padded rank.
* @returns Broadcast page dimensions.
*/
private static readonly pageBroadcastDimensions;
/**
* Page-wise matrix multiplication with singleton expansion over page
* dimensions.
*
* @param args `pagemtimes(X,Y)` or `pagemtimes(X,transpX,Y,transpY)`.
* @returns Page-wise matrix product.
*/
static readonly pagemtimes: (...args: ElementType[]) => ElementType;
static readonly pageinvSignature: BuiltInFunctionSignature;
/**
* Page-wise matrix inverse.
*
* MATLAB defines each output page as `Y(:,:,i,...) = inv(X(:,:,i,...))`.
*
* @param X Numeric matrix or N-D array whose pages are square matrices.
* @returns Page-wise inverse array.
*/
static readonly pageinvValue: (X: ElementType) => ElementType;
/**
* Estimate one reciprocal condition value for each matrix page.
*
* Square pages use `rcond`; rectangular pages use the reciprocal of the
* default dense `cond` estimate. Both produce the MATLAB-style `1x1` page
* result shape.
*
* @param functionName Function name used in diagnostics.
* @param source Source array.
* @param dimensions Padded source dimensions.
* @returns Reciprocal condition numbers, one scalar per matrix page.
*/
private static readonly pageReciprocalCondition;
/**
* Page-wise matrix inverse with optional reciprocal condition numbers.
*
* @param X Numeric matrix or N-D array whose pages are square matrices.
* @returns Lazy return list for `Y` and optional `RC`.
*/
static readonly pageinv: (X: ElementType) => NodeReturnList;
static readonly pagemldivideSignature: BuiltInFunctionSignature;
static readonly pagemrdivideSignature: BuiltInFunctionSignature;
/**
* Apply a binary page-wise matrix solver with singleton page expansion.
*
* @param functionName Function name used in diagnostics.
* @param left Left operand.
* @param right Right operand.
* @param solve Per-page solver.
* @returns Page-wise solver output.
*/
private static readonly pageMatrixBinarySolveValue;
/**
* Page-wise left matrix division.
*
* @param args `pagemldivide(A,B)` or `pagemldivide(A,transpA,B)`.
* @returns Page-wise solution for `A(:,:,i,...) \ B(:,:,i,...)`.
*/
static readonly pagemldivideValue: (...args: ElementType[]) => ElementType;
/**
* Page-wise left matrix division with optional reciprocal condition numbers.
*
* @param args `pagemldivide(A,B)` or `pagemldivide(A,transpA,B)`.
* @returns Lazy return list for `X` and optional `rcondA`.
*/
static readonly pagemldivide: (...args: ElementType[]) => NodeReturnList;
/**
* Page-wise right matrix division.
*
* @param args `pagemrdivide(B,A)` or `pagemrdivide(B,A,transpA)`.
* @returns Page-wise solution for `B(:,:,i,...) / A(:,:,i,...)`.
*/
static readonly pagemrdivideValue: (...args: ElementType[]) => ElementType;
/**
* Page-wise right matrix division with optional reciprocal condition numbers.
*
* @param args `pagemrdivide(B,A)` or `pagemrdivide(B,A,transpA)`.
* @returns Lazy return list for `X` and optional `rcondA`.
*/
static readonly pagemrdivide: (...args: ElementType[]) => NodeReturnList;
static readonly mulSignature: BuiltInFunctionSignature;
/**
* Matrix product.
* @param left Matrix.
* @param right Matrix.
* @returns left * right.
*/
static mul(left: MultiArray, right: MultiArray): MultiArray;
static readonly powerSignature: BuiltInFunctionSignature;
private static readonly multiplyMatrices;
private static readonly formatDimensions;
private static readonly hermitianEigenExpansion;
/**
* Matrix power for square matrices and scalar exponents.
*
* MATLAB/Octave-compatible integer powers are computed through
* exponentiation by squaring. Non-integer scalar exponents currently use
* the Hermitian/symmetric eigenvalue expansion supported by the numerical
* backend.
*
* @param left Square matrix base.
* @param right Integer real scalar exponent.
* @returns Matrix power result.
*/
static readonly power: (left: MultiArray, right: ComplexType) => MultiArray;
/**
* Scalar base raised to a Hermitian/symmetric matrix exponent.
*
* MATLAB/Octave define `a^B` for scalar `a` and square matrix `B` through
* an eigenvalue expansion. The current numerical backend exposes a
* Hermitian/symmetric eigensolver, so this method intentionally accepts
* that well-conditioned subset and rejects general square matrices until a
* general eigensolver or Schur path is available.
*
* @param left Scalar base.
* @param right Hermitian/symmetric matrix exponent.
* @returns Matrix result `V * diag(left .^ lambda) * V'`.
*/
static readonly scalarPower: (left: ComplexType, right: MultiArray) => MultiArray;
static readonly detSignature: BuiltInFunctionSignature;
/**
* Matrix determinant using LU decomposition with pivot sign correction.
* Uses `LinearAlgebra.luDecomposition`.
* @param M Matrix.
* @returns Matrix determinant.
*/
static readonly det: (M: MultiArray) => ComplexType;
/**
* Computes the LU decomposition with partial pivoting.
* @param M Input square matrix.
* @returns An object { L, U, P, swaps } where:
* - L: lower-triangular with unit diagonal (MultiArray)
* - U: upper-triangular (MultiArray)
* - P: permutation matrix (MultiArray)
* - swaps: number of row swaps performed (integer)
*
* ## References
* * https://www.codeproject.com/Articles/1203224/A-Note-on-PA-equals-LU-in-Javascript
* * https://rosettacode.org/wiki/LU_decomposition#JavaScript
*/
static readonly luDecomposition: (A: MultiArray) => {
L: MultiArray;
U: MultiArray;
P: MultiArray;
swaps: number;
};
static readonly luSignature: BuiltInFunctionSignature;
/**
* PLU matrix factorization.
* @param M Matrix.
* @returns L, U and P matrices as multiple output.
*/
static readonly lu: (M: MultiArray) => NodeReturnList;
static readonly invSignature: BuiltInFunctionSignature;
/**
* Returns the inverse of matrix `M`.
* inv(A) wrapper using LAPACK.getrf_blocked + LAPACK.getrs.
* Behavior: MATLAB-like: if factorization reports info !== 0, emit warning and return matrix filled with Inf.
* @param M Matrix.
* @returns Inverted matrix.
*/
static readonly inv: (A: MultiArray) => MultiArray;
static readonly condSignature: BuiltInFunctionSignature;
/**
* Matrix condition number for inversion.
*
* The default and `p = 2` forms use the singular value ratio. The
* remaining MATLAB-compatible orders use `norm(A, p) * norm(inv(A), p)`.
*
* @param A Input matrix.
* @param normType Optional norm type: `1`, `2`, `Inf`, or `'fro'`.
* @returns Scalar condition number.
*/
static readonly cond: (A: MultiArray, normType?: ComplexType | CharString) => ComplexType;
static readonly rcondSignature: BuiltInFunctionSignature;
/**
* Estimate reciprocal condition number in the 1-norm.
*
* This follows the public MATLAB/Octave contract of `rcond(A)`. The
* current implementation derives the estimate from the deterministic dense
* `cond(A,1)` path used elsewhere in this layer.
*
* @param A Square numeric matrix.
* @returns Reciprocal condition estimate.
*/
static readonly rcond: (A: MultiArray) => ComplexType;
static readonly rankSignature: BuiltInFunctionSignature;
/**
* Numerical matrix rank estimated from singular values.
*
* MATLAB defines the default tolerance as `max(size(A)) * eps(norm(A))`
* and counts singular values strictly larger than the tolerance.
*
* @param A Input matrix.
* @param tolerance Optional singular-value tolerance.
* @returns Rank as a scalar double value.
*/
static readonly rank: (A: MultiArray, tolerance?: ComplexType) => ComplexType;
/**
* Condition number through a matrix norm and inverse.
*
* @param A Input matrix.
* @param normType Matrix norm type.
* @returns `norm(A, p) * norm(inv(A), p)`.
*/
private static readonly squareMatrixNormCondition;
/**
* Matrix norm subset required by condition-number computation.
*
* @param matrix Input matrix.
* @param normType Norm type.
* @returns Requested matrix norm.
*/
private static readonly matrixNorm;
/**
* Compute squared singular values through the smaller Gram matrix.
*
* @param A Input matrix.
* @returns Sorted nonnegative squared singular values.
*/
private static readonly singularValuesSquared;
/**
* Compute singular values in ascending order.
*
* @param A Input matrix.
* @returns Sorted nonnegative singular values.
*/
private static readonly singularValues;
/**
* Estimate rank by Gaussian elimination with partial pivoting.
*
* This uses the MATLAB-compatible tolerance computed by `rank` but avoids
* deciding exact dependencies through the squared condition of `A' * A`.
*
* @param A Input matrix.
* @param tolerance Pivot tolerance.
* @returns Estimated rank.
*/
private static readonly rankByElimination;
/**
* Extract a dense two-dimensional block from a matrix.
*
* @param source Source matrix.
* @param rowStart First source row.
* @param columnStart First source column.
* @param rows Number of rows to copy.
* @param columns Number of columns to copy.
* @returns Copied matrix block.
*/
private static readonly matrixBlock;
/**
* Solve an upper-triangular square system by back substitution.
*
* @param upper Upper-triangular coefficient matrix.
* @param rightHandSide Right-hand side matrix.
* @param operatorName Operator used in diagnostics.
* @returns Solution matrix.
*/
private static readonly solveUpperTriangular;
/**
* Solve a lower-triangular square system by forward substitution.
*
* @param lower Lower-triangular coefficient matrix.
* @param rightHandSide Right-hand side matrix.
* @param operatorName Operator used in diagnostics.
* @returns Solution matrix.
*/
private static readonly solveLowerTriangular;
/**
* Solve a tall rectangular least-squares system through QR factorization.
*
* @param A Full-column-rank coefficient matrix with rows >= columns.
* @param B Right-hand side matrix.
* @returns Least-squares solution.
*/
private static readonly tallLeastSquares;
/**
* Solve a wide rectangular system through LQ factorization.
*
* @param A Full-row-rank coefficient matrix with rows < columns.
* @param B Right-hand side matrix.
* @returns Minimum-norm solution.
*/
private static readonly wideLeastSquares;
/**
* Matrix left division wrapper for the language-level `\` operator.
*
* This keeps parser/interpreter arithmetic routed through the
* MATLAB/Octave-facing linear algebra layer while `LAPACK` remains the
* numerical backend.
*
* @param A Coefficient matrix.
* @param B Right-hand side matrix.
* @returns Solution matrix `X` for `A * X = B`.
*/
static readonly mldivide: (A: MultiArray, B: MultiArray) => MultiArray;
/**
* Matrix right division wrapper for the language-level `/` operator.
*
* Implements `A / B` through the MATLAB/Octave identity
* `((B') \ (A'))'`, routing the actual solve through `mldivide`.
*
* @param A Numerator matrix.
* @param B Denominator matrix.
* @returns Solution matrix `X` for `X * B = A`.
*/
static readonly mrdivide: (A: MultiArray, B: MultiArray) => MultiArray;
static readonly gaussSignature: BuiltInFunctionSignature;
/**
* Gaussian elimination algorithm for solving systems of linear equations.
* Adapted from: https://github.com/itsravenous/gaussian-elimination
* ## References
* * https://mathworld.wolfram.com/GaussianElimination.html
* @param M Matrix.
* @param m Vector.
* @returns Solution of linear system.
*/
static readonly gauss: (M: MultiArray, m: MultiArray) => MultiArray;
static readonly dotSignature: BuiltInFunctionSignature;
/**
* High-performance dot product. Fully ND-aware, column-major, no index
* conversions (≈2-3× faster). Computes sum(conj(A).*B, dim) with minimal
* per-element overhead.
* C = dot(A,B) or C = dot(A,B,dim)
* Sums conj(A).*B along the specified dimension (zero-based operateDim). If dim is omitted,
* use the first non-singleton dimension (zero-based).
* @param A First array (MultiArray).
* @param B Second array (MultiArray).
* @param dim (optional) Dimension along which to operate (ComplexType representing integer, 1-based externally).
* @returns Scalar (ComplexType) if result is single value, else a MultiArray.
*/
static readonly dot: (A: MultiArray, B: MultiArray, dim?: ComplexType) => MultiArray | ComplexType;
static readonly crossSignature: BuiltInFunctionSignature;
private static readonly dimensionArgumentToNumber;
/**
* Cross product along dimension `dim` (MATLAB semantics).
* A and B must have the same size except along `dim` where size must be 3.
* dim is optional and is 1-based like MATLAB; internally converted to 0-based.
* @param A
* @param B
* @param dim
* @returns
*/
static readonly cross: (A: MultiArray, B: MultiArray, dim?: CrossDimensionArgument) => MultiArray;
static readonly kronSignature: BuiltInFunctionSignature;
/**
*
* @param A
* @param B
* @returns
*/
static readonly kron: (A: ElementType, B: ElementType) => MultiArray;
/**
* Normalize phases so that R diagonal becomes real non-negative:
* For k = 0..minmn-1:
* phi = R[k][k] / |R[k][k]|
* R[k, j] := R[k, j] / phi (j = k..n-1)
* Q[i, k] := Q[i, k] * phi (i = 0..m-1)
* @param Q
* @param R
* @param phis
*/
static readonly qrPhaseNormalize: (phis: ComplexType[], R: MultiArray, Q?: MultiArray) => void;
/**
* Normalize LQ Householder phases in place.
*
* `phis` must come from the same LQ factorization that produced `L`.
* When `Q` is supplied, the inverse phase adjustment is applied there so
* the product represented by the factorization is preserved.
*
* @param phis Phase factors produced during LQ factorization.
* @param L Lower/trapezoidal factor to normalize.
* @param Q Optional unitary/orthogonal factor to update consistently.
*/
static readonly lqPhaseNormalize: (phis: ComplexType[], L: MultiArray, Q?: MultiArray) => void;
/**
*
* @param A
* @param result
* @returns
*/
static readonly qrDecomposition: (A: MultiArray, result: 1 | 2 | 3) => {
Q?: MultiArray;
R: MultiArray;
P?: MultiArray;
};
static readonly qrSignature: BuiltInFunctionSignature;
/**
*
* @param M
* @returns
*/
static readonly qr: (M: MultiArray) => NodeReturnList;
/**
* eigDecomposition - wrapper that performs eigen decomposition using blocked tridiagonalization.
*
* Returns object depending on `result`:
* 1 -> { values: MultiArray } (column vector n x 1)
* 2 -> { values: MultiArray, vectors: MultiArray } (vector columns are eigenvectors)
* 3 -> { values: MultiArray, vectors: MultiArray, T: MultiArray } (T = tridiagonal matrix)
*
* Uses:
* - LAPACK.sytrd_blocked_w(Acopy, nb) -> { diag: ComplexType[], offdiag: ComplexType[], taus: ComplexType[] }
* - LAPACK.steqr_values(diag, offdiag) -> ComplexType[]
* - LAPACK.steqr_vectors(diag, offdiag) -> { D: ComplexType[], V: MultiArray }
* - LAPACK.orgtr_blocked_w(Acopy, taus, nb) -> MultiArray Q0
* - BLAS.gemm_block(Q0, Z, Vout, Complex.one(), Complex.zero(), nb)
*/
/**
* eigDecomposition - updated to use steqr_values/steqr_vectors returning MultiArray
*
* Returns:
* result === 1 -> { values: MultiArray }
* result === 2 -> { values: MultiArray, vectors: MultiArray }
* result === 3 -> { values: MultiArray, vectors: MultiArray, T: MultiArray }
*/
static readonly eigDecomposition_original: (A: MultiArray, result: 1 | 2 | 3, nb?: number, order?: "asc" | "desc" | "none") => {
values: MultiArray;
vectors?: MultiArray;
T?: MultiArray;
};
/**
* Compute a Hermitian/symmetric eigenvalue decomposition.
*
* The `result` selector mirrors MATLAB/Octave output arity: `1` computes
* eigenvalues only, `2` computes eigenvectors and eigenvalues, and `3` also
* exposes the tridiagonal intermediate matrix for diagnostics.
*
* @param A Square Hermitian/symmetric input matrix.
* @param result Requested output shape.
* @param order Eigenvalue ordering policy.
* @param blockSize Optional block size for blocked tridiagonalization.
* @returns Decomposition result with fields determined by `result`.
*/
static readonly eigDecomposition: (A: MultiArray, result: 1 | 2 | 3, order?: "asc" | "desc" | "none", blockSize?: number) => {
values: MultiArray;
vectors?: MultiArray;
T?: MultiArray;
};
static readonly eigSignature: BuiltInFunctionSignature;
/**
* MATLAB/Octave-style wrapper for `eig`.
*
* The returned `NodeReturnList` delays the actual decomposition until the
* caller asks for a specific number of outputs. One output returns the
* eigenvalues, two outputs return `[V, D]`, and three outputs return
* `[V, D, T]` where `T` is the tridiagonal intermediate used for
* diagnostics.
*/
static eig: (M: MultiArray) => NodeReturnList;
static readonly testSignature: BuiltInFunctionSignature;
/**
* Small return-list fixture used by tests of multiple-output plumbing.
*
* The argument is intentionally unused; it keeps the signature parallel to
* runtime helpers that receive a matrix before building a lazy return list.
*
* @param A Matrix argument kept for call-shape compatibility.
* @returns A lazy return list with deterministic placeholder values.
*/
static test(A: MultiArray): NodeReturnList;
/**
* LinearAlgebra functions.
*/
static readonly functions: {
[F in keyof LinearAlgebra | string]: FunctionSignatureEntry;
};
}
export { LinearAlgebra };
declare const _default: {
LinearAlgebra: typeof LinearAlgebra;
};
export default _default;