Skip to content

deepbox/linalg

Properties & Matrix Functions

Inverses, determinants, norms, rank, matrix functions such as expm, and special matrix constructors.

  • Matrix functions

Overview

  • inv reports a matrix as singular only when a pivot is exactly zero, as NumPy does. A matrix that is singular up to rounding returns very large entries instead of throwing. Check cond(a) or matrixRank(a) first, or use pinv.
  • det, norm, cond and matrixRank return JavaScript numbers. trace and slogdet return tensors. norm(x, ord) accepts numeric orders, "fro" and "nuc".
  • expm, logm, sqrtm and matrixPower take square 2-D matrices and return float64. kron and blockDiag combine matrices. The constructors (hilbert, hadamard, toeplitz, vandermonde, circulant, companion, hankel) take plain numbers and arrays rather than tensors.
  • matrix_power and block_diag are deprecated aliases of matrixPower and blockDiag.

Functions

21

inv

function inv(a: Tensor): Tensor;

Compute the inverse of a matrix.

Finds matrix A^(-1) such that A * A^(-1) = I.

Parameters:

Parameters

a
Tensor
Square matrix of shape (N, N) Returns: Inverse matrix Requirements: - Matrix must be square - Matrix must be non-singular (det(A) ≠ 0) Numerical singularity: as in NumPy, only an exactly zero pivot is reported as singular. A matrix that is singular up to rounding error, such as [[1, 2, 3], [4, 5, 6], [7, 8, 9]], returns very large entries instead of throwing. Check cond(a) or matrixRank(a) first when the input may be rank deficient, or use pinv. Properties: - A * inv(A) = I - inv(inv(A)) = A - inv(AB) = inv(B) * inv(A)

Returns

Tensor

Throws

  • ShapeErrorIf matrix is not square or not 2D
  • DTypeErrorIf input has string or complex dtype
  • DataValidationErrorIf matrix is singular or contains non-finite values
Example
import { inv } from 'deepbox/linalg';import { tensor, matmul } from 'deepbox/ndarray'; const A = tensor([[1, 2], [3, 4]]);const Ainv = inv(A); // Verify: A * A^(-1) ≈ Iconst I = matmul(A, Ainv);

pinv

function pinv(a: Tensor, rcond?: number): Tensor;

Compute the Moore-Penrose pseudo-inverse.

Generalization of matrix inverse for non-square or singular matrices.

Parameters:

Parameters

a
Tensor
Input matrix of shape (M, N)
rcondoptional
number
Cutoff for small singular values, relative to the largest one. Defaults to max(M, N) * machine epsilon, as in NumPy 2.x. Returns: Pseudo-inverse of shape (N, M) Properties: - A * pinv(A) * A = A - pinv(A) * A * pinv(A) = pinv(A) - For full rank square matrix: pinv(A) = inv(A) - For overdetermined system: pinv(A) gives least squares solution Algorithm: Using SVD A = U * Σ * V^T pinv(A) = V * Σ^+ * U^T where Σ^+ is pseudo-inverse of Σ (1/s_i for s_i > rcond * s_max, else 0)

Returns

Tensor

Throws

  • ShapeErrorIf input is not 2D matrix
  • DTypeErrorIf input has string or complex dtype
  • InvalidParameterErrorIf rcond is negative or non-finite
  • DataValidationErrorIf input contains non-finite values (NaN, Infinity)
Example
import { pinv } from 'deepbox/linalg';import { tensor } from 'deepbox/ndarray'; // Non-square matrixconst A = tensor([[1, 2], [3, 4], [5, 6]]);const Apinv = pinv(A); console.log(Apinv.shape);  // [2, 3]

blockDiag

function blockDiag(...matrices: Tensor[]): Tensor;

Construct a block-diagonal matrix from the provided 2-D matrices.

The blocks need not be square: for blocks of shape (r_i, c_i) the result has shape (sum r_i, sum c_i) and zeros outside the blocks. With no arguments an empty (0, 0) matrix is returned. The result is float64.

Parameters

matrices
Tensor[]
One or more 2-D tensors to place along the diagonal

Returns

TensorBlock-diagonal matrix

Throws

  • ShapeErrorIf any input is not 2-D
  • DTypeErrorIf any input has string or complex dtype
Example
import { blockDiag } from 'deepbox/linalg';import { tensor } from 'deepbox/ndarray'; const A = tensor([[1, 2], [3, 4]]);const B = tensor([[5]]);const D = blockDiag(A, B); // shape [3, 3]

circulant

function circulant(c: number[]): Tensor;

Create a circulant matrix from a vector.

C[i,j] = c[(i - j) mod n], so c is the first column and every column is a cyclic shift of the previous one.

Parameters

c
number[]
First column of the circulant matrix

Returns

TensorCirculant matrix of shape (n, n)

Throws

  • InvalidParameterErrorIf c is empty

companion

function companion(c: number[]): Tensor;

Create a companion matrix from polynomial coefficients.

The companion matrix of the polynomial p(x) = c[0]*x^n + c[1]*x^(n-1) + ... + c[n] is the n×n matrix with -c[1..n]/c[0] in the first row and ones on the sub-diagonal (the convention of scipy.linalg.companion). Its eigenvalues are the roots of p.

Parameters

c
number[]
Polynomial coefficients (leading coefficient first), length >= 2

Returns

TensorCompanion matrix of shape (c.length - 1, c.length - 1)

Throws

  • InvalidParameterErrorIf c has fewer than 2 elements or c[0] is zero or not finite
Example
import { companion } from 'deepbox/linalg'; companion([1, -10, 31, -30]); // [[10, -31, 30], [1, 0, 0], [0, 1, 0]]

expm

function expm(A: Tensor): Tensor;

Compute the matrix exponential exp(A).

Uses scaling and squaring with a degree-6 Padé approximant, so it also works for defective matrices and matrices with complex eigenvalues (for example a rotation generator). The result is float64.

Parameters

A
Tensor
Square matrix

Returns

Tensorexp(A)

Throws

  • ShapeErrorIf A is not a square 2-D matrix
  • DTypeErrorIf A has string or complex dtype
  • DataValidationErrorIf A contains NaN or Infinity
Example
import { expm } from 'deepbox/linalg';import { tensor } from 'deepbox/ndarray'; const A = tensor([[0, 1], [-1, 0]]);const E = expm(A); // [[cos 1, sin 1], [-sin 1, cos 1]]

hadamard

function hadamard(n: number): Tensor;

Create a Hadamard matrix of order n.

n must be a power of 2. Uses Sylvester's construction, so H[i,j] = (-1)^popcount(i & j).

Parameters

n
number
Order of the matrix (must be power of 2)

Returns

TensorHadamard matrix of shape (n, n) with entries +1/-1

Throws

  • InvalidParameterErrorIf n is not a positive power of 2, or is too large to allocate

hankel

function hankel(c: number[], r?: number[]): Tensor;

Create a Hankel matrix from first column and optional last row.

H[i,j] = c[i+j] for i+j < len(c), otherwise r[i+j-len(c)+1]. The first element of r is ignored (the last element of c is used instead), as in scipy.linalg.hankel.

Parameters

c
number[]
First column
roptional
number[]
Last row (optional; defaults to zeros of length c.length)

Returns

TensorHankel matrix of shape (c.length, r.length)

Throws

  • InvalidParameterErrorIf c is empty
Example
import { hankel } from 'deepbox/linalg'; hankel([1, 2, 3]);                // [[1, 2, 3], [2, 3, 0], [3, 0, 0]]hankel([1, 2, 3], [3, 4, 5]);     // [[1, 2, 3], [2, 3, 4], [3, 4, 5]]

hilbert

function hilbert(n: number): Tensor;

Create a Hilbert matrix of size n.

H[i,j] = 1 / (i + j + 1)

Parameters

n
number
Size of the matrix

Returns

TensorHilbert matrix of shape (n, n)

Throws

  • InvalidParameterErrorIf n is not a positive integer

kron

function kron(A: Tensor, B: Tensor): Tensor;

Compute the Kronecker product of two matrices.

If A is (m, n) and B is (p, q), the result is (m*p, n*q). The result is always float64.

Parameters

A
Tensor
First matrix of shape (m, n)
B
Tensor
Second matrix of shape (p, q)

Returns

TensorKronecker product of shape (m*p, n*q)

Throws

  • ShapeErrorIf A or B is not 2-D
  • DTypeErrorIf A or B has string or complex dtype
Example
import { kron } from 'deepbox/linalg';import { tensor } from 'deepbox/ndarray'; const A = tensor([[1, 2], [3, 4]]);const B = tensor([[0, 5], [6, 7]]);const K = kron(A, B); // shape [4, 4]

logm

function logm(A: Tensor): Tensor;

Compute the principal matrix logarithm log(A), the solution L of expm(L) = A whose eigenvalues have imaginary part in (-pi, pi).

Symmetric input is handled through the symmetric eigendecomposition and requires strictly positive eigenvalues. Other input uses inverse scaling and squaring, so defective matrices and matrices with complex eigenvalues work as long as no eigenvalue lies on the closed negative real axis. The result is float64.

Parameters

A
Tensor
Square matrix with no eigenvalues on the closed negative real axis

Returns

Tensorlog(A)

Throws

  • ShapeErrorIf A is not a square 2-D matrix
  • DTypeErrorIf A has string or complex dtype
  • DataValidationErrorIf A contains NaN or Infinity, or has no real principal logarithm (a zero, negative or negative-real-axis eigenvalue)
Example
import { logm, expm } from 'deepbox/linalg';import { tensor } from 'deepbox/ndarray'; const A = tensor([[2, 1], [1, 2]]);const L = logm(A);// expm(L) is A up to rounding

matrixPower

function matrixPower(A: Tensor, n: number): Tensor;

Raise a square matrix to an integer power.

For positive n: computes A^n via repeated squaring. For n=0: returns the identity matrix. For negative n: computes (A^{-1})^{|n|}.

The result is always float64, whatever the dtype of A.

Parameters

A
Tensor
Square matrix of shape (m, m)
n
number
Integer exponent

Returns

TensorA^n of shape (m, m)

Throws

  • ShapeErrorIf A is not a square 2-D matrix
  • InvalidParameterErrorIf n is not an integer
  • DTypeErrorIf A has string or complex dtype
  • DataValidationErrorIf n is negative and A is singular
Example
import { matrixPower } from 'deepbox/linalg';import { tensor } from 'deepbox/ndarray'; const A = tensor([[1, 2], [3, 4]]);const A3 = matrixPower(A, 3); // A * A * A

sqrtm

function sqrtm(A: Tensor): Tensor;

Compute the principal matrix square root sqrt(A), the solution S of S * S = A whose eigenvalues have non-negative real part.

Details

- Symmetric input is handled through the symmetric eigendecomposition. Eigenvalues that are negative only within rounding error (a positive semi-definite matrix) are treated as zero. - Other input uses the Denman-Beavers iteration, so defective matrices and matrices with complex eigenvalues work as long as the result is real. Diagonalisable singular matrices fall back to the eigendecomposition.

The result is float64.

Parameters

A
Tensor
Square matrix with no eigenvalues on the negative real axis

Returns

Tensorsqrt(A)

Throws

  • ShapeErrorIf A is not a square 2-D matrix
  • DTypeErrorIf A has string or complex dtype
  • DataValidationErrorIf A contains NaN or Infinity, or has no real principal square root (for example a negative eigenvalue)
Example
import { sqrtm } from 'deepbox/linalg';import { tensor } from 'deepbox/ndarray'; const S = sqrtm(tensor([[4, 0], [0, 9]])); // [[2, 0], [0, 3]]

toeplitz

function toeplitz(c: number[], r?: number[]): Tensor;

Create a Toeplitz matrix from first column and optional first row.

A Toeplitz matrix has constant diagonals. If only c is given, the result is symmetric. If both c and r are given, c defines the first column and r defines the first row (r[0] is ignored in favor of c[0]).

Parameters

c
number[]
First column
roptional
number[]
First row (optional; defaults to c for symmetric Toeplitz)

Returns

TensorToeplitz matrix of shape (c.length, r.length)

Throws

  • InvalidParameterErrorIf c is empty
Example
import { toeplitz } from 'deepbox/linalg'; toeplitz([1, 2, 3]);              // [[1, 2, 3], [2, 1, 2], [3, 2, 1]]toeplitz([1, 2, 3], [1, 5, 6]);   // [[1, 5, 6], [2, 1, 5], [3, 2, 1]]

vandermonde

function vandermonde(x: number[], N?: number, increasing?: boolean): Tensor;

Create a Vandermonde matrix.

V[i,j] = x[i]^(N-1-j) by default, or V[i,j] = x[i]^j when increasing is true (same convention as numpy.vander).

Parameters

x
number[]
Input vector of length n
Noptional
number
Number of columns (default: n)
increasingoptional
boolean
If true, powers increase left to right

Returns

TensorVandermonde matrix of shape (n, N)

Throws

  • InvalidParameterErrorIf x is empty or N is not a positive integer
Example
import { vandermonde } from 'deepbox/linalg'; vandermonde([1, 2, 3]);              // [[1, 1, 1], [4, 2, 1], [9, 3, 1]]vandermonde([1, 2, 3], 3, true);     // [[1, 1, 1], [1, 2, 4], [1, 3, 9]]

cond

function cond(a: Tensor, p?: number | "fro" | "nuc"): number;

Condition number of a matrix.

Measures how sensitive the solution of A*x=b is to changes in b. Large condition number indicates ill-conditioned matrix.

Formula: cond(A) = ||A|| * ||A^(-1)||

Parameters:

Parameters

a
Tensor
Input matrix of shape (M, N)
poptional
number | "fro" | "nuc"
Norm order, as in numpy.linalg.cond: - undefined or 2: ratio of the largest to the smallest singular value (any M, N) - -2: ratio of the smallest to the largest singular value (any M, N) - 'fro' or 'nuc': Frobenius or nuclear norm of A times that of its (pseudo-)inverse, computed from the singular values (any M, N) - 1, -1, Infinity, -Infinity: matrix norm of A times that of A^(-1) (square A only) Returns: Condition number (>= 1 for p != -2, Infinity for singular matrices). Singular values at or below max(M, N) * eps * largest singular value count as zero, and an empty matrix gives Infinity.

Returns

number

Throws

  • ShapeErrorIf input is not a 2D matrix, or is not square for p in {1, -1, Infinity, -Infinity}
  • DTypeErrorIf input has string or complex dtype
  • DataValidationErrorIf input contains non-finite values (NaN, Infinity)
  • InvalidParameterErrorIf p is unsupported
Example
import { cond } from 'deepbox/linalg';import { tensor } from 'deepbox/ndarray'; cond(tensor([[1, 2], [3, 4]]));      // 14.93... (2-norm)cond(tensor([[1, 2], [3, 4]]), 1);   // 21

norm

function norm(x: Tensor, ord?: number | "fro" | "nuc", axis?: Axis | Axis[], keepdims?: boolean): Tensor | number;

Parameters

x
Tensor
ordoptional
number | "fro" | "nuc"
axisoptional
Axis | Axis[]
keepdimsoptional
boolean

Returns

Tensor | number

det

function det(a: Tensor): number;

Compute the determinant of a matrix.

Uses LU decomposition with partial pivoting for numerical stability. The determinant is computed as: det(A) = pivSign * product(diag(U))

Algorithm: LU decomposition Time Complexity: O(N³) for N×N matrix Space Complexity: O(N²) for LU factorization

Parameters:

Parameters

a
Tensor
Square matrix of shape (N, N) Returns: Determinant value (scalar) Properties: - det(A) = 0 if and only if A is singular (non-invertible) - det(AB) = det(A) * det(B) - det(A^T) = det(A) - det(cA) = c^N * det(A) for scalar c and N×N matrix A - det(I) = 1 for identity matrix

Returns

number

Throws

  • ShapeErrorIf input is not a 2D square matrix
  • DTypeErrorIf input has string or complex dtype
  • DataValidationErrorIf input contains non-finite values (NaN, Infinity)
Example
import { det } from 'deepbox/linalg';import { tensor } from 'deepbox/ndarray'; const A = tensor([[1, 2], [3, 4]]);console.log(det(A));  // -2

matrixRank

function matrixRank(a: Tensor, tol?: number): number;

Compute the rank of a matrix.

Number of linearly independent rows/columns. Uses SVD to count singular values above a threshold.

Algorithm: SVD-based rank computation Time Complexity: O(min(M,N) * M * N) for M×N matrix Space Complexity: O(M*N) for SVD computation

Parameters:

Parameters

a
Tensor
Input matrix of shape (M, N)
toloptional
number
Threshold for small singular values (optional) - Default: max(M,N) * largest_singular_value * machine_epsilon, where the epsilon follows the dtype of a as in NumPy (about 1.2e-7 for float32, 2.2e-16 for float64 and integers) - Singular values > tol are counted as non-zero Returns: Rank (integer between 0 and min(M, N)) Properties: - 0 ≤ rank(A) ≤ min(M, N) - rank(A) = rank(A^T) - rank(A) = number of non-zero singular values - Full rank: rank(A) = min(M, N) - Rank deficient: rank(A) < min(M, N)

Returns

number

Throws

  • ShapeErrorIf input is not a 2D matrix
  • DTypeErrorIf input has string or complex dtype
  • InvalidParameterErrorIf tol is negative or non-finite
  • DataValidationErrorIf input contains non-finite values (NaN, Infinity)
Example
import { matrixRank } from 'deepbox/linalg';import { tensor } from 'deepbox/ndarray'; const A = tensor([[1, 2], [2, 4]]);  // Rank 1 (linearly dependent rows)console.log(matrixRank(A));  // 1 const B = tensor([[1, 0], [0, 1]]);  // Full rankconsole.log(matrixRank(B));  // 2

slogdet

function slogdet(a: Tensor): [ Tensor, Tensor ];

Compute sign and natural logarithm of the determinant.

More numerically stable than det() for large matrices or matrices with very large/small determinants that would overflow/underflow.

Algorithm: LU decomposition Time Complexity: O(N³) Space Complexity: O(N²)

Parameters:

Parameters

a
Tensor
Square matrix Returns: [sign, logdet], both 0-D float64 tensors - sign: +1, -1, or 0 for a singular matrix - logdet: Natural log of |det(A)|, -Infinity if singular (an empty matrix gives [1, 0]) Mathematical Relation: det(A) = sign * exp(logdet) Advantages over det(): - Avoids overflow for large determinants - Avoids underflow for small determinants - More numerically stable for ill-conditioned matrices

Returns

[ Tensor, Tensor ]

Throws

  • ShapeErrorIf input is not a 2D square matrix
  • DTypeErrorIf input has string or complex dtype
  • DataValidationErrorIf input contains non-finite values (NaN, Infinity)
Example
import { slogdet } from 'deepbox/linalg';import { tensor } from 'deepbox/ndarray'; const A = tensor([[1, 2], [3, 4]]);const [sign, logdet] = slogdet(A);// det(A) = sign * exp(logdet)

trace

function trace(a: Tensor, offset?: number, axis1?: Axis, axis2?: Axis): Tensor;

Compute the trace of a matrix.

Sum of diagonal elements. Supports offset diagonals.

Algorithm: Direct summation Time Complexity: O(min(M, N)) where M×N is matrix size Space Complexity: O(1)

Parameters:

Parameters

a
Tensor
Input matrix (at least 2D)
offsetoptional
number
Integer offset from main diagonal: - 0: main diagonal (default) - >0: upper diagonal (k-th diagonal above main) - <0: lower diagonal (k-th diagonal below main)
axis1optional
Axis
First axis to take the diagonal from (default: 0)
axis2optional
Axis
Second axis to take the diagonal from (default: 1) Returns: Trace values as a float64 tensor: shape [1] for a 2-D input, otherwise one value per remaining index (the input shape without axis1 and axis2) Properties: - trace(A) = sum of eigenvalues (for square matrices) - trace(AB) = trace(BA) (cyclic property) - trace(A + B) = trace(A) + trace(B) (linearity) - trace(cA) = c * trace(A) for scalar c - trace(A^T) = trace(A) NaN and Infinity entries on the summed diagonal propagate into the result.

Returns

Tensor

Throws

  • ShapeErrorIf input is not at least 2D
  • InvalidParameterErrorIf axis values are invalid/identical or offset is non-integer
  • DTypeErrorIf input has string or complex dtype
Example
import { trace } from 'deepbox/linalg';import { tensor } from 'deepbox/ndarray'; const A = tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);console.log(trace(A).toArray());  // [15] (1 + 5 + 9)console.log(trace(A, 1).toArray());  // [8] (2 + 6, upper diagonal)console.log(trace(A, -1).toArray());  // [12] (4 + 8, lower diagonal)

Deprecated names

2

These older spellings still work in 1.x. New code should use the names above.

  • block_diagPrefer blockDiag.
  • matrix_powerPrefer matrixPower.
linalg-properties.ts
import {  blockDiag,  cond,  det,  expm,  hadamard,  inv,  matrixPower,  matrixRank,  norm,  pinv,  trace,} from "deepbox/linalg";import { tensor } from "deepbox/ndarray"; const a = tensor([[2, 0], [0, 3]]);console.log(inv(a).toString(), det(a));console.log(norm(a), norm(a, "fro"), trace(a).toString());console.log(cond(a), matrixRank(a));console.log(matrixPower(a, 3).toString());console.log(expm(a).toString());console.log(pinv(tensor([[1, 2], [2, 4]])).toString()); // works for singular inputconsole.log(blockDiag(a, tensor([[1]])).toString());console.log(hadamard(4).toString());