Table of contents
Here are some quick compilation instructions with GCC. To quickly test an example program, just do
g++ -I /path/to/eigen2/ my_program.cpp -o my_program
There is no library to link to. For good performance, add the -O2
compile-flag. Note however that this makes it impossible to debug inside Eigen code, as many functions get inlined. In some cases, performance can be further improved by disabling Eigen assertions: use -DEIGEN_NO_DEBUG
or -DNDEBUG
to disable them.
On the x86 architecture, the SSE2 instruction set is not enabled by default. Use -msse2
to enable it, and Eigen will then automatically enable its vectorized paths. On x86-64 and AltiVec-based architectures, vectorization is enabled by default.
#include <Eigen/Core> // import most common Eigen types USING_PART_OF_NAMESPACE_EIGEN int main(int, char *[]) { Matrix3f m3; m3 << 1, 2, 3, 4, 5, 6, 7, 8, 9; Matrix4f m4 = Matrix4f::Identity(); Vector4i v4(1, 2, 3, 4); std::cout << "m3\n" << m3 << "\nm4:\n" << m4 << "\nv4:\n" << v4 << std::endl; } | output: m3 1 2 3 4 5 6 7 8 9 m4: 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 v4: 1 2 3 4 |
#include <Eigen/Core> // import most common Eigen types USING_PART_OF_NAMESPACE_EIGEN int main(int, char *[]) { for (int size=1; size<=4; ++size) { MatrixXi m(size,size+1); // a (size)x(size+1)-matrix of int's for (int j=0; j<m.cols(); ++j) // loop over columns for (int i=0; i<m.rows(); ++i) // loop over rows m(i,j) = i+j*m.rows(); // to access matrix coefficients, // use operator()(int,int) std::cout << m << "\n\n"; } VectorXf v(4); // a vector of 4 float's // to access vector coefficients, use either operator () or operator [] v[0] = 1; v[1] = 2; v(2) = 3; v(3) = 4; std::cout << "\nv:\n" << v << std::endl; } | output: 0 1 0 2 4 1 3 5 0 3 6 9 1 4 7 10 2 5 8 11 0 4 8 12 16 1 5 9 13 17 2 6 10 14 18 3 7 11 15 19 v: 1 2 3 4 |
Eigen/Core
header only to get started with Eigen. However, some features presented in this tutorial require the Array module to be included (#include
<Eigen/Array>
). Those features are highlighted with a red star *. Notice that if you want to include all Eigen functionality at once, you can do: #include <Eigen/Eigen>
The template class Matrix takes a number of template parameters, but for now it is enough to understand the 3 first ones (and the others can then be left unspecified):
Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime>
Scalar
is the scalar type, i.e. the type of the coefficients. That is, if you want a vector of floats, choose float
here. RowsAtCompileTime
and ColsAtCompileTime
are the number of rows and columns of the matrix as known at compile-time.Vector3d
is a typedef for Matrix<double, 3, 1>
For dynamic-size, that is in order to left the number of rows or of columns unspecified at compile-time, use the special value Eigen::Dynamic. For example, VectorXd
is a typedef for
Matrix<double, Dynamic, 1>
matrix(i,j); vector(i) vector[i] vector.x() // first coefficient vector.y() // second coefficient vector.z() // third coefficient vector.w() // fourth coefficient
Notice that these coefficient access methods have assertions checking the ranges. So if you do a lot of coefficient access, these assertion can have an important cost. There are then two possibilities if you want avoid paying this cost:
Fixed-size matrix or vector | Dynamic-size matrix | Dynamic-size vector |
Matrix3f x; x = Matrix3f::Zero(); x = Matrix3f::Ones(); x = Matrix3f::Constant(value); x = Matrix3f::Identity(); x = Matrix3f::Random(); x.setZero(); x.setOnes(); x.setIdentity(); x.setConstant(value); x.setRandom(); | MatrixXf x; x = MatrixXf::Zero(rows, cols); x = MatrixXf::Ones(rows, cols); x = MatrixXf::Constant(rows, cols, value); x = MatrixXf::Identity(rows, cols); x = MatrixXf::Random(rows, cols); x.setZero(rows, cols); x.setOnes(rows, cols); x.setConstant(rows, cols, value); x.setIdentity(rows, cols); x.setRandom(rows, cols); | VectorXf x; x = VectorXf::Zero(size); x = VectorXf::Ones(size); x = VectorXf::Constant(size, value); x = VectorXf::Identity(size); x = VectorXf::Random(size); x.setZero(size); x.setOnes(size); x.setConstant(size, value); x.setIdentity(size); x.setRandom(size); |
* the Random() and setRandom() functions require the inclusion of the Array module (#include <Eigen/Array> ) | ||
Basis vectors [details] | ||
Vector3f::UnitX() // 1 0 0 Vector3f::UnitY() // 0 1 0 Vector3f::UnitZ() // 0 0 1 | VectorXf::Unit(size,i) VectorXf::Unit(4,1) == Vector4f(0,1,0,0) == Vector4f::UnitY() |
Here is an usage example:
cout << MatrixXf::Constant(2, 3, sqrt(2)) << endl; RowVector3i v; v.setConstant(6); cout << "v = " << v << endl; | output: 1.41 1.41 1.41 1.41 1.41 1.41 v = 6 6 6 |
The destination matrix is automatically resized in any assignment:
Of course, fixed-size matrices can't be resized.Matrix3f m; m << 1, 2, 3, 4, 5, 6, 7, 8, 9; cout << m; | output: 1 2 3 4 5 6 7 8 9 |
Not excited by the above example? Then look at the following one where the matrix is set by blocks:
int rows=5, cols=5; MatrixXf m(rows,cols); m << (Matrix3f() << 1, 2, 3, 4, 5, 6, 7, 8, 9).finished(), MatrixXf::Zero(3,cols-3), MatrixXf::Zero(rows-3,3), MatrixXf::Identity(rows-3,cols-3); cout << m; | output: 1 2 3 0 0 4 5 6 0 0 7 8 9 0 0 0 0 0 1 0 0 0 0 0 1 |
Side note: here .finished() is used to get the actual matrix object once the comma initialization of our temporary submatrix is done. Note that despite the apparent complexity of such an expression, Eigen's comma initializer usually compiles to very optimized code without any overhead.
mat4 -= mat1*1.5 + mat2 * (mat3/4);
matrix/vector product | col2 = mat1 * col1; row2 = row1 * mat1; row1 *= mat1; mat3 = mat1 * mat2; mat3 *= mat1; |
add/subtract | mat3 = mat1 + mat2; mat3 += mat1; mat3 = mat1 - mat2; mat3 -= mat1; |
scalar product | mat3 = mat1 * s1; mat3 = s1 * mat1; mat3 *= s1; mat3 = mat1 / s1; mat3 /= s1; |
In Eigen, only traditional mathematical operators can be used right away. But don't worry, thanks to the .cwise() operator prefix, Eigen's matrices are also very powerful as a numerical container supporting most common coefficient-wise operators.
|
|
#include
<Eigen/Array>
).
Side note: If you think that the .cwise() syntax is too verbose for your own taste and prefer to have non-conventional mathematical operators directly available, then feel free to extend MatrixBase as described here.
So far, we saw the notation
mat1*mat2
mat1.cwise()*mat2
dot product (inner product) | scalar = vec1.dot(vec2); |
outer product | mat = vec1 * vec2.transpose(); |
cross product | #include <Eigen/Geometry>
vec3 = vec1.cross(vec2);
|
5 3 1 mat = 2 7 8 9 4 6 | mat.minCoeff(); | 1 |
mat.colwise().minCoeff(); | 2 3 1 | |
mat.rowwise().minCoeff(); | 1 2 4 |
Also note that maxCoeff and minCoeff can takes optional arguments returning the coordinates of the respective min/max coeff: maxCoeff(int* i, int* j) , minCoeff(int* i, int* j) .
Side note: The all() and any() functions are especially useful in combinaison with coeff-wise comparison operators (example).
mat1.row(i) = mat2.col(j); mat1.col(j1).swap(mat1.col(j2));
Read-write access to sub-vectors:
Default versions | Optimized versions when the size is known at compile time |
|
vec1.start(n) | vec1.start<n>() | the first n coeffs |
vec1.end(n) | vec1.end<n>() | the last n coeffs |
vec1.segment(pos,n) | vec1.segment<n>(pos) | the size coeffs in the range [ pos : pos + n [ |
Read-write access to sub-matrices: | ||
mat1.block(i,j,rows,cols) | mat1.block<rows,cols>(i,j) | the rows x cols sub-matrix starting from position ( i ,j ) |
mat1.corner(TopLeft,rows,cols) mat1.corner(TopRight,rows,cols) mat1.corner(BottomLeft,rows,cols) mat1.corner(BottomRight,rows,cols) | mat1.corner<rows,cols>(TopLeft) mat1.corner<rows,cols>(TopRight) mat1.corner<rows,cols>(BottomLeft) mat1.corner<rows,cols>(BottomRight) | the rows x cols sub-matrix taken in one of the four corners |
mat4x4.minor(i,j) = mat3x3; mat3x3 = mat4x4.minor(i,j); | minor (read-write) |
make a diagonal matrix from a vector this product is automatically optimized ! | mat3 = mat1 * vec2.asDiagonal(); |
Access the diagonal of a matrix as a vector (read/write) | vec1 = mat1.diagonal(); mat1.diagonal() = vec1; |
transposition (read-write) | mat3 = mat1.transpose() * mat2; mat3.transpose() = mat1 * mat2.transpose(); |
adjoint (read only) | mat3 = mat1.adjoint() * mat2; |
Dot-product of two vectors | vec1.dot(vec2); |
norm of a vector squared norm of a vector | vec.norm(); vec.squaredNorm() |
returns a normalized vector normalize a vector | vec3 = vec1.normalized(); vec1.normalize(); |
Extract triangular matrices from a given matrix m: | m.part<Eigen::UpperTriangular>() m.part<Eigen::StrictlyUpperTriangular>() m.part<Eigen::UnitUpperTriangular>() m.part<Eigen::LowerTriangular>() m.part<Eigen::StrictlyLowerTriangular>() m.part<Eigen::UnitLowerTriangular>() |
Write to triangular parts of a matrix m: | m1.part<Eigen::UpperTriangular>() = m2; m1.part<Eigen::StrictlyUpperTriangular>() = m2; m1.part<Eigen::LowerTriangular>() = m2; m1.part<Eigen::StrictlyLowerTriangular>() = m2; |
Special: take advantage of symmetry (selfadjointness) when copying an expression into a matrix | m.part<Eigen::SelfAdjoint>() = someSelfadjointMatrix;
m1.part<Eigen::SelfAdjoint>() = m2 + m2.adjoint(); // m2 + m2.adjoint() is selfadjoint
|