Austin Schuh | c55b017 | 2022-02-20 17:52:35 -0800 | [diff] [blame] | 1 | namespace Eigen { |
| 2 | |
| 3 | /** \eigenManualPage TutorialSlicingIndexing Slicing and Indexing |
| 4 | |
| 5 | This page presents the numerous possibilities offered by `operator()` to index sub-set of rows and columns. |
| 6 | This API has been introduced in %Eigen 3.4. |
| 7 | It supports all the feature proposed by the \link TutorialBlockOperations block API \endlink, and much more. |
| 8 | In particular, it supports \b slicing that consists in taking a set of rows, columns, or elements, uniformly spaced within a matrix or indexed from an array of indices. |
| 9 | |
| 10 | \eigenAutoToc |
| 11 | |
| 12 | \section TutorialSlicingOverview Overview |
| 13 | |
| 14 | All the aforementioned operations are handled through the generic DenseBase::operator()(const RowIndices&, const ColIndices&) method. |
| 15 | Each argument can be: |
| 16 | - An integer indexing a single row or column, including symbolic indices. |
| 17 | - The symbol Eigen::all representing the whole set of respective rows or columns in increasing order. |
| 18 | - An ArithmeticSequence as constructed by the Eigen::seq, Eigen::seqN, or Eigen::lastN functions. |
| 19 | - Any 1D vector/array of integers including %Eigen's vector/array, expressions, std::vector, std::array, as well as plain C arrays: `int[N]`. |
| 20 | |
| 21 | More generally, it can accepts any object exposing the following two member functions: |
| 22 | \code |
| 23 | <integral type> operator[](<integral type>) const; |
| 24 | <integral type> size() const; |
| 25 | \endcode |
| 26 | where `<integral type>` stands for any integer type compatible with Eigen::Index (i.e. `std::ptrdiff_t`). |
| 27 | |
| 28 | \section TutorialSlicingBasic Basic slicing |
| 29 | |
| 30 | 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: |
| 31 | |
| 32 | <table class="manual"> |
| 33 | <tr> |
| 34 | <th>function</th> |
| 35 | <th>description</th> |
| 36 | <th>example</th> |
| 37 | </tr> |
| 38 | <tr> |
| 39 | <td>\code seq(firstIdx,lastIdx) \endcode</td> |
| 40 | <td>represents the sequence of integers ranging from \c firstIdx to \c lastIdx</td> |
| 41 | <td>\code seq(2,5) <=> {2,3,4,5} \endcode</td> |
| 42 | </tr> |
| 43 | <tr> |
| 44 | <td>\code seq(firstIdx,lastIdx,incr) \endcode</td> |
| 45 | <td>same but using the increment \c incr to advance from one index to the next</td> |
| 46 | <td>\code seq(2,8,2) <=> {2,4,6,8} \endcode</td> |
| 47 | </tr> |
| 48 | <tr> |
| 49 | <td>\code seqN(firstIdx,size) \endcode</td> |
| 50 | <td>represents the sequence of \c size integers starting from \c firstIdx</td> |
| 51 | <td>\code seqN(2,5) <=> {2,3,4,5,6} \endcode</td> |
| 52 | </tr> |
| 53 | <tr> |
| 54 | <td>\code seqN(firstIdx,size,incr) \endcode</td> |
| 55 | <td>same but using the increment \c incr to advance from one index to the next</td> |
| 56 | <td>\code seqN(2,3,3) <=> {2,5,8} \endcode</td> |
| 57 | </tr> |
| 58 | </table> |
| 59 | |
| 60 | The \c firstIdx and \c 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(). |
| 61 | Here are some examples for a 2D array/matrix \c A and a 1D array/vector \c v. |
| 62 | <table class="manual"> |
| 63 | <tr> |
| 64 | <th>Intent</th> |
| 65 | <th>Code</th> |
| 66 | <th>Block-API equivalence</th> |
| 67 | </tr> |
| 68 | <tr> |
| 69 | <td>Bottom-left corner starting at row \c i with \c n columns</td> |
| 70 | <td>\code A(seq(i,last), seqN(0,n)) \endcode</td> |
| 71 | <td>\code A.bottomLeftCorner(A.rows()-i,n) \endcode</td> |
| 72 | </tr> |
| 73 | <tr> |
| 74 | <td>%Block starting at \c i,j having \c m rows, and \c n columns</td> |
| 75 | <td>\code A(seqN(i,m), seqN(i,n) \endcode</td> |
| 76 | <td>\code A.block(i,j,m,n) \endcode</td> |
| 77 | </tr> |
| 78 | <tr> |
| 79 | <td>%Block starting at \c i0,j0 and ending at \c i1,j1</td> |
| 80 | <td>\code A(seq(i0,i1), seq(j0,j1) \endcode</td> |
| 81 | <td>\code A.block(i0,j0,i1-i0+1,j1-j0+1) \endcode</td> |
| 82 | </tr> |
| 83 | <tr> |
| 84 | <td>Even columns of A</td> |
| 85 | <td>\code A(all, seq(0,last,2)) \endcode</td> |
| 86 | <td></td> |
| 87 | </tr> |
| 88 | <tr> |
| 89 | <td>First \c n odd rows A</td> |
| 90 | <td>\code A(seqN(1,n,2), all) \endcode</td> |
| 91 | <td></td> |
| 92 | </tr> |
| 93 | <tr> |
| 94 | <td>The last past one column</td> |
| 95 | <td>\code A(all, last-1) \endcode</td> |
| 96 | <td>\code A.col(A.cols()-2) \endcode</td> |
| 97 | </tr> |
| 98 | <tr> |
| 99 | <td>The middle row</td> |
| 100 | <td>\code A(last/2,all) \endcode</td> |
| 101 | <td>\code A.row((A.rows()-1)/2) \endcode</td> |
| 102 | </tr> |
| 103 | <tr> |
| 104 | <td>Last elements of v starting at i</td> |
| 105 | <td>\code v(seq(i,last)) \endcode</td> |
| 106 | <td>\code v.tail(v.size()-i) \endcode</td> |
| 107 | </tr> |
| 108 | <tr> |
| 109 | <td>Last \c n elements of v</td> |
| 110 | <td>\code v(seq(last+1-n,last)) \endcode</td> |
| 111 | <td>\code v.tail(n) \endcode</td> |
| 112 | </tr> |
| 113 | </table> |
| 114 | |
| 115 | As seen in the last exemple, referencing the <i> last n </i> elements (or rows/columns) is a bit cumbersome to write. |
| 116 | This becomes even more tricky and error prone with a non-default increment. |
| 117 | Here comes \link Eigen::lastN(SizeType) Eigen::lastN(size) \endlink, and \link Eigen::lastN(SizeType,IncrType) Eigen::lastN(size,incr) \endlink: |
| 118 | |
| 119 | <table class="manual"> |
| 120 | <tr> |
| 121 | <th>Intent</th> |
| 122 | <th>Code</th> |
| 123 | <th>Block-API equivalence</th> |
| 124 | </tr> |
| 125 | <tr> |
| 126 | <td>Last \c n elements of v</td> |
| 127 | <td>\code v(lastN(n)) \endcode</td> |
| 128 | <td>\code v.tail(n) \endcode</td> |
| 129 | </tr> |
| 130 | <tr> |
| 131 | <td>Bottom-right corner of A of size \c m times \c n</td> |
| 132 | <td>\code v(lastN(m), lastN(n)) \endcode</td> |
| 133 | <td>\code A.bottomRightCorner(m,n) \endcode</td> |
| 134 | </tr> |
| 135 | <tr> |
| 136 | <td>Bottom-right corner of A of size \c m times \c n</td> |
| 137 | <td>\code v(lastN(m), lastN(n)) \endcode</td> |
| 138 | <td>\code A.bottomRightCorner(m,n) \endcode</td> |
| 139 | </tr> |
| 140 | <tr> |
| 141 | <td>Last \c n columns taking 1 column over 3</td> |
| 142 | <td>\code A(all, lastN(n,3)) \endcode</td> |
| 143 | <td></td> |
| 144 | </tr> |
| 145 | </table> |
| 146 | |
| 147 | \section TutorialSlicingFixed Compile time size and increment |
| 148 | |
| 149 | In terms of performance, %Eigen and the compiler can take advantage of compile-time size and increment. |
| 150 | To this end, you can enforce compile-time parameters using Eigen::fix<val>. |
| 151 | Such compile-time value can be combined with the Eigen::last symbol: |
| 152 | \code v(seq(last-fix<7>, last-fix<2>)) |
| 153 | \endcode |
| 154 | In this example %Eigen knowns at compile-time that the returned expression has 6 elements. |
| 155 | It is equivalent to: |
| 156 | \code v(seqN(last-7, fix<6>)) |
| 157 | \endcode |
| 158 | |
| 159 | We can revisit the <i>even columns of A</i> example as follows: |
| 160 | \code A(all, seq(0,last,fix<2>)) |
| 161 | \endcode |
| 162 | |
| 163 | |
| 164 | \section TutorialSlicingReverse Reverse order |
| 165 | |
| 166 | Row/column indices can also be enumerated in decreasing order using a negative increment. |
| 167 | For instance, one over two columns of A from the column 20 to 10: |
| 168 | \code A(all, seq(20, 10, fix<-2>)) |
| 169 | \endcode |
| 170 | The last \c n rows starting from the last one: |
| 171 | \code A(seqN(last, n, fix<-1>), all) |
| 172 | \endcode |
| 173 | You can also use the ArithmeticSequence::reverse() method to reverse its order. |
| 174 | The previous example can thus also be written as: |
| 175 | \code A(lastN(n).reverse(), all) |
| 176 | \endcode |
| 177 | |
| 178 | |
| 179 | \section TutorialSlicingArray Array of indices |
| 180 | |
| 181 | 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. |
| 182 | |
| 183 | <table class="example"> |
| 184 | <tr><th>Example:</th><th>Output:</th></tr> |
| 185 | <tr><td> |
| 186 | \include Slicing_stdvector_cxx11.cpp |
| 187 | </td> |
| 188 | <td> |
| 189 | \verbinclude Slicing_stdvector_cxx11.out |
| 190 | </td></tr></table> |
| 191 | |
| 192 | You can also directly pass a static array: |
| 193 | <table class="example"> |
| 194 | <tr><th>Example:</th><th>Output:</th></tr> |
| 195 | <tr><td> |
| 196 | \include Slicing_rawarray_cxx11.cpp |
| 197 | </td> |
| 198 | <td> |
| 199 | \verbinclude Slicing_rawarray_cxx11.out |
| 200 | </td></tr></table> |
| 201 | |
| 202 | or expressions: |
| 203 | <table class="example"> |
| 204 | <tr><th>Example:</th><th>Output:</th></tr> |
| 205 | <tr><td> |
| 206 | \include Slicing_arrayexpr.cpp |
| 207 | </td> |
| 208 | <td> |
| 209 | \verbinclude Slicing_arrayexpr.out |
| 210 | </td></tr></table> |
| 211 | |
| 212 | 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. |
| 213 | |
| 214 | \section TutorialSlicingCustomArray Custom index list |
| 215 | |
| 216 | More generally, `operator()` can accept as inputs any object \c ind of type \c T compatible with: |
| 217 | \code |
| 218 | Index s = ind.size(); or Index s = size(ind); |
| 219 | Index i; |
| 220 | i = ind[i]; |
| 221 | \endcode |
| 222 | |
| 223 | This means you can easily build your own fancy sequence generator and pass it to `operator()`. |
| 224 | Here is an exemple enlarging a given matrix while padding the additional first rows and columns through repetition: |
| 225 | |
| 226 | <table class="example"> |
| 227 | <tr><th>Example:</th><th>Output:</th></tr> |
| 228 | <tr><td> |
| 229 | \include Slicing_custom_padding_cxx11.cpp |
| 230 | </td> |
| 231 | <td> |
| 232 | \verbinclude Slicing_custom_padding_cxx11.out |
| 233 | </td></tr></table> |
| 234 | |
| 235 | <br> |
| 236 | |
| 237 | */ |
| 238 | |
| 239 | /* |
| 240 | TODO add: |
| 241 | so_repeat_inner.cpp |
| 242 | so_repeleme.cpp |
| 243 | */ |
| 244 | } |