Introduction
Eigen is a C++ template library for performing matrix and linear algebra operations. You can operate matrices and expressions of any size using this library. Several compilers support Eigen’s library, ensuring good-quality debugging and great reliability.

This article will discuss one of Eigen's most necessary foundational concepts. That is Block Operations and several modules of it. Every module has been explained using detailed examples to help you understand better.
Block Operations
By the name, it is very clear that Block Operations are some functionalities performed on a block. A Block Operation is a rectangular portion of any matrix or array. It can be used as rvalues as well as Ivalues.
You might wonder why we use block operations when we can perform desired calculations using simple operations.

This is because Block Operations abstraction has zero runtime cost. It optimizes the compiler and saves you a lot of time and cost. Block Operations are highly preferred when many operations are involved in getting the desired result.
How to use Block Operations?
The most commonly used Block Operations method is block(). You can use the block() method in two ways- Fixed-size and Dynamic-size. Both these expressions are equivalent but find the best applications in different cases.
- Construction of a fixed-size block expression
In this type, the size of the block is pre-defined. The block’s size cannot be changed once defined. It gives you faster results, but the size must be known at compile-time.
For example, if you want to release a block of fixed size (p,q) starting at point (i,j), the syntax will be:
matrix.block(i, j, p, q);
Refer to the example below for a better understanding.
#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
Eigen::MatrixXf matrix(5,5);
matrix << 1, 2, 3, 4, 5
6, 7, 8, 9,10,
11,12, 13,14,15,
16, 17,18,19,20,
21, 22, 23, 24, 25;
for (int i = 2; i <= 4; ++i)
{
cout << "Block of size " << i << "x" << i << endl;
cout << matrix.block(0,0,i,i) << endl << endl;
}
}
Output:
Block of size 2x2
1 2
6 7
Block of size 3x3
1 2 3
6 7 8
11 12 13
Block of size 4x4
1 2 3 4
6 7 8 5
11 12 13 14
- Construction of a dynamic-sized block expression
In this type, the size of the block is defined in the middle of the process. We can change the block’s size as per the situation's requirement. It takes a few extra seconds, but you can change the size whenever you want.
For example, if you want to release a block of dynamic size (p,q) starting at point (i,j), the syntax will be:
matrix.block<p,q>(i, j);
Refer to the example below for a better understanding.
#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
Eigen::MatrixXf matrix(5,5);
matrix << 1, 2, 3, 4, 5
6, 7, 8, 9,10,
11,12, 13,14,15,
16, 17,18,19,20,
21, 22, 23, 24, 25;
cout << "Block in the middle" << endl;
cout << matrix.block<3,3>(2,2) << endl << endl;
}
Output:
Block in the middle
13 14 15
18 19 20
23 24 25
Note that the indices in Eigen always start at 0. Therefore, points i and j are used as it is without any change.
In the above examples, we have used the block() function as a rvalue, i.e., a point from where you have to read. You can also use this function as an Ivalue, i.e., assign values to a part or block of a matrix.
Use the example below for a better understanding.
#include <Eigen/Dense>
#include <iostream>
int main()
{
Eigen::Array22i matrix;
matrix << 5,6,
7,8;
Eigen::Array22i array = Eigen::Array22i::Constant(4);
std::cout << "Array: \n" << array << "\n\n";
array.block<1,1>(2,2) = matrix;
std::cout << "New array with matrix copied as a block:\n" << array << "\n\n";
array.block(0,0,2,3) = array.block(2,1,2,3);
std::cout << "New array with matrix copied at different locations:\n" << array << "\n\n";
}
Output:
Array:
4 4 4 4
4 4 4 4
4 4 4 4
4 4 4 4
New array with matrix copied as a block:
4 4 4 4
4 4 4 4
4 4 5 6
4 4 7 8
New array with matrix copied at different locations:
5 6 4 4
4 4 4 4
4 5 6 4
4 4 4 4
Columns and Rows
There is a special set of block operations for individual rows and columns. Eigen’s library provides matrix methods- row() and col() to easily address and operate rows and columns. The arguments of these methods contain the index of the row or column to be accessed.
For ith row, the method will be:
matrix.row(i);
For jth column, the method will be:
matrix.column(j);
Note that the indices in Eigen always start at 0. Therefore, points i and j are used as it is without any change.
You can use the example below for a better understanding.
#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
Eigen::MatrixXf matrix(4,4);
matrix << 1, 2, 3, 4
5, 6, 7, 8
9,10,11,12,
13,14,15,16;
cout << "Matrix:" << endl << matrix << endl;
cout << "3rd Row: " << matrix.row(2) << endl;
matrix.col(2) += 2 * m.col(0);
cout << "After adding 2x the first column into the third column:\n";
cout << matrix << endl;
}
Output:
Matrix:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
3rd Row: 9 10 11 12
After adding 2 times the first column into the third column:
1 2 5 4
5 6 17 8
9 10 29 12
13 14 41 16
Corner-associated Operations
Eigen’s library provides a few specific methods for Block Operations that are used against one of the sides or corners of the referred matrix, known as Corner-related or Corner-associated Operations. These methods are very useful when operating row-wise, column-wise, or diagonally. You can use the matrix() methods in two ways- Fixed-size and Dynamic-size. Both these expressions are equivalent but find the best applications in different cases.
- For fixed-size block expression
Refer to the table below to learn about the methods used in different cases.
| Block Operation | Method used |
| Top-left p by q block | matrix.topLeftCorner(p,q); |
| Bottom-left p by q block | matrix.bottomLeftCorner(p,q); |
| Top-right p by q block | matrix.topRightCorner(p,q); |
| Bottom-right p by q block | matrix.bottomRightCorner(p,q); |
| Block containing the first q rows | matrix.topRows(q); |
| Block containing the last q rows | matrix.bottomRows(q); |
| Block containing the first p columns | matrix.leftCols(p); |
| Block containing the last q columns | matrix.rightCols(q); |
| Block containing the q columns starting from i | matrix.middleCols(i,q); |
| Block containing the q rows starting from i | matrix.middleRows(i,q); |
- For dynamic-sized block expression
Refer to the table below to learn about the methods used in different cases.
| Block Operation | Method used |
| Top-left p by q block | matrix.topLeftCorner<p,q>(); |
| Bottom-left p by q block | matrix.bottomLeftCorner<p,q>(); |
| Top-right p by q block | matrix.topRightCorner<p,q>(); |
| Bottom-right p by q block | matrix.bottomRightCorner<p,q>(); |
| Block containing the first q rows | matrix.topRows<q>(); |
| Block containing the last q rows | matrix.bottomRows<q>(); |
| Block containing the first p columns | matrix.leftCols<p>(); |
| Block containing the last q columns | matrix.rightCols<q>(); |
| Block containing the q columns starting from i | matrix.middleCols<q>(i); |
| Block containing the q rows starting from i | matrix.middleRows<q>(i); |
Use the example C++ code for a better understanding.
#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
Eigen::Matrix4f matrix;
matrix << 1, 2, 3, 4,
5, 6, 7, 8,
9, 10,11,12,
13,14,15,16;
cout << matrix.rightCols(3) << endl << endl;
cout << matrix.topRows<1>() << endl << endl;
}
Output:
2 3 4
6 7 8
10 11 12
14 15 16
1 2 3 4
Block Operations for Vectors
Eigen’s library comes with a special set of Block Operations designed especially for Vectors or One-dimensional arrays. You can use the vector() methods in two ways- Fixed-size and Dynamic-size. Both these expressions are equivalent but find the best applications in different cases.
- For fixed-size block expression
Refer to the table below to learn about the methods used in different cases.
| Block Operation | Method used |
| Consisting of first n elements | vector.head<n>(); |
| Consisting of last n elements | vector.tail<n>(); |
| Consisting of n elements starting from index ‘i’ | vector.segment<n>(i); |
- For dynamic-sized block expression
Refer to the table below to learn about the methods used in different cases.
| Block Operation | Method used |
| Consisting of first n elements | vector.head(n); |
| Consisting of last n elements | vector.tail(n); |
| Consisting of n elements starting from index ‘i’ | vector.segment(i,n); |
Use the example C++ code for a better understanding.
#include <Eigen/Dense>
#include <iostream>
using namespace std;
int main()
{
Eigen::ArrayXf v(8);
v << 1, 2, 3, 4, 5, 6, 7, 8;
cout << v.head(4) << endl << endl;
cout << v.tail<2>() << endl << endl;
}
Output:
1
2
3
4
7
8




