Numerical Computing with Eigen

Robotics, computer vision, graphics, and machine learning all run on linear algebra — vectors and matrices, multiplied and solved at speed. Eigen is the go-to C++ library for exactly that: fast, expressive, and header-only. By the end of this lesson you'll create fixed and dynamic Matrix and Vector types, fill them with the comma initializer, multiply and transpose them, take dot products, and solve a system of linear equations.

Learn Numerical Computing with Eigen in our free C++ course — an interactive lesson with worked examples, a practice exercise and a quick reference.

Part of the free C++ course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Think of Eigen as a spreadsheet engine for C++ . A Vector is a single column of numbers; a Matrix is a grid of rows and columns. Just as a spreadsheet lets you add two ranges, multiply them, or transpose a block with one formula, Eigen lets you write a * b or a.transpose() and have it mean the correct linear-algebra operation. And like choosing a fixed table size versus a table that grows, you pick a fixed-size type ( Matrix3d ) when you know the dimensions, or a dynamic one ( MatrixXd ) when they depend on the data.

1. Matrices and Vectors

Eigen's core types are Matrix and Vector . Convenient typedefs name the common ones: Vector3d is a 3-element column vector of double , Matrix3d a 3x3 matrix of double . These are fixed-size — their dimensions are known at compile time, which lets Eigen optimize hard and often skip heap allocation. For sizes decided at run time, use dynamic types like MatrixXd and VectorXd (the X means "any size"). You index elements with m(row, col) .

To fill a matrix with literal values, use Eigen's comma initializer : stream values in with << , and they fill the matrix in row-major order (left to right, top to bottom).

2. Arithmetic and Matrix Multiplication

On Matrix objects, the operators follow linear-algebra rules. + and - are element-wise, but * is true matrix multiplication (rows times columns), not element-by-element. .transpose() swaps rows and columns, and for vectors .dot() gives the scalar dot product.

Your turn. Two perpendicular unit vectors should have a dot product of zero. Fill in the blank with the dot-product call:

These lines should build a 2x2 matrix, fill it, and print its transpose. Put them in the right order:

Declare the matrix (A), begin the comma initializer with the first row (B), finish it with the second row (C), then print the transpose (D).

3. Matrix vs Array: Two Meanings of *

Sometimes you want element-by-element math, not linear algebra. Eigen separates these into the Matrix interface (linear-algebra operators) and the Array interface (coefficient-wise operators). Call .array() on a matrix to get array semantics — now * multiplies element by element — and .matrix() to switch back. Same data, two operator meanings.

4. Solving Linear Systems

A core task in numerical computing is solving A x = b for the unknown vector x . You could write x = A.inverse() * b , but explicitly inverting a matrix is slower and less numerically stable. The recommended way is a matrix decomposition that solves directly — for a general matrix, A.colPivHouseholderQr().solve(b) .

Eigen is header-only : there is no compiled .lib or .so to link. You add its include directory and write ; the compiler does the rest. That makes it trivial to drop into a project — but because it is third-party, it must first be present on the include path.

Under the hood, Eigen uses expression templates . An expression like a + b + c doesn't build two temporary matrices; instead it builds a small compile-time description of the computation and evaluates the whole thing in one pass when assigned. That is a big part of why Eigen is both expressive and fast.

2. For two Eigen matrices, what does a * b compute?

The matrix product — not element-wise. Use a.array() * b.array() for element-wise.

A decomposition such as A.colPivHouseholderQr().solve(b) , rather than A.inverse() * b .

Build a 90-degree rotation matrix with the comma initializer, multiply it by a point vector, and print the rotated result. This is matrix-times-vector in action.

Practice quiz

What kind of library is Eigen?

  • A header-only C++ template library for linear algebra
  • A compiled library you must link against
  • A Python package
  • A part of the C++ standard library

Answer: A header-only C++ template library for linear algebra. Eigen is a header-only C++ template library, so you include its headers and need no separate linking step.

What does Eigen::Matrix3d represent?

  • A 3D graphics object
  • A dynamic-size matrix of ints
  • A fixed-size 3x3 matrix of doubles
  • A 3-element vector

Answer: A fixed-size 3x3 matrix of doubles. Matrix3d is a convenience typedef for a fixed-size 3x3 matrix of double.

What is the difference between fixed-size and dynamic-size matrices in Eigen?

  • Fixed-size are always faster to compile
  • Fixed-size have dimensions known at compile time; dynamic-size are sized at run time
  • Dynamic-size cannot be multiplied
  • There is no difference

Answer: Fixed-size have dimensions known at compile time; dynamic-size are sized at run time. Fixed-size dimensions are compile-time constants (often stack-allocated); dynamic-size (MatrixXd) are chosen at run time.

What does the comma initializer do, as in m << 1, 2, 3, 4;?

  • Declares matrix dimensions
  • Prints the matrix
  • Concatenates matrices
  • Fills the matrix entries in row-major order

Answer: Fills the matrix entries in row-major order. Eigen's comma initializer fills coefficients row by row in the order written.

Which operator multiplies two Eigen matrices as matrix multiplication?

  • The * operator
  • The % operator
  • The .array() method
  • The .dot() method

Answer: The * operator. For Matrix objects, operator* performs true matrix (not element-wise) multiplication.

What does a.dot(b) compute for two vectors?

  • Their element-wise product
  • Their scalar dot product
  • A matrix
  • Their cross product

Answer: Their scalar dot product. .dot() returns the scalar dot (inner) product of two vectors.

What does m.transpose() return?

  • The determinant of m
  • m scaled by -1
  • The inverse of m
  • A view of m with rows and columns swapped

Answer: A view of m with rows and columns swapped. .transpose() gives the transpose, swapping rows and columns.

In Eigen, what is the difference between the Matrix and Array interfaces?

  • Array cannot store doubles
  • Array uses linear-algebra operators; Matrix uses element-wise ones
  • Matrix uses linear-algebra operators; Array makes * and others element-wise (coefficient-wise)
  • They are identical

Answer: Matrix uses linear-algebra operators; Array makes * and others element-wise (coefficient-wise). Matrix operators are linear-algebra (so * is matrix product); Array operators are coefficient-wise, so * multiplies element by element.

How do you typically solve a linear system A x = b in Eigen?

  • By calling A.solve(b) directly
  • By computing A.inverse() * b, or better, using a decomposition's .solve(b)
  • By calling b / A
  • It is not possible in Eigen

Answer: By computing A.inverse() * b, or better, using a decomposition's .solve(b). You can write A.inverse() * b, but using a decomposition such as colPivHouseholderQr().solve(b) is preferred for accuracy and speed.

Why is Eigen described as header-only?

  • You include its headers and compile directly, with no library to link
  • It has no documentation
  • It only supports headers up to C++11
  • It only works in header files

Answer: You include its headers and compile directly, with no library to link. Being header-only means you just add the include path and #include the headers; there is no compiled .lib or .so to link.