aboutsummaryrefslogtreecommitdiffhomepage
path: root/doc
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2018-11-09 11:35:27 +0100
committerGravatar Gael Guennebaud <g.gael@free.fr>2018-11-09 11:35:27 +0100
commitd7c644213cbf548f67aeb7ed6f872aef96c1dbd2 (patch)
tree576a7e2400362015c89b7433571198fecc8ed579 /doc
parenta368848473967548572b69a841b70f9f123b9559 (diff)
Add and update manual pages for slicing, indexing, and reshaping.
Diffstat (limited to 'doc')
-rw-r--r--doc/Manual.dox4
-rw-r--r--doc/TutorialReshape.dox82
-rw-r--r--doc/TutorialReshapeSlicing.dox65
-rw-r--r--doc/TutorialSlicingIndexing.dox244
-rw-r--r--doc/snippets/Slicing_arrayexpr.cpp4
-rw-r--r--doc/snippets/Slicing_custom_padding_cxx11.cpp12
-rw-r--r--doc/snippets/Slicing_rawarray_cxx11.cpp5
-rw-r--r--doc/snippets/Slicing_stdvector_cxx11.cpp4
-rw-r--r--doc/snippets/Tutorial_reshaped_vs_resize_1.cpp5
-rw-r--r--doc/snippets/Tutorial_reshaped_vs_resize_2.cpp6
10 files changed, 365 insertions, 66 deletions
diff --git a/doc/Manual.dox b/doc/Manual.dox
index 342b145fd..cb0e7d156 100644
--- a/doc/Manual.dox
+++ b/doc/Manual.dox
@@ -64,13 +64,15 @@ namespace Eigen {
\ingroup DenseMatrixManipulation_chapter */
/** \addtogroup TutorialBlockOperations
\ingroup DenseMatrixManipulation_chapter */
+/** \addtogroup TutorialSlicingIndexing
+ \ingroup DenseMatrixManipulation_chapter */
/** \addtogroup TutorialAdvancedInitialization
\ingroup DenseMatrixManipulation_chapter */
/** \addtogroup TutorialReductionsVisitorsBroadcasting
\ingroup DenseMatrixManipulation_chapter */
/** \addtogroup TutorialMapClass
\ingroup DenseMatrixManipulation_chapter */
-/** \addtogroup TutorialReshapeSlicing
+/** \addtogroup TutorialReshape
\ingroup DenseMatrixManipulation_chapter */
/** \addtogroup TopicAliasing
\ingroup DenseMatrixManipulation_chapter */
diff --git a/doc/TutorialReshape.dox b/doc/TutorialReshape.dox
new file mode 100644
index 000000000..5b4022a3b
--- /dev/null
+++ b/doc/TutorialReshape.dox
@@ -0,0 +1,82 @@
+namespace Eigen {
+
+/** \eigenManualPage TutorialReshape Reshape
+
+Since the version 3.4, %Eigen exposes convenient methods to reshape a matrix to another matrix of different sizes or vector.
+All cases are handled via the DenseBase::reshaped(NRowsType,NColsType) and DenseBase::reshaped() functions.
+Those functions do not perform in-place reshaping, but instead return a <i> view </i> on the input expression.
+
+\eigenAutoToc
+
+\section TutorialReshapeMat2Mat Reshaped 2D views
+
+The more general reshaping transformation is handled via: `reshaped(nrows,ncols)`.
+Here is an example reshaping a 4x4 matrix to a 2x8 one:
+
+<table class="example">
+<tr><th>Example:</th><th>Output:</th></tr>
+<tr><td>
+\include MatrixBase_reshaped_int_int.cpp
+</td>
+<td>
+\verbinclude MatrixBase_reshaped_int_int.out
+</td></tr></table>
+
+By default, the input coefficients are always interpreted in column-major order regardless of the storage order of the input expression.
+For more control on ordering, compile-time sizes, and automatic size deduction, please see de documentation of DenseBase::reshaped(NRowsType,NColsType) that contains all the details with many examples.
+
+
+\section TutorialReshapeMat2Vec 1D linear views
+
+A very common usage of reshaping is to create a 1D linear view over a given 2D matrix or expression.
+In this case, sizes can be deduced and thus omitted as in the following example:
+
+<table class="example">
+<tr><th>Example:</th></tr>
+<tr><td>
+\include MatrixBase_reshaped_to_vector.cpp
+</td></tr>
+<tr><th>Output:</th></tr>
+<tr><td>
+\verbinclude MatrixBase_reshaped_to_vector.out
+</td></tr></table>
+
+This shortcut always returns a column vector and by default input coefficients are always interpreted in column-major order.
+Again, see the documentation of DenseBase::reshaped() for more control on the ordering.
+
+\section TutorialReshapeInPlace
+
+The above examples create reshaped views, but what about reshaping inplace a given matrix?
+Of course this task in only conceivable for matrix and arrays having runtime dimensions.
+In many cases, this can be accomplished via PlainObjectBase::resize(Index,Index):
+
+<table class="example">
+<tr><th>Example:</th></tr>
+<tr><td>
+\include Tutorial_reshaped_vs_resize_1.cpp
+</td></tr>
+<tr><th>Output:</th></tr>
+<tr><td>
+\verbinclude Tutorial_reshaped_vs_resize_1.out
+</td></tr></table>
+
+However beware that unlike \c reshaped, the result of \c resize depends on the input storage order.
+It thus behaves similarly to `reshaped<AutoOrder>`:
+
+<table class="example">
+<tr><th>Example:</th></tr>
+<tr><td>
+\include Tutorial_reshaped_vs_resize_2.cpp
+</td></tr>
+<tr><th>Output:</th></tr>
+<tr><td>
+\verbinclude Tutorial_reshaped_vs_resize_2.out
+</td></tr></table>
+
+Finally, assigning a reshaped matrix to itself is currently not supported and will result to undefined-behavior because of \link TopicAliasing aliasing \endlink.
+The following is forbidden: \code A = A.reshaped(2,8); \endcode
+This is OK: \code A = A.reshaped(2,8).eval(); \endcode
+
+*/
+
+}
diff --git a/doc/TutorialReshapeSlicing.dox b/doc/TutorialReshapeSlicing.dox
deleted file mode 100644
index 44de786ea..000000000
--- a/doc/TutorialReshapeSlicing.dox
+++ /dev/null
@@ -1,65 +0,0 @@
-namespace Eigen {
-
-/** \eigenManualPage TutorialReshapeSlicing Reshape and Slicing
-
-%Eigen does not expose convenient methods to take slices or to reshape a matrix yet.
-Nonetheless, such features can easily be emulated using the Map class.
-
-\eigenAutoToc
-
-\section TutorialReshape Reshape
-
-A reshape operation consists in modifying the sizes of a matrix while keeping the same coefficients.
-Instead of modifying the input matrix itself, which is not possible for compile-time sizes, the approach consist in creating a different \em view on the storage using class Map.
-Here is a typical example creating a 1D linear view of a matrix:
-
-<table class="example">
-<tr><th>Example:</th><th>Output:</th></tr>
-<tr><td>
-\include Tutorial_ReshapeMat2Vec.cpp
-</td>
-<td>
-\verbinclude Tutorial_ReshapeMat2Vec.out
-</td></tr></table>
-
-Remark how the storage order of the input matrix modifies the order of the coefficients in the linear view.
-Here is another example reshaping a 2x6 matrix to a 6x2 one:
-<table class="example">
-<tr><th>Example:</th><th>Output:</th></tr>
-<tr><td>
-\include Tutorial_ReshapeMat2Mat.cpp
-</td>
-<td>
-\verbinclude Tutorial_ReshapeMat2Mat.out
-</td></tr></table>
-
-
-
-\section TutorialSlicing Slicing
-
-Slicing consists in taking a set of rows, columns, or elements, uniformly spaced within a matrix.
-Again, the class Map allows to easily mimic this feature.
-
-For instance, one can skip every P elements in a vector:
-<table class="example">
-<tr><th>Example:</th><th>Output:</th></tr>
-<tr><td>
-\include Tutorial_SlicingVec.cpp
-</td>
-<td>
-\verbinclude Tutorial_SlicingVec.out
-</td></tr></table>
-
-One can also take one column over three using an adequate outer-stride or inner-stride depending on the actual storage order:
-<table class="example">
-<tr><th>Example:</th><th>Output:</th></tr>
-<tr><td>
-\include Tutorial_SlicingCol.cpp
-</td>
-<td>
-\verbinclude Tutorial_SlicingCol.out
-</td></tr></table>
-
-*/
-
-}
diff --git a/doc/TutorialSlicingIndexing.dox b/doc/TutorialSlicingIndexing.dox
new file mode 100644
index 000000000..2e5543539
--- /dev/null
+++ b/doc/TutorialSlicingIndexing.dox
@@ -0,0 +1,244 @@
+namespace Eigen {
+
+/** \eigenManualPage TutorialSlicingIndexing Slicing and Indexing
+
+This pape 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 \link TutorialBlockOperations block API \endlink, and much more.
+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.
+
+\eigenAutoToc
+
+\section TutorialSlicingOverview 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:
+ \code
+ <integral type> operator[](<integral type>) const;
+ <integral type> size() const;
+ \endcode
+where `<integral type>` stands for any integer type compatible with Eigen::Index (i.e. `std::ptrdiff_t`).
+
+\section TutorialSlicingBasic 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:
+
+<table class="manual">
+<tr>
+ <th>function</th>
+ <th>description</th>
+ <th>example</th>
+</tr>
+<tr>
+ <td>\code seq(firstIdx,lastIdx) \endcode</td>
+ <td>represents the sequence of integers ranging from \c firstIdx to \c lastIdx</td>
+ <td>\code seq(2,5) <=> {2,3,4,5} \endcode</td>
+</tr>
+<tr>
+ <td>\code seq(firstIdx,lastIdx,incr) \endcode</td>
+ <td>same but using the increment \c incr to advance from one index to the next</td>
+ <td>\code seq(2,8,2) <=> {2,4,6,8} \endcode</td>
+</tr>
+<tr>
+ <td>\code seqN(firstIdx,size) \endcode</td>
+ <td>represents the sequence of \c size integers starting from \c firstIdx</td>
+ <td>\code seqN(2,5) <=> {2,3,4,5,6} \endcode</td>
+</tr>
+<tr>
+ <td>\code seqN(firstIdx,size,incr) \endcode</td>
+ <td>same but using the increment \c incr to advance from one index to the next</td>
+ <td>\code seqN(2,3,3) <=> {2,5,8} \endcode</td>
+</tr>
+</table>
+
+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().
+Here are some examples for a 2D array/matrix \c A and a 1D array/vector \c v.
+<table class="manual">
+<tr>
+ <th>Intent</th>
+ <th>Code</th>
+ <th>Block-API equivalence</th>
+</tr>
+<tr>
+ <td>Bottom-left corner starting at row \c i with \c n columns</td>
+ <td>\code A(seq(i,last), seqN(0,n)) \endcode</td>
+ <td>\code A.bottomLeftCorner(A.rows()-i,n) \endcode</td>
+</tr>
+<tr>
+ <td>%Block starting at \c i,j having \c m rows, and \c n columns</td>
+ <td>\code A(seqN(i,m), seqN(i,n) \endcode</td>
+ <td>\code A.block(i,j,m,n) \endcode</td>
+</tr>
+<tr>
+ <td>%Block starting at \c i0,j0 and ending at \c i1,j1</td>
+ <td>\code A(seq(i0,i1), seq(j0,j1) \endcode</td>
+ <td>\code A.block(i0,j0,i1-i0+1,j1-j0+1) \endcode</td>
+</tr>
+<tr>
+ <td>Even columns of A</td>
+ <td>\code A(all, seq(0,last,2)) \endcode</td>
+ <td></td>
+</tr>
+<tr>
+ <td>First \c n odd rows A</td>
+ <td>\code A(seqN(1,n,2), all) \endcode</td>
+ <td></td>
+</tr>
+<tr>
+ <td>The last past one column</td>
+ <td>\code A(all, last-1) \endcode</td>
+ <td>\code A.col(A.cols()-2) \endcode</td>
+</tr>
+<tr>
+ <td>The middle row</td>
+ <td>\code A(last/2,all) \endcode</td>
+ <td>\code A.row((A.rows()-1)/2) \endcode</td>
+</tr>
+<tr>
+ <td>Last elements of v starting at i</td>
+ <td>\code v(seq(i,last)) \endcode</td>
+ <td>\code v.tail(v.size()-i) \endcode</td>
+</tr>
+<tr>
+ <td>Last \c n elements of v</td>
+ <td>\code v(seq(last+1-n,last)) \endcode</td>
+ <td>\code v.tail(n) \endcode</td>
+</tr>
+</table>
+
+As seen in the last exemple, referencing the <i> last n </i> 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 \link Eigen::lastN(SizeType) Eigen::lastN(size) \endlink, and \link Eigen::lastN(SizeType,IncrType) Eigen::lastN(size,incr) \endlink:
+
+<table class="manual">
+<tr>
+ <th>Intent</th>
+ <th>Code</th>
+ <th>Block-API equivalence</th>
+</tr>
+<tr>
+ <td>Last \c n elements of v</td>
+ <td>\code v(lastN(n)) \endcode</td>
+ <td>\code v.tail(n) \endcode</td>
+</tr>
+<tr>
+ <td>Bottom-right corner of A of size \c m times \c n</td>
+ <td>\code v(lastN(m), lastN(n)) \endcode</td>
+ <td>\code A.bottomRightCorner(m,n) \endcode</td>
+</tr>
+<tr>
+ <td>Bottom-right corner of A of size \c m times \c n</td>
+ <td>\code v(lastN(m), lastN(n)) \endcode</td>
+ <td>\code A.bottomRightCorner(m,n) \endcode</td>
+</tr>
+<tr>
+ <td>Last \c n columns taking 1 column over 3</td>
+ <td>\code A(all, lastN(n,3)) \endcode</td>
+ <td></td>
+</tr>
+</table>
+
+\section TutorialSlicingFixed 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:
+\code v(seq(last-fix<7>, last-fix<2>))
+\endcode
+In this example %Eigen knowns at compile-time that the returned expression has 6 elements.
+It is equivalent to:
+\code v(seqN(last-7, fix<6>))
+\endcode
+
+We can revisit the <i>even columns of A</i> example as follows:
+\code A(all, seq(0,last,fix<2>))
+\endcode
+
+
+\section TutorialSlicingReverse 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:
+\code A(all, seq(20, 10, fix<-2>))
+\endcode
+The last \c n rows starting from the last one:
+\code A(seqN(last, n, fix<-1>), all)
+\endcode
+You can also use the ArithmeticSequence::reverse() method to reverse its order.
+The previous example can thus also be written as:
+\code A(lastN(n).reverse(), all)
+\endcode
+
+
+\section TutorialSlicingArray 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.
+
+<table class="example">
+<tr><th>Example:</th><th>Output:</th></tr>
+<tr><td>
+\include Slicing_stdvector_cxx11.cpp
+</td>
+<td>
+\verbinclude Slicing_stdvector_cxx11.out
+</td></tr></table>
+
+You can also directly pass a static array:
+<table class="example">
+<tr><th>Example:</th><th>Output:</th></tr>
+<tr><td>
+\include Slicing_rawarray_cxx11.cpp
+</td>
+<td>
+\verbinclude Slicing_rawarray_cxx11.out
+</td></tr></table>
+
+or expressions:
+<table class="example">
+<tr><th>Example:</th><th>Output:</th></tr>
+<tr><td>
+\include Slicing_arrayexpr.cpp
+</td>
+<td>
+\verbinclude Slicing_arrayexpr.out
+</td></tr></table>
+
+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.
+
+\section TutorialSlicingCustomArray Custom index list
+
+More generally, `operator()` can accept as inputs any object \c ind of type \c T compatible with:
+\code
+Index s = ind.size(); or Index s = size(ind);
+Index i;
+i = ind[i];
+\endcode
+
+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 first rows and columns through repetition:
+
+<table class="example">
+<tr><th>Example:</th><th>Output:</th></tr>
+<tr><td>
+\include Slicing_custom_padding_cxx11.cpp
+</td>
+<td>
+\verbinclude Slicing_custom_padding_cxx11.out
+</td></tr></table>
+
+<br>
+
+*/
+
+/*
+TODO add:
+so_repeat_inner.cpp
+so_repeleme.cpp
+*/
+}
diff --git a/doc/snippets/Slicing_arrayexpr.cpp b/doc/snippets/Slicing_arrayexpr.cpp
new file mode 100644
index 000000000..00b689b90
--- /dev/null
+++ b/doc/snippets/Slicing_arrayexpr.cpp
@@ -0,0 +1,4 @@
+ArrayXi ind(5); ind<<4,2,5,5,3;
+MatrixXi A = MatrixXi::Random(4,6);
+cout << "Initial matrix A:\n" << A << "\n\n";
+cout << "A(all,ind-1):\n" << A(all,ind-1) << "\n\n"; \ No newline at end of file
diff --git a/doc/snippets/Slicing_custom_padding_cxx11.cpp b/doc/snippets/Slicing_custom_padding_cxx11.cpp
new file mode 100644
index 000000000..5dac3d7c9
--- /dev/null
+++ b/doc/snippets/Slicing_custom_padding_cxx11.cpp
@@ -0,0 +1,12 @@
+struct pad {
+ Index size() const { return out_size; }
+ Index operator[] (Index i) const { return std::max<Index>(0,i-(out_size-in_size)); }
+ Index in_size, out_size;
+};
+
+Matrix3i A;
+A.reshaped() = VectorXi::LinSpaced(9,1,9);
+cout << "Initial matrix A:\n" << A << "\n\n";
+MatrixXi B(5,5);
+B = A(pad{3,5}, pad{3,5});
+cout << "A(pad{3,N}, pad{3,N}):\n" << B << "\n\n"; \ No newline at end of file
diff --git a/doc/snippets/Slicing_rawarray_cxx11.cpp b/doc/snippets/Slicing_rawarray_cxx11.cpp
new file mode 100644
index 000000000..0d3287a42
--- /dev/null
+++ b/doc/snippets/Slicing_rawarray_cxx11.cpp
@@ -0,0 +1,5 @@
+#if EIGEN_HAS_STATIC_ARRAY_TEMPLATE
+MatrixXi A = MatrixXi::Random(4,6);
+cout << "Initial matrix A:\n" << A << "\n\n";
+cout << "A(all,{4,2,5,5,3}):\n" << A(all,{4,2,5,5,3}) << "\n\n";
+#endif \ No newline at end of file
diff --git a/doc/snippets/Slicing_stdvector_cxx11.cpp b/doc/snippets/Slicing_stdvector_cxx11.cpp
new file mode 100644
index 000000000..469651e38
--- /dev/null
+++ b/doc/snippets/Slicing_stdvector_cxx11.cpp
@@ -0,0 +1,4 @@
+std::vector<int> ind{4,2,5,5,3};
+MatrixXi A = MatrixXi::Random(4,6);
+cout << "Initial matrix A:\n" << A << "\n\n";
+cout << "A(all,ind):\n" << A(all,ind) << "\n\n"; \ No newline at end of file
diff --git a/doc/snippets/Tutorial_reshaped_vs_resize_1.cpp b/doc/snippets/Tutorial_reshaped_vs_resize_1.cpp
new file mode 100644
index 000000000..686b96c38
--- /dev/null
+++ b/doc/snippets/Tutorial_reshaped_vs_resize_1.cpp
@@ -0,0 +1,5 @@
+MatrixXi m = Matrix4i::Random();
+cout << "Here is the matrix m:" << endl << m << endl;
+cout << "Here is m.reshaped(2, 8):" << endl << m.reshaped(2, 8) << endl;
+m.resize(2,8);
+cout << "Here is the matrix m after m.resize(2,8):" << endl << m << endl; \ No newline at end of file
diff --git a/doc/snippets/Tutorial_reshaped_vs_resize_2.cpp b/doc/snippets/Tutorial_reshaped_vs_resize_2.cpp
new file mode 100644
index 000000000..50dc45488
--- /dev/null
+++ b/doc/snippets/Tutorial_reshaped_vs_resize_2.cpp
@@ -0,0 +1,6 @@
+Matrix<int,Dynamic,Dynamic,RowMajor> m = Matrix4i::Random();
+cout << "Here is the matrix m:" << endl << m << endl;
+cout << "Here is m.reshaped(2, 8):" << endl << m.reshaped(2, 8) << endl;
+cout << "Here is m.reshaped<AutoOrder>(2, 8):" << endl << m.reshaped<AutoOrder>(2, 8) << endl;
+m.resize(2,8);
+cout << "Here is the matrix m after m.resize(2,8):" << endl << m << endl;