Matrix library for C++20
A tiny C++20 general-purpose library for dense, fixed-size and dynamically-sized matrices with no dependencies.
Overview
Features:
- intuitive syntax
- low-overhead
- header-only and single-header
- fully constexpr (except where math functions like `sqrt` are used).
- STL-oriented
- Statically-sized have static memory (e.g. suited for audio development).
- Dynamically-sized matrices are now available as well.
- simple software design in comparison to some other matrix libs, e.g. no CRTP, virtual functions, ...
- fully tested. Tests can be run with Catch2.
Limitations:
- only C++20 (and up) because of heavy use of concepts and constexpr
- this is not a linear algebra library - at the moment the library provides no linear algebra algorithms such as decomposition and solvers
Sample Code (some possible operations)
Matrix<float, 3, 3> mat{ 1,2,3,4,5,6,7,8,9 };
auto mat2 = mat * 2.f - mat;
// Take sqrt of all entries
mat.apply([](float& f) {f = std::sqrtf(f); });
// Iterate over all entries (row first)
for (const auto& el : mat) {}
// Iterate over one row
for (const auto& el : mat.row(1)) {}
// Copy one row into another
mat.row(1) = mat.row(0);
// Copy matrix block into other matrix
mat2.block(1, 1, 2, 2) = mat.block(0, 0, 2, 2);
Vector3f vec = mat.col(0);
vec.x() += 5;
float norm = vec.norm();
RowVector3f row_vec(7);
// Auto cast 1x1 matrix to scalar
float scalar = row_vec * vec;
// Pretty print matrices
cout << mat << mat2 << vec;
// Dynamic matrices
Matrix<float, dynamic, dynamic> dyn_mat{ 3, 4 };
Documentation
Documentation overview
- Classes
- Type Definitions
- Predefined Matrices
- Exceptions (optional)
- Matrix Class
- Matrix_view Class
- Global Functions
Classes
class Matrix<T,m,n>
m
×n
matrices of type T
.class Matrix_view<T>
class Matrix_iterator<T>
class Matrix_stride_iterator<T>
class Matrix_block_iterator<T>
struct Shape<bool>
Type Definitions
using Index = size_t
using Vector<T,n> = Matrix<T,1,n>
Matrix
.using RowVector<T,m> = Matrix<T,m,1>
Matrix
.Predefined Matrices
using Matrix2f = Matrix<float, 2, 2>
using Matrix3f = Matrix<float, 3, 3>
using Matrix4f = Matrix<float, 4, 4>
using Vector2f = Vector<float, 2>
using Vector3f = Vector<float, 3>
using Vector4f = Vector<float, 4>
using RowVector2f = RowVector<float, 2>
using RowVector3f = RowVector<float, 3>
using RowVector4f = RowVector<float, 4>
float
matrix and vector types.using Matrix2d = Matrix<double, 2, 2>
using Matrix3d = Matrix<double, 3, 3>
using Matrix4d = Matrix<double, 4, 4>
using Vector2d = Vector<double, 2>
using Vector3d = Vector<double, 3>
using Vector4d = Vector<double, 4>
using RowVector2d = RowVector<double, 2>
using RowVector3d = RowVector<double, 3>
using RowVector4d = RowVector<double, 4>
double
matrix and vector types.Exceptions
By default, exceptions are not activated. Calls to Matrix::block(Index, Index, Index, Index)
, Matrix::row(Index)
, Matrix::col(Index)
,
Matrix_view::operator=(const Matrix_view&)
, Matrix_view::operator=(const Matrix&)
and
Matrix(const Matrix_view&)
will do an assertation when running in debug mode. Defining the macro MATRIX_EXCEPTIONS
before
including this library will instead turn on exceptions for these cases.
struct Matrix_view_mismatch
Matrix_view
into another is attempted with different block dimensions.struct Matrix_block_domain_error
struct Matrix_shape_error
Matrix Class
Template Parameters
class T
T
needs to be default-constructible, copy-insertable, destructable, equality-comparable and capable of basic arithmetic. Index m
Index n
Matrix
satisfies the requirements for a C++ Container, ReversableContainer and ContiguousContainer with the same exceptions as std::array
that the complexity of swapping is
linear and the default-constructed matrix is not empty for non-zero m
and n
.
Types
using value_type = T
using size_type = size_t
using difference_type = ptrdiff_t
using iterator = Matrix_iterator<T>
,using const_iterator = Matrix_iterator<const T>
using reverse_iterator = std::reverse_iterator<iterator>
,using const_reverse_iterator = std::reverse_iterator<const_iterator>
Constructors (fixed-size)
Matrix()
Matrix(const T& value)
value
. Matrix(const std::initializer_list<T> elems)
Matrix(const std::array<T, m*n>& elems)
std::array
with fitting length.Matrix(std::array<T, m*n>&& elems)
std::array
with fitting length.Matrix(const Matrix_view<T>& mat_view)
mat_view
.Constructors (dynamically-sized)
Matrix(Index m, Index n)
Matrix(Index m, Index n, const T& value)
value
. Matrix(Index m, Index n, const std::initializer_list<T> elems)
Matrix(Index m, Index n, const std::vector<T>& elems)
std::vector
with fitting length.Matrix(Index m, Index n, std::vector<T>&& elems)
std::vector
with fitting length.Matrix(const Matrix_view<T>& mat_view)
mat_view
.Matrix Access
size_type rows() const
size_type cols() const
size_type size() const
T* data()
,const T* data() const
T& operator()(size_type i, size_type j)
,const T& operator()(size_type i, size_type j) const
i
and column j
.T& at(size_type i, size_type j)
,const T& at(size_type i, size_type j) const
i
and column j
(bounds checked).void fill(const T& c)
c
.void swap(Matrix& a)
Arithmetic
template<class F>
Matrix& apply(F f)
f
takes one argument: the entry). template<class F>
Matrix& apply(F f, const T& c)
f
takes two arguments: the entry and the constant c
). template<class F>
Matrix& apply(F f, const Matrix& a))
f
takes two arguments: one entry of each matrix). Matrix& operator+=(const T& c)
Matrix operator+(const T& c) const
Matrix& operator-=(const T& c)
Matrix operator-(const T& c) const
Matrix& operator*=(const T& c)
Matrix operator*(const T& c) const
Matrix& operator/=(const T& c)
Matrix operator/(const T& c) const
Matrix& operator%=(const T& c)
Matrix operator%(const T& c) const
Matrix& operator+=(const Matrix& a)
Matrix operator+(const Matrix& a) const
Matrix& operator-=(const Matrix& a)
Matrix operator-(const Matrix& a) const
Resize and reshape (only for dynamically-sized matrices)
void resize(Index m, Index n)
resize()
on the vector storing the matrix' elements. void reshape(Index m, Index n)
void reshape(Shape new_shape)
Shape shape() const
Other Matrix Operations
Matrix<T, n, m> transpose() const
Matrix<T, m, p> operator*(const Matrix<T, n, p>& a) const
template<class U>
Matrix<U, m, n> cast() const
U
. This function returns a new matrix. The type U
needs to fulfill std::convertible_to<T, U>
. Iterators
iterator begin()
,const_iterator begin() const
iterator end()
,const_iterator end() const
reverse_iterator rbegin()
,const_reverse_iterator rbegin() const
reverse_iterator rend()
,const_reverse_iterator rend() const
Row/Column/Block Access
The programmer is responsible to ensure that a Matrix_view<T>
does not outlive the pointed-to matrix.
Matrix_view<T> block(size_type row, size_type col, size_type rows, size_type cols)
,Matrix_view<const T> block(size_type row, size_type col, size_type rows, size_type cols) const
Matrix_view<T>
referencing a rectangular block of the matrix. Matrix_view<T> row(size_type row)
,Matrix_view<const T> row(size_type row) const
Matrix_view<T>
referencing the specified row of the matrix. Matrix_view<T> col(size_type col)
,Matrix_view<const T> col(size_type col) const
Matrix_view<T>
referencing the specified column of the matrix. Vector-specific Operations
Matrices that have at least one dimension equal 1 are considered vectors. These feature some additional operations.
T& operator[](size_type i)
,const T& operator[](size_type i) const
i
'th element of the vector. T& x(size_type i)
,const T& x(size_type i) const
T& y(size_type i)
,const T& y(size_type i) const
T& z(size_type i)
,const T& z(size_type i) const
T norm() const
Matrix& normalize()
T operator*(const Matrix& vec)
operator T() const
Factory Functions
static Matrix zero()
static Matrix zero(Index m, Index n)
static Matrix identity()
static Matrix identity(Index n)
Matrix_view Class
Types
using value_type = T
using pointer = T*
using reference = T&
using size_type = size_t
using iterator = Matrix_block_iterator<T>
,using const_iterator = Matrix_block_iterator<const T>
using reverse_iterator = std::reverse_iterator<iterator>
,using const_reverse_iterator = std::reverse_iterator<const_iterator>
Constructors
Matrix_view()
Matrix_view(T* ptr, size_type m, size_type n, size_type rows, size_type cols)
Iterators
iterator begin()
,const_iterator begin() const
iterator end()
,const_iterator end() const
reverse_iterator rbegin()
,const_reverse_iterator rbegin() const
reverse_iterator rend()
,const_reverse_iterator rend() const
Member functions
size_type rows() const
size_type cols() const
Matrix_view& operator=(const Matrix_view& mat_view)
mat_view
points to the matrix block that this view points to. The block dimensions need to match. template<size_type m, size_type n>
Matrix_view& operator=(const Matrix<T, m, n>& mat)
mat
into the matrix block that this view points to. Block dimensions and dimensions of mat
need to match. Global Functions
template<class T, Index m, Index n>
bool operator==(const Matrix<T, m, n>& a, const Matrix<T, m, n>& b)
template<class T, Index m, Index n>
bool operator!=(const Matrix<T, m, n>& a, const Matrix<T, m, n>& b)
template<class T, Index m, Index n>
Matrix<T, m, n>& operator-(const Matrix<T, m, n>& mat)
mat*-1
). template<class T, Index m, Index n>
Matrix<T, m, n>& operator*(const T& c, const Matrix<T, m, n>& mat)
mat*c
). template<class T, Index m>
T distance(const Vector& a, const Vector& b)
template<class T, Index m>
T distance(const RowVector& a, const RowVector& b)
(a - b).norm()
). template<class T, Index n>
Matrix<T, n, n> diag(const T(&values)[n])
values
. All other values are default-initialized. Template parameters can be deduced automaticallytemplate<class T, Index n>
Matrix<T, n, n> antidiag(const T(&values)[n])
values
. All other values are default-initialized. Template parameters can be deduced automatically