Linear algebra
The linear-algebra library holds the operations on vectors, matrices and tensors: their shape, products, inverses, linear systems, eigenvalues and matrix decompositions. This introduction gives the concepts you need before you read the entries.
Vectors, matrices and tensors
There is no separate matrix value. A vector is a list, a matrix is a list of rows, and a tensor is a list nested more deeply. Every row of a matrix must have the same length.
[[1, 3], [5, 0]]
// ➔ [[1,3],[5,0]]
Matrices are stored in row-major order: the first element of the outer list is the first row. An index reads an element. Indexes start at 1. The first index selects the row and the second index selects the column.
let A = [[1, 2, 3], [4, 5, 6]]
A[2, 3]
// ➔ 6
With one index, you get a complete row:
let A = [[1, 2], [3, 4]]
A[2]
// ➔ [3,4]
Because vectors and matrices are lists, the collection operations (map,
reduce, at, length) also apply to them.
A plain list is a row of values. vector makes a column vector, that is a
matrix with one column:
vector(1, 2, 3)
// ➔ [[1],[2],[3]]
matrix does not change the value of its argument. It only records how the
matrix is displayed, for example its delimiters.
Shape and rank
An axis is one level of nesting. A vector has one axis, a matrix has two, and a tensor has more than two.
The shape is the length along each axis. A matrix with 2 rows and 3
columns has the shape (2, 3). A scalar has the empty shape ().
shape([[1, 2, 3], [4, 5, 6]])
// ➔ (2, 3)
The rank is the number of axes, that is the length of the shape. In this
library, rank always has this meaning:
rank([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
// ➔ 3
The number of linearly independent rows of a matrix is a different quantity.
Use matrixRank for it:
matrixRank([[1, 2], [2, 4]])
// ➔ 1
reshape puts the same elements into a new shape, and flatten puts them
into one list, in row-major order:
reshape(1..6, (2, 3))
// ➔ [[1,2,3],[4,5,6]]
Element types
The type of a vector or matrix includes the type of its elements and its shape. The element type is the narrowest type that includes every element.
type([[1/2, 1], [3, 4]])
// ➔ TypeFrom("matrix<rational^(2x2)>")
type([1, 2, 3])
// ➔ TypeFrom("vector<integer^3>")
A tensor with more than two axes has a list type with its full shape. An
operation that needs a matrix, such as determinant or inverse, reports an
incompatible-type error when its argument is not a matrix.
Elements can be symbolic. The operations then give a symbolic result:
determinant([[a, b], [c, d]])
// ➔ -b * c + a * d
Arithmetic and broadcasting
+ and - operate element by element. The two operands must have the same
shape.
[1, 2, 3] + [10, 20, 30]
// ➔ [11,22,33]
A scalar is broadcast: it combines with every element.
10 * [[1, 2], [3, 4]]
// ➔ [[10,20],[30,40]]
[[1, 2], [3, 4]] + 1
// ➔ [[2,3],[4,5]]
A vector is not broadcast along the rows of a matrix. Operands whose shapes
do not agree give an incompatible-dimensions error:
[[1, 2], [3, 4]] + [[1, 2, 3], [4, 5, 6]]
// ➔ Error("incompatible-dimensions", "2x2 vs 2x3")
Functions of one number, such as sqrt or cos, apply to each element:
sqrt([1, 4, 9])
// ➔ [1,2,3]
Products and powers
When one operand of * is a matrix, * is the matrix product. The
order of the operands is kept, because the matrix product is not
commutative.
[[1, 2], [3, 4]] * [[5, 6], [7, 8]]
// ➔ [[19,22],[43,50]]
A matrix times a vector is a vector:
[[1, 2], [3, 4]] * [1, 1]
// ➔ [3,7]
The product of two vectors with * is element by element. Use dot for the
scalar (inner) product:
[1, 2, 3] * [4, 5, 6]
// ➔ [4,10,18]
dot([1, 2, 3], [4, 5, 6])
// ➔ 32
hadamardProduct multiplies two matrices element by element. cross is the
cross product of two vectors of length 3.
For a square matrix and an integer exponent, ^ is the matrix power. A
power of 0 gives the identity matrix and a negative power uses the inverse.
[[1, 2], [3, 4]] ^ 2
// ➔ [[7,10],[15,22]]
[[1, 2], [3, 4]] ^ -1
// ➔ [[-2,1],[3/2,-1/2]]
Exact and numeric results
When all the elements are exact (integers and rationals), determinant,
inverse, linearSolve, rowReduce and kernel give an exact result. Use
N to get a decimal result:
inverse([[1, 2], [3, 4]])
// ➔ [[-2,1],[3/2,-1/2]]
N(inverse([[1, 2], [3, 4]]))
// ➔ [[-2,1],[1.5,-0.5]]
A matrix with a decimal element gives a decimal result.
eigenvalues and eigenvectors give exact values for a triangular matrix
and for a 2×2 matrix whose eigenvalues are rational or complex rational.
Otherwise they can give decimal values.
eigenvalues([[0, -1], [1, 0]])
// ➔ [i,-i]
eigenvalues([[2, 1], [1, 2]])
// ➔ [3,1]
The decompositions luDecomposition, qrDecomposition,
choleskyDecomposition and svd use numeric algorithms. Their factors can
contain decimal values even when the argument is exact. Multiply the factors
to check a decomposition:
let (P, L, U) = luDecomposition([[4, 3], [2, 1]])
L * U
// ➔ [[4,3],[2,1]]
An operation that has no result for its argument stays unevaluated. For example, a singular matrix has no inverse:
inverse([[1, 2], [2, 4]])
// ➔ Inverse([[1,2],[2,4]])
Each definition is listed under its Epsil spelling (the MathJSON name when it has none), with its signature in the engine's type syntax. The Standard Library page is the one-page index of every category.
Definitions
adjugateMatrix
MathJSON AdjugateMatrix · (matrix) -> matrix
Adjugate (classical adjoint) of a square matrix.
adjugateMatrix([[1, 2], [3, 4]])
// ➔ [[4,-2],[-3,1]]
characteristicPolynomial
MathJSON CharacteristicPolynomial · (matrix, any?) -> expression
Characteristic polynomial det(x·I − A) of a square matrix (monic).
characteristicPolynomial([[2, 1], [1, 2]], x)
// ➔ x^2 - 4x + 3
choleskyDecomposition
MathJSON CholeskyDecomposition · (matrix) -> matrix
Cholesky decomposition of a positive-definite matrix.
choleskyDecomposition([[4, 2], [2, 5]])
// ➔ [[2,0],[1,2]]
conjugateTranspose
MathJSON ConjugateTranspose · (value, axis1: integer?, axis2: integer?) -> value
Conjugate transpose (Hermitian adjoint) of a matrix or tensor.
conjugateTranspose([[1, 2 + i], [3 - i, 4]])
// ➔ [[1,(3 + i)],[(2 - i),4]]
cross
MathJSON Cross · (tuple | vector, tuple | vector) -> tuple | vector
Cross product of two 3-vectors.
cross([1, 0, 0], [0, 1, 0])
// ➔ [0,0,1]
degree
MathJSON Degree · (value) -> integer
Degree of an object
degree(x^3 + 2 * x + 1)
// ➔ 3
det
MathJSON Det · (matrix) -> number
Det is an alias for Determinant, which is the preferred name. Determinant of a square matrix.
det([[1, 2], [3, 4]])
// ➔ -2
determinant
MathJSON Determinant · (matrix) -> number
Determinant of a square matrix.
determinant([[1, 2], [3, 4]])
// ➔ -2
diagonal
MathJSON Diagonal · (value) -> value
Extract a matrix diagonal or build a diagonal matrix.
diagonal([[1, 2], [3, 4]])
// ➔ [1,4]
diagonal([1, 2, 3])
// ➔ [[1,0,0],[0,2,0],[0,0,3]]
dimension
MathJSON Dimension · (value) -> integer
Dimension of an object
dimension([[1, 2, 3], [4, 5, 6]])
// ➔ 6
dot
MathJSON Dot · (list<tuple> | matrix | tuple | vector, list<tuple> | matrix | tuple | vector) -> value
Dot product (vector inner product) or matrix product.
dot([1, 2, 3], [4, 5, 6])
// ➔ 32
eigen
MathJSON Eigen · (matrix) -> tuple
Eigenvalue-eigenvector decomposition of a square matrix.
eigen([[2, 1], [1, 2]])
// ➔ ([3,1], [[1,1],[-1,1]])
eigenvalues
MathJSON Eigenvalues · (matrix) -> list
Eigenvalues of a square matrix.
eigenvalues([[2, 1], [1, 2]])
// ➔ [3,1]
eigenvectors
MathJSON Eigenvectors · (matrix) -> list
Eigenvectors of a square matrix.
eigenvectors([[2, 1], [1, 2]])
// ➔ [[1,1],[-1,1]]
flatten
MathJSON Flatten · (value, integer?) -> list
Flatten a tensor or collection into a list.
flatten([[1, 2], [3, 4]])
// ➔ [1,2,3,4]
hadamardProduct
MathJSON HadamardProduct · (matrix | vector, matrix | vector) -> matrix | vector
Hadamard (element-wise) product of two vectors or matrices of the same shape.
hadamardProduct([[1, 2], [3, 4]], [[5, 6], [7, 8]])
// ➔ [[5,12],[21,32]]
hom
MathJSON Hom · (value*) -> value
Hom-set of morphisms between objects
dimension(hom([1, 2], [3, 4, 5]))
// ➔ 6
identityMatrix
MathJSON IdentityMatrix · (integer) -> matrix
n-by-n identity matrix.
identityMatrix(3)
// ➔ [[1,0,0],[0,1,0],[0,0,1]]
inverse
MathJSON Inverse · (T) -> T where T: matrix
Multiplicative inverse of a square matrix.
inverse([[1, 2], [3, 4]])
// ➔ [[-2,1],[3/2,-1/2]]
isDiagonal
MathJSON IsDiagonal · (value) -> boolean
Whether the matrix is diagonal (all off-diagonal entries are zero).
isDiagonal([[1, 0], [0, 5]])
// ➔ "True"
isSquareMatrix
MathJSON IsSquareMatrix · (value) -> boolean
Whether the value is a square matrix.
isSquareMatrix([[1, 2], [3, 4]])
// ➔ "True"
isSymmetric
MathJSON IsSymmetric · (value) -> boolean
Whether the matrix is symmetric (A equals its transpose).
isSymmetric([[1, 2], [2, 3]])
// ➔ "True"
kernel
MathJSON Kernel · (value) -> list
Kernel (null space) of a linear map
kernel([[1, 2], [2, 4]])
// ➔ [[-2,1]]
luDecomposition
MathJSON LUDecomposition · (matrix) -> tuple
LU decomposition of a square matrix.
luDecomposition([[4, 3], [2, 1]])
// ➔ ([[1,0],[0,1]], [[1,0],[0.5,1]], [[4,3],[0,-0.5]])
linearSolve
MathJSON LinearSolve · (matrix, matrix | vector) -> value
Solve the linear system A·x = b for x.
linearSolve([[2, 1], [1, 3]], [3, 5])
// ➔ [4/5,7/5]
matrix
MathJSON Matrix · (matrix, string?, string?) -> matrix
Matrix constructor and canonicalizer.
matrix([[1, 2], [3, 4]])
// ➔ [[1,2],[3,4]]
matrixMultiply
MathJSON MatrixMultiply · (matrix | vector, matrix | vector) -> matrix | vector
Matrix and vector multiplication.
matrixMultiply([[1, 2], [3, 4]], [[5, 6], [7, 8]])
// ➔ [[19,22],[43,50]]
matrixPower
MathJSON MatrixPower · (matrix, real) -> matrix
Square matrix raised to a power. Integer powers are the repeated matrix product; a half-integer power (e.g. 1/2) of an exact 2×2 positive-semidefinite matrix is the principal matrix square root.
matrixPower([[1, 1], [1, 0]], 10)
// ➔ [[89,55],[55,34]]
matrixRank
MathJSON MatrixRank · (value) -> integer
Rank of a matrix (number of linearly independent rows/columns).
matrixRank([[1, 2], [2, 4]])
// ➔ 1
norm
MathJSON Norm · (list<number> | list<tuple> | number | tuple, (+oo | real | string)?) -> +oo | nan | real
Vector or matrix norm.
norm([3, 4])
// ➔ 5
norm([3, 4], 1)
// ➔ 7
onesMatrix
MathJSON OnesMatrix · (integer, integer?) -> matrix
Matrix filled with ones.
onesMatrix(2, 3)
// ➔ [[1,1,1],[1,1,1]]
pseudoInverse
MathJSON PseudoInverse · (matrix) -> matrix
Moore-Penrose pseudoinverse of a matrix.
pseudoInverse([[1, 2], [3, 4], [5, 6]])
// ➔ [[-4/3,-1/3,2/3],[13/12,1/3,-5/12]]
qrDecomposition
MathJSON QRDecomposition · (matrix) -> tuple
QR decomposition of a matrix.
qrDecomposition([[0, 1], [1, 1]])
// ➔ ([[0,1],[-1,0]], [[-1,-1],[0,1]])
rank
MathJSON Rank · (value) -> integer
The length of the shape of the expression. Note this is not the matrix rank (the number of linearly independent rows or columns in the matrix)
rank([[1, 2, 3], [4, 5, 6]])
// ➔ 2
reshape
MathJSON Reshape · (value, tuple) -> value
Reshape a tensor or collection to a target shape.
reshape([1, 2, 3, 4, 5, 6], (2, 3))
// ➔ [[1,2,3],[4,5,6]]
rowReduce
MathJSON RowReduce · (matrix) -> matrix
Reduced row echelon form (RREF) of a matrix.
rowReduce([[1, 2, 3], [4, 5, 6]])
// ➔ [[1,0,-1],[0,1,2]]
svd
MathJSON SVD · (matrix) -> tuple
Singular value decomposition of a matrix.
svd([[3, 0], [0, 4]])
// ➔ ([[0,1],[1,0]], [[4,0],[0,3]], [[0,1],[1,0]])
shape
MathJSON Shape · (value) -> tuple
Return the shape tuple of an expression.
shape([[1, 2, 3], [4, 5, 6]])
// ➔ (2, 3)
singularValues
MathJSON SingularValues · (matrix) -> list
The singular values of a matrix, sorted in descending order (including any zero values). Exact for a matrix whose Gram matrix A^T·A (or A·A^T) is at most 2×2 with exact rational entries; numeric otherwise.
singularValues([[3, 0], [0, 4]])
// ➔ [4,3]
trace
MathJSON Trace · (list<number> | number, axis1: integer?, axis2: integer?) -> list<number> | number
Trace of a matrix or pair of tensor axes.
trace([[1, 2], [3, 4]])
// ➔ 5
transpose
MathJSON Transpose · (value, axis1: integer?, axis2: integer?) -> value
Transpose a matrix or swap two tensor axes.
transpose([[1, 2, 3], [4, 5, 6]])
// ➔ [[1,4],[2,5],[3,6]]
vector
MathJSON Vector · (any+) -> vector
Construct a column vector.
vector(1, 2, 3)
// ➔ [[1],[2],[3]]
zeroMatrix
MathJSON ZeroMatrix · (integer, integer?) -> matrix
Matrix filled with zeros.
zeroMatrix(2, 3)
// ➔ [[0,0,0],[0,0,0]]