Vectors and matrices§
Vector and matrices are the fundamental building blocks of any linear algebra library. Their sizes can either be known at compiletime or only at runtime. In either case, they allow common operations (additions, multiplications, etc.) to be used through operator overloading.
The generic Matrix
type§
We first give a short description of the generic Matrix
type. Readers
interested in the implementation details are refered to the section about
implementation internals.
In practice, most usecases are covered by type aliases that hide the most
complicated type parameters.
The Matrix<N, R, C, S>
type is a columnmajor matrix with a shape that may or
may not be known at compiletime. It takes four type parameters:
N
: the scalar type, i.e., the type of the matrix components. Typical values aref32
orf64
.R
: a type characterizing the number of rows on this matrix.C
: a type characterizing the number of columns on this matrix.S
: the buffer that contains all the matrix components and (if necessary) metadata about its shape at runtime. Of all the type parameters, this is the only element actually instantiated by aMatrix
.
The type parameters R
and C
completely determine whether or not the matrix
shape is known at compiletime or only at runtime. They can have two kinds of
values:
 Typelevel integers: because the Rust programming language does not
support parametrization over integer values (yet), we have to simulate this
feature using types instead of literals. For example, instead of writing
Matrix<N, 2, 4, S>
for a 2x4 matrix, we have to writeMatrix<N, U2, U4, S>
, whereU2
andU4
are types exported by the root module of nalgebra, e.g.,use nalgebra::U2;
. Note that nalgebra only defines types fromU1
toU127
. If you need typelevel integers greater than 127, you have to grab them from the typenum crate instead, e.g.typenum::U1000
. RedefiningU1
toU127
instead of using types from typenum right away was necessary to improve significantly the quality of error messages when matrices with incompatible dimensions are, say, added or multiplied.  The special
Dynamic
type: using this instead of a typelevel integer indicates that the corresponding matrix dimension is not known at compiletime. For example,Matrix<N, Dynamic, Dynamic, S>
has a number of rows and number of columns that can only be known at runtime. Another typical example is a dynamicallysized column vector:Matrix<N, Dynamic, U1, S>
.
use na::{U2, U3, Dynamic, MatrixArray, MatrixVec};
use typenum::U1000;
// Statically sized and statically allocated 2x3 matrix using 32bit floats.
type Matrix2x3f = Matrix<f32, U2, U3, MatrixArray<f32, U2, U3>>;
// Halfdynamically sized and dynamically allocated matrix with
// two rows using 64bit floats.
type Matrix2xXf64 = Matrix<f64, U2, Dynamic, MatrixVec<f64, U2, Dynamic>>;
// Dynamically sized and dynamically allocated matrix with
// two rows and using 32bit signed integers.
type DMatrixi32 = Matrix<i32, Dynamic, Dynamic, MatrixVec<i32, Dynamic, Dynamic>>;
// Statically sized and statically allocated 1000x3 matrix using 32bit floats.
// Note that U1000 is imported from `typenum` while U3 comes from `nalgebra`.
type Matrix1000x3f = Matrix<f32, U1000, U3, MatrixArray<f32, U1000, U3>>;
Note that vectors are just type aliases for matrices. For a column vector
(resp. row vector), we simply use a matrix with C
set to U1
(resp. R
set
to U1
). Common lowdimensional matrices and vectors are exposed as type
aliases so that the user does not have to deal with anything but the scalar
type parameter N
:
Vector1<N>
..Vector6<N>
: are column vectors of dimension 1 to 6.Matrix1<N>
..Matrix6<N>
: are square matrices of dimension 1x1 to 6x6. Rectangular matrices have the form
MatrixIxJ<N>
whereI
andJ
are any value from 1 to 6, e.g.,Matrix4x5<N>
. DVector<N>
andDMatrix<N>
: are respectively a dynamicallysized column vector and a dynamicallysized matrix.
Internally, dynamically and staticallysized matrices do not use the same data
storage type. While the former is always allocated on the heap using a Vec
,
the latter prefers static allocation indirectly using a GenericArray
from the
genericarray crate. This distinction
is made possible by using different concrete types for the S
type parameter
of the Matrix
structure, depending on the values of the R
and C
parameters for the matrix shape. See the section dedicated to storage
buffers for more details.
Matrix construction§
All matrices and vectors with shapes known at compiletime can be created from
the values of their components given in conventional mathematical notation,
i.e., rowbyrows, using the usual ::new
method:
// A vector with three components.
let v = Vector3::new(1, 2, 3);
// A matrix with three lines and four columns.
// We chose values such that, for example, 23 is at the row 2 and column 3.
let m = Matrix3x4::new(11, 12, 13, 14,
21, 22, 23, 24,
31, 32, 33, 34);
Depending on the values of the R
and C
type parameters for the matrix
shape, the matrix construction methods listed below may have different
signatures. In particular, each constructor takes one usize
parameter for
each matrix dimension that is set to Dynamic
. Specifically:
 If
R
andC
are both typelevel integers,::from_element(e)
takes only one parameter which is the element to fill the matrix with.  If
R
isDynamic
andC
a typelevel integer,::from_element(nrows, e)
takes two parameters: one for the number of matrix rows and one for the element to fill the matrix with.  If
R
is a typelevel integer andC
isDynamic
,::from_element(ncols, e)
takes two parameters: one for the number of matrix columns and one for the element to fill the matrix with.  If both
R
andC
are equal toDynamic
, then::from_element(nrows, ncols, e)
takes three parameters: one for the number of matrix rows, one for the number of columns, and the last one for the element to fill the matrix with.
Method  Description 

::from_rows(...) 
Creates a matrix filled with the given array of rows. Panics if any two rows provided do not have the same size. 
::from_columns(...) 
Creates a matrix filled with the given array of columns. Panics if any two columns provided do not have the same size. 
::from_diagonal(...) 
Creates a diagonal matrix with its diagonal equal to the provided vector. All offdiagonal elements are set to 0 . 
::repeat(...) 
Creates a matrix filled with the given element (same as ::from_element(...) ). 
::from_element(...) 
Creates a matrix filled with the given element (same as ::repeat(...) ). 
::from_iterator(...) 
Creates a matrix filled with the content of the given iterator. The iterator must provide the matrix components in columnmajor order. 
::from_row_slice(...) 
Creates a matrix filled with the content of the given slice. Elements of the slice are provided in rowmajor order (which is the usual mathematical notation.) 
::from_column_slice(...) 
Creates a matrix filled with the content of the given slice. Elements of the slice are provided in columnmajor order. 
::from_fn(...) 
Creates a matrix filled with the values returned by the given closure of type FnMut(usize, usize) > N . This closure is called exactly once per matrix component and is given as parameter each matrix component’s 0based indices. 
::identity(...) 
Creates a matrix with 1 on its diagonal and 0 elsewhere. If the matrix to be constructed is not square, only the largest square submatrix formed by its first rows and columns is set to the identity matrix. All the other components are 0 . 
::from_diagonal_element(...) 
Creates a matrix with its diagonal filled with the given element and 0 elsewhere. If the matrix to be constructed is not square, only the largest square submatrix formed by its first rows and columns is set to the identity matrix. All the other components are set to 0 . 
::new_random(...) 
Creates a matrix with all its components initialized at random using the default random generator of the rand crate, i.e., the rand::random() function. 
// All the following matrices are equal but constructed in different ways.
let m = Matrix2x3::new(1.1, 1.2, 1.3,
2.1, 2.2, 2.3);
let m1 = Matrix2x3::from_rows(&[
RowVector3::new(1.1, 1.2, 1.3),
RowVector3::new(2.1, 2.2, 2.3)
]);
let m2 = Matrix2x3::from_columns(&[
Vector2::new(1.1, 2.1),
Vector2::new(1.2, 2.2),
Vector2::new(1.3, 2.3)
]);
let m3 = Matrix2x3::from_row_slice(&[
1.1, 1.2, 1.3,
2.1, 2.2, 2.3
]);
let m4 = Matrix2x3::from_column_slice(&[
1.1, 2.1,
1.2, 2.2,
1.3, 2.3
]);
let m5 = Matrix2x3::from_fn(r, c (r + 1) as f32 + (c + 1) as f32 / 10.0);
let m6 = Matrix2x3::from_iterator([ 1.1f32, 2.1, 1.2, 2.2, 1.3, 2.3 ].iter().cloned());
assert_eq!(m, m1); assert_eq!(m, m2); assert_eq!(m, m3);
assert_eq!(m, m4); assert_eq!(m, m5); assert_eq!(m, m6);
// All the following matrices are equal but constructed in different ways.
// This time, we used a dynamicallysized matrix to show the extra arguments
// for the matrix shape.
let dm = DMatrix::from_row_slice(4, 3, &[
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
0.0, 0.0, 0.0
]);
let dm1 = DMatrix::from_diagonal_element(4, 3, 1.0);
let dm2 = DMatrix::identity(4, 3);
let dm3 = DMatrix::from_fn(4, 3, r, c if r == c { 1.0 } else { 0.0 });
let dm4 = DMatrix::from_iterator(4, 3, [
// Components listed columnbycolumn.
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0
].iter().cloned());
assert_eq!(dm, dm1); assert_eq!(dm, dm2);
assert_eq!(dm, dm3); assert_eq!(dm, dm4);
Matrices with sizes known at compiletime also implement some construction
traits from the num
crate at well:
Trait method  Description 

Zero::zero() 
Creates a matrix filled with zeros. 
One::one() 
Creates a matrix with a diagonal set to 1 and offdiagonal elements set to 0 . 
Bounded::min_value() 
Creates a matrix filled with the minimal value of the matrix scalar type. 
Bounded::max_value() 
Creates a matrix filled with the maximal value of the matrix scalar type. 
Column vectors (which are just Matrix
with C
set to U1
) with low dimensions
from 1 to 6 have additional constructors:
::x()
,::y()
, and::z()
create a vector with, respectively, the first, second, or third coordinate set to1
and all others to0
.::a()
,::b()
, and::c()
create a vector with, respectively, the fourth, fifth, or sixth coordinate set to1
and all others to0
.
assert_eq!(Vector3::x(), Vector3::new(1.0, 0.0, 0.0));
assert_eq!(Vector3::y(), Vector3::new(0.0, 1.0, 0.0));
assert_eq!(Vector3::z(), Vector3::new(0.0, 0.0, 1.0));
assert_eq!(Vector6::a(), Vector6::new(0.0, 0.0, 0.0, 1.0, 0.0, 0.0));
assert_eq!(Vector6::b(), Vector6::new(0.0, 0.0, 0.0, 0.0, 1.0, 0.0));
assert_eq!(Vector6::c(), Vector6::new(0.0, 0.0, 0.0, 0.0, 0.0, 1.0));
Adding a _axis
suffix to those constructors, e.g., ::y_axis()
, will create
a unit vector wrapped into the Unit
structure. For example,
Vector2::y_axis()
will create a Unit<Vector2<N>>
with its the second
component of the underlying vector set to 1
.
assert_eq!(Vector4::x_axis().unwrap(), Vector4::x());
assert_eq!(Vector4::y_axis().unwrap(), Vector4::y());
assert_eq!(Vector4::z_axis().unwrap(), Vector4::z());
assert_eq!(Vector5::a_axis().unwrap(), Vector5::a());
assert_eq!(Vector5::b_axis().unwrap(), Vector5::b());
Matrix operations§
Operations between two matrices like addition, division, and multiplication, require both matrices to have compatible shapes. In particular:
 Addition require both matrices to have the same number of rows and the same number of columns.
 Multiplication and division requires the matrix on the lefthandside to have as many columns as the number of rows of the matrix on the righthandside.
Those restrictions are either checked at compiletime or at runtime, depending on the inputs types. In particular, if the matrix dimensions to be checked are typelevel integers then the check is performed at compiletime. The following shows an example of compilation error for attempting to multiply a 2x3 matrix with a 4x4 matrix:
let a = Matrix2x3::zero();
let b = Matrix4::zero();
let _ = a * b; // Compiletime error here.
error[E0277]: the trait bound `na::constraint::ShapeConstraint: na::constraint::DimEq<na::U3, na::U4>` is not satisfied
> tests/matrix.rs:27:13

27  let _ = a * b;
 ^^^^^ the trait `na::constraint::DimEq<na::U3, na::U4>` is not implemented for `na::constraint::ShapeConstraint`

= help: the following implementations were found:
= help: <na::constraint::ShapeConstraint as na::constraint::DimEq<D, D>>
= help: <na::constraint::ShapeConstraint as na::constraint::DimEq<D, na::Dynamic>>
= help: <na::constraint::ShapeConstraint as na::constraint::DimEq<na::Dynamic, D>>
= note: required because of the requirements on the impl of `na::constraint::AreMultipliable<na::U2, na::U3, na::U4, na::U4>` for `na::constraint::ShapeConstraint`
= note: required because of the requirements on the impl of `std::ops::Mul<na::Matrix<{float}, na::U4, na::U4, na::MatrixArray<{float}, na::U4, na::U4>>>` for `na::Matrix<{float}, na::U2, na::U3, na::MatrixArray<{float}, na::U2, na::U3>>`
If at least one matrix dimension to be checked is Dynamic
then the check is
performed at runtime and panics in case of mismatch. The following example
shows the runtime error for attempting to multiply a staticallysized 2x3
matrix with a dynamicallysized 4x4 matrix:
let a = Matrix2x3::zero();
let b = DMatrix::from_element(4, 4, 0.0);
let _ = a * b; // Compiles fine but panics here.
thread 'main' panicked at 'Matrix multiplication dimensions mismatch.', [...]/nalgebra/src/core/ops.rs:328
note: Run with `RUST_BACKTRACE=1` for a backtrace
The return type of a matrix operation is automatically deduced from the matrix dimensions:
 If both matrices have dimensions known at compiletime then the result also has dimensions known at compiletime.
 If both matrices have dimensions known at runtime only then the result also has dimensions known at runtime.
 If one matrix has dimensions known at runtime and the other has dimensions
known at compiletime then the result will have dimensions known at
compiletime if they can be statically deduced from the arguments. For example,
adding a
Matrix2x3
to aDMatrix
will return aMatrix2x3
. However, multiplying aMatrix2x3
to aDMatrix
will return a matrix with one dimension known at compiletime, and a second one known at runtime, i.e.,Matrix<N, U2, Dynamic, S>
(whereN
andS
are some types not detailed here). Indeed, the number of rows can be deduced from the first argument but the number of columns depends on the runtime value stored by the second argument.
let static_m = Matrix2::zero();
let dynamic_m = DMatrix::from_element(2, 2, 0.0);
let static_v = Vector2::zero();
let dynamic_v = DVector::from_element(2, 0.0);
// We know at compiletime that the sum will be a 2x2 matrix
// because of the first argument. The result is thus a `Matrix2`.
let static_plus_dynamic: Matrix2<_> = static_m + dynamic_m;
// We don't know anything about the matrix dimensions at
// compiletime. The result is thus a `DMatrix`.
let dynamic_plus_dynamic: DMatrix<_> = dynamic_m + dynamic_m;
// The result is a static vector (even if the second argument
// has a dynamic size) because we know at compiletime that
// `static_m` has two rows and that `dynamic_v` has one column.
let static_times_dynamic: Vector2<_> = static_m * dynamic_v;
// The result is a dynamic vector because we do not know at
// compiletime its number of rows.
let dynamic_times_static: DVector<_> = dynamic_m * static_v;
Matrix slicing§
Matrix (and vector) slicing allows you to take a reference to a part of any matrix. Slicing a matrix does not perform any copy, move, or allocation of the original matrix data. Instead, it stores a pointer to that data together with some metadata about the slice size and strides. Note that taking a slice of a matrix slice is allowed!
Because a matrix slice also has a type like Matrix<N, R, C, S>
(with some
special value for the buffer S
) it can usually be used just like a plain,
nonslice matrix besides three exceptions:
 Methods that require a
&mut self
cannot be called on nonmutable slices.  Matrix slices cannot be created out of thin air using the methods shown in the Matrix construction section. One must already have an allocated matrix or another slice and use one of the dedicated methods shown thereafter.
 Assignment operators do not work on any kind of slice, i.e., one cannot
write
a *= b
ifa
even ifa
is a mutable matrix slice. This is actually a limitation of the current design of nalgebra that will be fixed in the future. Usea.copy_from(&(a * b))
as a workaround.
There are three variations of matrix slicing methods. Mutable slices follow the
same semantics, except that the method names end with _mut
:
 “Fixed” slices: slices with numbers of rows and columns known at
compiletime. The name of the corresponding slicing methods usually start
with the prefix
fixed_
.
Method  Description 

.row(i) 
Reference to the ith row of self . 
.column(i) 
Reference to the ith column of self . 
.fixed_rows::<D>(i) 
Reference to the submatrix with D consecutive rows of self , starting with the ith. D must be a typelevel integer. 
.fixed_columns::<D>(i) 
Reference to the submatrix with D consecutive columns of self , starting with the ith. D must be a typelevel integer. 
.fixed_slice::<R, C>(irow, icol) 
Reference to the submatrix with R consecutive rows and C consecutive columns, starting with the irow th row and icol th column. R and C are typelevel integers. 
 “Dynamic” slices: slices with numbers of rows and columns known at runtime only.
Method  Description 

.rows(i, size) 
Reference to size rows of self , starting with the ith. 
.columns(i, size) 
Reference to size columns of self , starting with the ith. 
.slice(start, shape) 
Reference to the submatrix with shape.0 rows and shape.1 columns, starting with the start.0 th row and start.1 th column. start and shape are both tuples. 
 Slices with strides: fixed or dynamic slices that reference
nonconsecutive (but regularly spaced) rows and columns of the original
matrix. The name of the corresponding slicing methods end with
_with_step
.
Method  Description 

.fixed_rows_with_step::<D>(i, step) 
Reference to D nonconsecutive rows of self , starting with the ith. step rows of self are skipped between each referenced row. 
.fixed_columns_with_step::<D>(i, step) 
Reference to D nonconsecutive columns of self , starting with the ith. step columns of self are skipped between each referenced column. 
.fixed_slice_with_steps::<R, C>(start, step) 
Reference to R and C nonconsecutive rows and columns, starting with the component (start.0, start.1) . step.0 (resp. step.1 ) rows (resp. columns) are skipped between each referenced row (resp. column). 
.rows_with_step(i, size, step) 
Reference to size rows of self , starting with the ith. step rows are skipped between each referenced row. 
.columns_with_step(i, size, step) 
Reference to size columns of self , starting with the ith. step columns are skipped between each reference column. 
.slice_with_steps(start, shape, steps) 
Reference to shape.0 rows and shape.1 columns, starting with the (start.0, start.1) th component. step.0 (resp. step.1 ) rows (resp. columns) are skipped between each referenced row (resp. column). 
Note that the method .clone_owned()
may be used to create a plain matrix from
a slice, i.e., actually copying the referenced components into a new matrix
structure that owns its data. Whether or not the result of this cloning is a
dynamically or staticallysized matrix depends on the kind of slice.
Fixed slices will yield a staticallysized matrix while dynamic slices yield
a dynamicallysized matrice.
Matrix resizing§
The number of rows or columns of a matrix can be modified by adding or removing some of them. Similarly to slicing, two variants exist:
 “Fixed resizing” where the number of rows or columns to be removed or inserted are known at compiletime. This allows the compiler to output a staticallysized matrix when the input is also staticallysized.
Method  Description 

.remove_row(i) 
Removes the ith row. 
.remove_column(i) 
Removes the ith column. 
.remove_fixed_rows::<D>(i) 
Removes D consecutive rows, starting with the ith. 
.remove_fixed_columns::<D>(i) 
Removes D consecutive columns, starting with the ith. 
.insert_row(i, val) 
Adds one row filled with val at the ith row position. 
.insert_column(i, val) 
Adds one column filled with val at the ith row position. 
.insert_fixed_rows::<D>(i, val) 
Adds D consecutive rows filled with val starting at the ith row position. 
.insert_fixed_columns::<D>(i, val) 
Adds D consecutive columns filled with val starting at the ith column position. 
.fixed_resize::<R2, C2>(val) 
Resizes the matrix so that it contains R2 rows and C2 columns. Components are copied such that result[(i, j)] == input[(i, j)] . If the result matrix has more rows or more columns, then the extra components are initialized to val . 
 “Dynamic resizing” where the number of rows or columns to be removed or
inserted are not known at compiletime. The result matrix will always be
dynamicallysized (the affected dimensionrelated type parameter of
Matrix<...>
is set toDynamic
).
Method  Description 

.remove_rows(i, n) 
Removes n rows, starting with the ith. 
.remove_columns(i, n) 
Removes n columns, starting with the ith. 
.insert_rows(i, n, val) 
Inserts n rows filled with val starting at the ith row position. 
.insert_columns(i, n, val) 
Inserts n columns filled with val starting at the ith row position. 
.resize(new_nrows, new_ncols, val) 
Resizes the matrix so that it contains new_nrows rows and new_ncols columns. Components are copied such that result[(i, j)] == input[(i, j)] . If the result matrix has more rows or more columns, then the extra components are initialized to val . 
The implicit self
argument of those methods is always consumed in order to
reuse the input data storage to construct the output. Fixed resizing should be
preferred whenever the number of rows/columns to be inserted or removed is
known at compiletime.
It is strongly recommended to use fixed resizing whenever possible, especially when the matrix being resize has a size known at compiletime (and is thus statically allocated). Indeed, dynamic resizing will produce heapallocated results because the size of the output matrix cannot be deduced at compiletime.