Table of contents
1.
Introduction
2.
Block Operations
2.1.
How to use Block Operations?
2.2.
Columns and Rows
2.3.
Corner-associated Operations
2.4.
Block Operations for Vectors
3.
Frequently Asked Questions
3.1.
Explain PCA.
3.2.
What is a Symmetric Matrix?
3.3.
Mention the compilers Eigen supports.
3.4.
Describe Sparse Matrix.
4.
Conclusion
Last Updated: Mar 27, 2024
Medium

How to use Block Operations

Author Rupal Saluja
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

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.

logo of eigen

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.

notion of block 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

Frequently Asked Questions

Explain PCA.

PCA stands for Principal Component Analysis. It is an unsupervised dimensionality reduction approach. In this approach, we find the nearest hyperplane to the given data and project the data on it. Throughout this process, we preserve the variance o get accurate results.

What is a Symmetric Matrix?

A Symmetric Matrix is a matrix whose square matrix is equal to its transpose matrix in a linear algebraic approach.

Mention the compilers Eigen supports.

The compilers that Eigen supports are Intel C++ Compiler, MinGW, MSVC, and GCC.

Describe Sparse Matrix.

A Sparse Matrix is a matrix with a good number of zeroes. In other words, it contains very few non-zero elements.

Conclusion

To cut it short, we understood the Block Operations and various aspects related to Eigen’s Block Operations. This includes using them, their columns and rows, corner-related operations, and block operations for vectors.

We hope the above discussion helped you understand the perks of Eigen’s Block Operations and can be used for future reference whenever needed. To learn more about Eigen and its components, you can refer to blogs on Eigen's GeometryEigen's Class HierarchyPreprocessor Tokens recognized by EigenAdvanced Methods for initializing Matrices, and Introduction to Sparse Matrix.

Visit our website to read more such blogs. Make sure you enroll in our courses, take mock tests, solve problems, and interview puzzles. Also, you can pay attention to interview stuff- interview experiences and an interview bundle for placement preparations. Do upvote our blog to help fellow ninjas grow.

Happy Coding!

Live masterclass