On this page
Slicing and Indexing
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.
Overview
All the aforementioned operations are handled through the generic DenseBase::operator()(const RowIndices&, const ColIndices&) method. Each argument can be:
- An integer indexing a single row or column, including symbolic indices.
- The symbol Eigen::all representing the whole set of respective rows or columns in increasing order.
- An ArithmeticSequence as constructed by the Eigen::seq, Eigen::seqN, or Eigen::lastN functions.
- Any 1D vector/array of integers including Eigen's vector/array, expressions, std::vector, std::array, as well as plain C arrays:
int[N].
More generally, it can accepts any object exposing the following two member functions:
<integral type> operator[](<integral type>) const;
<integral type> size() const;
where <integral type> stands for any integer type compatible with Eigen::Index (i.e. std::ptrdiff_t).
Basic slicing
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 |
|---|---|---|
|
represents the sequence of integers ranging from firstIdx to lastIdx |
|
|
same but using the increment incr to advance from one index to the next |
|
|
represents the sequence of size integers starting from firstIdx |
|
|
same but using the increment incr to advance from one index to the next |
|
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 |
|
|
Block starting at i,j having m rows, and n columns |
|
|
Block starting at i0,j0 and ending at i1,j1 |
|
|
| Even columns of A | |
|
First n odd rows A |
|
|
| The last past one column | |
|
| The middle row | |
|
| Last elements of v starting at i | |
|
Last n elements of v |
|
|
As seen in the last exemple, 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::lastN(size) , and Eigen::lastN(size,incr) :
| Intent | Code | Block-API equivalence |
|---|---|---|
Last n elements of v |
|
|
Bottom-right corner of A of size m times n |
|
|
Bottom-right corner of A of size m times n |
|
|
Last n columns taking 1 column over 3 |
|
Compile time size and increment
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:
v(seq(last-fix<7>, last-fix<2>))
In this example Eigen knowns at compile-time that the returned expression has 6 elements. It is equivalent to:
v(seqN(last-7, fix<6>))
We can revisit the even columns of A example as follows:
A(all, seq(0,last,fix<2>))
Reverse order
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:
A(all, seq(20, 10, fix<-2>))
The last n rows starting from the last one:
A(seqN(last, n, fix<-1>), all)
You can also use the ArithmeticSequence::reverse() method to reverse its order. The previous example can thus also be written as:
A(lastN(n).reverse(), all)
Array of indices
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: |
|---|---|
|
|
You can also directly pass a static array:
| Example: | Output: |
|---|---|
|
|
or expressions:
| Example: | Output: |
|---|---|
|
|
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.
Custom index list
More generally, operator() can accept as inputs any object ind of type T compatible with:
Index s = ind.size(); or Index s = size(ind);
Index i;
i = ind[i];
This means you can easily build your own fancy sequence generator and pass it to operator(). Here is an exemple enlarging a given matrix while padding the additional first rows and columns through repetition:
| Example: | Output: |
|---|---|
|
|
© Eigen.
Licensed under the MPL2 License.
https://eigen.tuxfamily.org/dox/group__TutorialSlicingIndexing.html