$darkmode
![]() |
Eigen
5.0.1-dev
|
|
This page presents the numerous possibilities offered by operator() to index sub-set of rows and columns. This API has been introduced in Eigen 3.4. It supports all the feature proposed by the block API , and much more. In particular, it supports slicing that consists in taking a set of rows, columns, or elements, uniformly spaced within a matrix or indexed from an array of indices.
All the aforementioned operations are handled through the generic DenseBase::operator()(const RowIndices&, const ColIndices&) method. Each argument can be:
int[N].More generally, it can accepts any object exposing the following two member functions:
where <integral type> stands for any integer type compatible with Eigen::Index (i.e. std::ptrdiff_t).
Taking a set of rows, columns, or elements, uniformly spaced within a matrix or vector is achieved through the Eigen::seq or Eigen::seqN functions where "seq" stands for arithmetic sequence. Their signatures are summarized below:
| function | description | example |
|---|---|---|
seq(firstIdx,lastIdx) | represents the sequence of integers ranging from firstIdx to lastIdx | seq(2,5) <=> {2,3,4,5} |
seq(firstIdx,lastIdx,incr) | same but using the increment incr to advance from one index to the next | seq(2,8,2) <=> {2,4,6,8} |
seqN(firstIdx,size) | represents the sequence of size integers starting from firstIdx | seqN(2,5) <=> {2,3,4,5,6} |
seqN(firstIdx,size,incr) | same but using the increment incr to advance from one index to the next | seqN(2,3,3) <=> {2,5,8} |
The firstIdx and lastIdx parameters can also be defined with the help of the Eigen::last symbol representing the index of the last row, column or element of the underlying matrix/vector once the arithmetic sequence is passed to it through operator(). Here are some examples for a 2D array/matrix A and a 1D array/vector v.
| Intent | Code | Block-API equivalence |
|---|---|---|
Bottom-left corner starting at row i with n columns | A.bottomLeftCorner(A.rows()-i,n) | |
Block starting at i,j having m rows, and n columns | A.block(i,j,m,n) | |
Block starting at i0,j0 and ending at i1,j1 | A.block(i0,j0,i1-i0+1,j1-j0+1) | |
| Even columns of A | ||
First n odd rows of A | ||
| The second-last column | A.col(A.cols()-2) | |
| The middle row | A.row((A.rows()-1)/2) | |
| Last elements of v starting at i | v.tail(v.size()-i) | |
Last n elements of v | v.tail(n) |
As seen in the last example, referencing the last n elements (or rows/columns) is a bit cumbersome to write. This becomes even more tricky and error prone with a non-default increment. Here comes Eigen::placeholders::lastN(SizeType), and Eigen::placeholders::lastN(SizeType,IncrType):
| Intent | Code | Block-API equivalence |
|---|---|---|
Last n elements of v | v(lastN(n)) | v.tail(n) |
Bottom-right corner of A of size m times n | A(lastN(m), lastN(n)) | A.bottomRightCorner(m,n) |
Bottom-right corner of A of size m times n | A(lastN(m), lastN(n)) | A.bottomRightCorner(m,n) |
Last n columns taking 1 column over 3 | A(all, lastN(n,3)) |
In terms of performance, Eigen and the compiler can take advantage of compile-time size and increment. To this end, you can enforce compile-time parameters using Eigen::fix<val>. Such compile-time value can be combined with the Eigen::last symbol:
In this example Eigen knowns at compile-time that the returned expression has 6 elements. It is equivalent to:
We can revisit the even columns of A example as follows:
Row/column indices can also be enumerated in decreasing order using a negative increment. For instance, one over two columns of A from the column 20 to 10:
The last n rows starting from the last one:
You can also use the ArithmeticSequence::reverse() method to reverse its order. The previous example can thus also be written as:
The generic operator() can also takes as input an arbitrary list of row or column indices stored as either an ArrayXi, a std::vector<int>, std::array<int,N>, etc.
| Example: | Output: |
|---|---|
std::vector<int> ind{4, 2, 5, 5, 3}; MatrixXi A = MatrixXi::Random(4, 6); cout << "Initial matrix A:\n" << A << "\n\n"; | Initial matrix A: 1804289383 -1550966999 1365180540 336465782 1315634022 -1016307419 -465790871 -1122281286 304089172 -1868760786 -778350579 -1287999227 -189735855 -1364114958 35005211 -2309581 1059961393 -1539069864 719885386 2044897763 -1852781081 1101513929 628175011 1734575198 A(all,ind): 1315634022 1365180540 -1016307419 -1016307419 336465782 -778350579 304089172 -1287999227 -1287999227 -1868760786 1059961393 35005211 -1539069864 -1539069864 -2309581 628175011 -1852781081 1734575198 1734575198 1101513929 |
You can also directly pass a static array:
| Example: | Output: |
|---|---|
MatrixXi A = MatrixXi::Random(4, 6); cout << "Initial matrix A:\n" << A << "\n\n"; | Initial matrix A:
1804289383 -1550966999 1365180540 336465782 1315634022 -1016307419
-465790871 -1122281286 304089172 -1868760786 -778350579 -1287999227
-189735855 -1364114958 35005211 -2309581 1059961393 -1539069864
719885386 2044897763 -1852781081 1101513929 628175011 1734575198
A(all,{4,2,5,5,3}):
1315634022 1365180540 -1016307419 -1016307419 336465782
-778350579 304089172 -1287999227 -1287999227 -1868760786
1059961393 35005211 -1539069864 -1539069864 -2309581
628175011 -1852781081 1734575198 1734575198 1101513929
|
or expressions:
| Example: | Output: |
|---|---|
Initial matrix A: 1804289383 -1550966999 1365180540 336465782 1315634022 -1016307419 -465790871 -1122281286 304089172 -1868760786 -778350579 -1287999227 -189735855 -1364114958 35005211 -2309581 1059961393 -1539069864 719885386 2044897763 -1852781081 1101513929 628175011 1734575198 A(all,ind-1): 336465782 -1550966999 1315634022 1315634022 1365180540 -1868760786 -1122281286 -778350579 -778350579 304089172 -2309581 -1364114958 1059961393 1059961393 35005211 1101513929 2044897763 628175011 628175011 -1852781081 |
When passing an object with a compile-time size such as Array4i, std::array<int,N>, or a static array, then the returned expression also exhibit compile-time dimensions.
More generally, operator() can accept as inputs any object ind of type T compatible with:
This means you can easily build your own fancy sequence generator and pass it to operator(). Here is an example enlarging a given matrix while padding the additional first rows and columns through repetition:
| Example: | Output: |
|---|---|
Initial matrix A:
1 4 7
2 5 8
3 6 9
A(pad{3,N}, pad{3,N}):
1 1 1 4 7
1 1 1 4 7
1 1 1 4 7
2 2 2 5 8
3 3 3 6 9
|