Documentation
¶
Overview ¶
Package matrix provides a clean, generic matrix type with support for common linear algebra operations — creation, arithmetic, transformations, and decompositions.
Built with Go generics, it works with int, float32, float64, complex128, and other numeric types. Zero external dependencies.
Index ¶
- Variables
- type Float
- type Matrix
- func Add[T Numeric](a, b *Matrix[T]) (*Matrix[T], error)
- func HadamardProduct[T Numeric](a, b *Matrix[T]) (*Matrix[T], error)
- func Identity[T Numeric](n int) *Matrix[T]
- func Mul[T Numeric](a, b *Matrix[T]) (*Matrix[T], error)
- func MustNew[T Numeric](data [][]T) *Matrix[T]
- func New[T Numeric](data [][]T) (*Matrix[T], error)
- func Ones[T Numeric](rows, cols int) *Matrix[T]
- func Random[T Float](rows, cols int) *Matrix[T]
- func Scale[T Numeric](m *Matrix[T], scalar T) *Matrix[T]
- func Solve[T Numeric](A *Matrix[T], b *Matrix[T]) (*Matrix[float64], error)
- func Sub[T Numeric](a, b *Matrix[T]) (*Matrix[T], error)
- func Transpose[T Numeric](m *Matrix[T]) *Matrix[T]
- func Zeros[T Numeric](rows, cols int) *Matrix[T]
- func (m *Matrix[T]) ApproxEquals(other *Matrix[T], eps float64) bool
- func (m *Matrix[T]) At(i, j int) (T, error)
- func (m *Matrix[T]) Col(j int) (*Matrix[T], error)
- func (m *Matrix[T]) Cols() int
- func (m *Matrix[T]) Copy() *Matrix[T]
- func (m *Matrix[T]) Data() [][]T
- func (m *Matrix[T]) Det() (float64, error)
- func (m *Matrix[T]) Eigen() ([]complex128, error)
- func (m *Matrix[T]) Equals(other *Matrix[T]) bool
- func (m *Matrix[T]) Inverse() (*Matrix[float64], error)
- func (m *Matrix[T]) IsIdentity() bool
- func (m *Matrix[T]) IsSquare() bool
- func (m *Matrix[T]) IsSymmetric() bool
- func (m *Matrix[T]) IsZero() bool
- func (m *Matrix[T]) LU() (*Matrix[float64], *Matrix[float64], error)
- func (m *Matrix[T]) LUP() (*Matrix[float64], *Matrix[float64], *Matrix[float64], error)
- func (m *Matrix[T]) Norm() float64
- func (m *Matrix[T]) Print()
- func (m *Matrix[T]) PrintWith(opts PrintOptions)
- func (m *Matrix[T]) QR() (*Matrix[float64], *Matrix[float64], error)
- func (m *Matrix[T]) REF() (*Matrix[float64], error)
- func (m *Matrix[T]) RREF() (*Matrix[float64], error)
- func (m *Matrix[T]) Rank() int
- func (m *Matrix[T]) Row(i int) (*Matrix[T], error)
- func (m *Matrix[T]) Rows() int
- func (m *Matrix[T]) SVD() (*Matrix[float64], *Matrix[float64], *Matrix[float64], error)
- func (m *Matrix[T]) Set(i, j int, val T) error
- func (m *Matrix[T]) Shape() (int, int)
- func (m *Matrix[T]) String() string
- func (m *Matrix[T]) SubMatrix(r0, r1, c0, c1 int) (*Matrix[T], error)
- func (m *Matrix[T]) Trace() (T, error)
- type Numeric
- type PrintOptions
- type RealNumeric
Constants ¶
This section is empty.
Variables ¶
var ( // ErrDimensionMismatch is returned when matrix dimensions are incompatible // for the requested operation (e.g., adding a 2x3 to a 3x2). ErrDimensionMismatch = errors.New("matrix: dimension mismatch") // ErrNotSquare is returned when an operation requires a square matrix // but receives a non-square one (e.g., determinant of a 2x3). ErrNotSquare = errors.New("matrix: matrix must be square") // ErrSingular is returned when a matrix is singular (determinant ≈ 0) // and the operation requires a non-singular matrix. ErrSingular = errors.New("matrix: matrix is singular") // ErrNotInvertible is returned when a matrix cannot be inverted. // This is typically because the matrix is singular. ErrNotInvertible = errors.New("matrix: matrix is not invertible") // ErrOutOfBounds is returned when an index is outside the valid range // for the matrix dimensions. ErrOutOfBounds = errors.New("matrix: index out of bounds") // ErrEmptyMatrix is returned when attempting to create or operate on // a matrix with zero rows or zero columns. ErrEmptyMatrix = errors.New("matrix: empty matrix") // ErrNotVector is returned when an operation expects a vector (n×1 or 1×n) // but receives a general matrix. ErrNotVector = errors.New("matrix: expected a vector (n×1)") // ErrNotImplemented is returned for operations that are planned but not // yet implemented (e.g., SVD in v1). ErrNotImplemented = errors.New("matrix: operation not yet implemented") // ErrNotConverged is returned when an iterative algorithm (e.g., QR // eigenvalue computation) fails to converge within the maximum number // of iterations. ErrNotConverged = errors.New("matrix: algorithm did not converge") )
Sentinel errors for matrix operations. All operations that can fail return (result, error) — never panic.
var Epsilon = 1e-9
Epsilon is the tolerance used for floating-point comparisons. Operations like singularity checks compare against this value rather than testing exact equality to zero.
Functions ¶
This section is empty.
Types ¶
type Float ¶
Float is a constraint for floating-point types only. Used for operations like Random that only make sense for floats.
type Matrix ¶
type Matrix[T Numeric] struct { // contains filtered or unexported fields }
Matrix is the core generic matrix type. It stores elements in row-major order as a 2D slice. All operations return new matrices — the original is never mutated (except Set, which operates on a pointer receiver).
func Add ¶
Add performs element-wise addition of two matrices. Both matrices must have the same dimensions.
Mathematically: C[i][j] = A[i][j] + B[i][j]
func HadamardProduct ¶
HadamardProduct performs element-wise multiplication of two matrices. Both matrices must have the same dimensions. Also known as the Schur product.
Mathematically: C[i][j] = A[i][j] * B[i][j]
func Identity ¶
Identity returns an n×n identity matrix (1s on the diagonal, 0s elsewhere). Panics if n <= 0.
func Mul ¶
Mul performs matrix multiplication (dot product) of two matrices. Requires a.cols == b.rows. The result has dimensions (a.rows × b.cols).
Mathematically: C[i][j] = Σ(k=0..n-1) A[i][k] * B[k][j]
Uses the naive O(n³) algorithm. Fine for small-to-medium matrices. For large matrices, consider Strassen (planned for v2).
func MustNew ¶
MustNew is like New but panics on error. Useful for test code and literals where you know the input is valid.
func New ¶
New creates a Matrix from a 2D slice. It validates that the input is rectangular (all rows have the same length) and performs a deep copy so the caller's original slice is not aliased.
Returns nil and an error if the input is empty or jagged.
func Random ¶
Random returns a rows×cols matrix filled with random float values in [0, 1). Only available for float32 and float64 types. Panics if rows or cols <= 0.
func Scale ¶
Scale multiplies every element of the matrix by a scalar value. Always succeeds — returns a new matrix.
Mathematically: C[i][j] = scalar * A[i][j]
func Solve ¶
Solve solves the linear system Ax = b using LU decomposition with forward and backward substitution.
Given:
- A is an n×n coefficient matrix
- b is an n×1 column vector (right-hand side)
Returns x such that Ax = b.
Algorithm:
- Decompose PA = LU (with partial pivoting)
- Permute b according to P → Pb
- Solve Ly = Pb (forward substitution)
- Solve Ux = y (backward substitution)
Returns ErrNotSquare if A isn't square. Returns ErrDimensionMismatch if b doesn't have the right dimensions. Returns ErrNotVector if b isn't a column vector. Returns ErrSingular if A is singular.
func Sub ¶
Sub performs element-wise subtraction of two matrices. Both matrices must have the same dimensions.
Mathematically: C[i][j] = A[i][j] - B[i][j]
func Transpose ¶
Transpose returns the transpose of the matrix. Rows become columns and columns become rows.
Mathematically: B[j][i] = A[i][j]
Properties:
- (Aᵀ)ᵀ = A
- (A + B)ᵀ = Aᵀ + Bᵀ
- (AB)ᵀ = BᵀAᵀ
func (*Matrix[T]) ApproxEquals ¶ added in v1.1.0
ApproxEquals returns true if two matrices have the same shape and all corresponding elements differ by less than eps (in absolute value).
This is essential when comparing matrices that result from floating-point arithmetic, where exact equality (Equals) would produce false negatives.
func (*Matrix[T]) At ¶
At returns the element at row i, column j (0-indexed). Returns an error if the indices are out of bounds.
func (*Matrix[T]) Col ¶ added in v1.1.0
Col returns the j-th column as a new n×1 matrix (deep copy, 0-indexed). Returns ErrOutOfBounds if j is out of range.
func (*Matrix[T]) Data ¶
func (m *Matrix[T]) Data() [][]T
Data returns a deep copy of the underlying 2D slice. The returned slice is safe to modify without affecting the matrix.
func (*Matrix[T]) Det ¶
Det returns the determinant of a square matrix.
The determinant is computed via LU-style Gaussian elimination with partial pivoting. The determinant equals the product of the diagonal elements of the upper triangular form, adjusted for row swaps.
Properties:
- det(I) = 1
- det(AB) = det(A) * det(B)
- det(Aᵀ) = det(A)
- det(cA) = c^n * det(A) for n×n matrix
- A is invertible ⟺ det(A) ≠ 0
Returns ErrNotSquare if the matrix isn't square.
func (*Matrix[T]) Eigen ¶
func (m *Matrix[T]) Eigen() ([]complex128, error)
Eigen computes the eigenvalues of a square matrix using the QR algorithm with implicit shifts.
Eigenvalues λ satisfy: Av = λv for some non-zero vector v.
The QR algorithm iteratively decomposes A = QR, then forms A' = RQ. This converges to an upper triangular (Schur) form where the diagonal entries are the eigenvalues.
For real matrices, complex eigenvalues appear as 2×2 blocks on the diagonal.
Returns eigenvalues as complex128 (real eigenvalues have zero imaginary part). Returns ErrNotSquare if the matrix isn't square. Returns ErrNotConverged if the algorithm fails to converge.
Note: eigenvector computation is planned for v1.5.
func (*Matrix[T]) Equals ¶
Equals returns true if two matrices have the same shape and identical elements. For floating-point types, exact equality is used — use ApproxEquals for epsilon-based comparison.
func (*Matrix[T]) Inverse ¶
Inverse returns the multiplicative inverse of a square matrix using Gauss-Jordan elimination on the augmented matrix [A | I].
The inverse A⁻¹ satisfies: A * A⁻¹ = A⁻¹ * A = I
Returns ErrNotSquare if the matrix isn't square. Returns ErrNotInvertible if the matrix is singular (det ≈ 0).
func (*Matrix[T]) IsIdentity ¶
IsIdentity returns true if the matrix is the identity matrix (ones on diagonal, zeros elsewhere), within Epsilon tolerance.
func (*Matrix[T]) IsSquare ¶
IsSquare returns true if the matrix has the same number of rows and columns.
func (*Matrix[T]) IsSymmetric ¶
IsSymmetric returns true if the matrix equals its own transpose: A = Aᵀ. For floating-point types, comparisons use the package-level Epsilon tolerance. A non-square matrix is never symmetric.
func (*Matrix[T]) LU ¶
LU performs LU decomposition with partial pivoting.
Decomposes the matrix A into a lower triangular matrix L and an upper triangular matrix U such that PA = LU, where P is an implicit permutation matrix from row swaps.
The Doolittle algorithm is used: L has ones on its diagonal.
Uses:
- Solving linear systems (Ax = b → LUx = b)
- Computing determinants efficiently
- Matrix inversion
Returns (L, U, error). Returns ErrNotSquare if the matrix isn't square. Returns ErrSingular if a zero pivot is encountered.
func (*Matrix[T]) LUP ¶ added in v1.1.0
LUP performs LU decomposition with partial pivoting and also returns the permutation matrix P.
Returns (L, U, P, error) such that P*A = L*U.
P is an n×n permutation matrix built from the row-swap history. Use this when you need to verify or reconstruct the decomposition.
func (*Matrix[T]) Norm ¶
Norm returns the Frobenius norm of the matrix.
Mathematically: ‖A‖_F = √(Σ |a[i][j]|²)
The Frobenius norm is the matrix analogue of the Euclidean vector norm. It's always non-negative and equals zero only for the zero matrix.
func (*Matrix[T]) Print ¶
func (m *Matrix[T]) Print()
Print prints the matrix to stdout with default formatting.
func (*Matrix[T]) PrintWith ¶
func (m *Matrix[T]) PrintWith(opts PrintOptions)
PrintWith prints the matrix to stdout with custom formatting options.
func (*Matrix[T]) QR ¶
QR performs QR decomposition using the Modified Gram-Schmidt process.
Decomposes the matrix A into an orthogonal matrix Q and an upper triangular matrix R such that A = QR.
Q has orthonormal columns: QᵀQ = I R is upper triangular
Uses:
- Solving least-squares problems
- Eigenvalue computation (QR algorithm)
- Numerical stability improvements
The modified Gram-Schmidt process is more numerically stable than the classical version.
Returns (Q, R, error). Works on any m×n matrix where m ≥ n.
func (*Matrix[T]) REF ¶
REF returns the Row Echelon Form of the matrix using Gaussian elimination with partial pivoting.
In REF:
- All zero rows are at the bottom
- The leading entry (pivot) of each non-zero row is to the right of the pivot in the row above
- All entries below a pivot are zero
The result is always float64 regardless of the input type, since row reduction inherently produces fractions.
func (*Matrix[T]) RREF ¶
RREF returns the Reduced Row Echelon Form of the matrix using Gauss-Jordan elimination with partial pivoting.
In RREF (extends REF with):
- Each pivot is exactly 1
- Each pivot is the only non-zero entry in its column
RREF is unique for any given matrix — unlike REF, which depends on the elimination order.
func (*Matrix[T]) Rank ¶
Rank returns the rank of the matrix — the number of linearly independent rows (equivalently, columns).
Computed by reducing to RREF and counting non-zero rows (pivots).
Properties:
- 0 ≤ rank(A) ≤ min(rows, cols)
- rank(A) = rank(Aᵀ)
- A is full rank if rank(A) = min(rows, cols)
func (*Matrix[T]) Row ¶ added in v1.1.0
Row returns the i-th row as a new 1×n matrix (deep copy, 0-indexed). Returns ErrOutOfBounds if i is out of range.
func (*Matrix[T]) SVD ¶
SVD performs Singular Value Decomposition (thin SVD).
Decomposes A = U * Σ * Vᵀ where:
- U is an m×k orthogonal matrix (left singular vectors)
- Σ is a k×k diagonal matrix (singular values, non-negative, descending)
- V is an n×k orthogonal matrix (right singular vectors)
- k = min(m, n)
Algorithm: One-sided Jacobi SVD. Iteratively applies Jacobi rotations to orthogonalize the columns of A, producing V and the singular values as column norms, then normalizes to get U.
Uses:
- Principal Component Analysis (PCA)
- Low-rank approximation
- Pseudoinverse computation
- Condition number estimation
Returns (U, Σ, V, error). Returns ErrEmptyMatrix for empty inputs.
func (*Matrix[T]) Set ¶
Set sets the element at row i, column j (0-indexed). This is the only mutating operation — it uses a pointer receiver. Returns an error if the indices are out of bounds.
func (*Matrix[T]) String ¶
String implements the fmt.Stringer interface, providing a clean default representation of the matrix.
Example output for a 2×3 matrix:
[ 1.0000 2.0000 3.0000 ] [ 4.0000 5.0000 6.0000 ]
func (*Matrix[T]) SubMatrix ¶ added in v1.1.0
SubMatrix extracts the submatrix spanning rows [r0, r1) and columns [c0, c1). Uses half-open ranges consistent with Go slice semantics. Returns a deep copy — modifying the result does not affect the original.
Returns ErrOutOfBounds if any index is out of range or if r0 >= r1 or c0 >= c1.
type Numeric ¶
type Numeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~float32 | ~float64 |
~complex64 | ~complex128
}
Numeric is the type constraint for all matrix element types. It supports integers, floats, and complex numbers.
type PrintOptions ¶
type PrintOptions struct {
// Precision is the number of decimal places for floating-point values.
// Default: 4. Ignored for integer types.
Precision int
// Padding is the minimum number of spaces between columns.
// Default: 2.
Padding int
// Brackets controls the bracket style for the matrix.
// Options: "square" (default), "round", "pipe", "none".
Brackets string
}
PrintOptions controls how a matrix is formatted when using PrintWith.
type RealNumeric ¶
RealNumeric is a stricter constraint for operations that require ordered comparisons or real-valued math functions (Abs, Sqrt, etc.). Complex types are excluded because they lack a natural ordering.