aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Tim Holy <holy@wustl.edu>2012-02-08 22:11:12 +0100
committerGravatar Tim Holy <holy@wustl.edu>2012-02-08 22:11:12 +0100
commit44b19b432c1fc86da7a1836a23007504d995009a (patch)
tree916ea545d332ba60a8c4d3f5512345a75097ee05
parent5bb34fd14c74021314744cb1d4a82a39449359cf (diff)
Add a tutorial page on the Map class, and add a section to FunctionsTakingEigenTypes about multiple-argument functions and the pitfalls when using Map/Expression types.
-rw-r--r--doc/C09_TutorialSparse.dox4
-rw-r--r--doc/C10_TutorialMapClass.dox96
-rw-r--r--doc/I13_FunctionsTakingEigenTypes.dox21
-rw-r--r--doc/Overview.dox1
-rw-r--r--doc/snippets/Tutorial_Map_rowmajor.cpp7
-rw-r--r--doc/snippets/Tutorial_Map_using.cpp21
6 files changed, 146 insertions, 4 deletions
diff --git a/doc/C09_TutorialSparse.dox b/doc/C09_TutorialSparse.dox
index 4507c6812..86a6d1430 100644
--- a/doc/C09_TutorialSparse.dox
+++ b/doc/C09_TutorialSparse.dox
@@ -4,7 +4,7 @@ namespace Eigen {
\ingroup Tutorial
\li \b Previous: \ref TutorialGeometry
-\li \b Next: TODO
+\li \b Next: \ref TutorialMapClass
\b Table \b of \b contents \n
- \ref TutorialSparseIntro
@@ -318,7 +318,7 @@ The compute() method is equivalent to calling both analyzePattern() and factoriz
Finally, each solver provides some specific features, such as determinant, access to the factors, controls of the iterations, and so on.
More details are availble in the documentations of the respective classes.
-\li \b Next: TODO
+\li \b Next: \ref TutorialMapClass
*/
diff --git a/doc/C10_TutorialMapClass.dox b/doc/C10_TutorialMapClass.dox
new file mode 100644
index 000000000..09e792792
--- /dev/null
+++ b/doc/C10_TutorialMapClass.dox
@@ -0,0 +1,96 @@
+namespace Eigen {
+
+/** \page TutorialMapClass Tutorial page 10 - Interfacing with C/C++ arrays and external libraries: the %Map class
+
+\ingroup Tutorial
+
+\li \b Previous: \ref TutorialSparse
+\li \b Next: \ref TODO
+
+This tutorial page explains how to work with "raw" C++ arrays. This can be useful in a variety of contexts, particularly when "importing" vectors and matrices from other libraries into Eigen.
+
+\b Table \b of \b contents
+ - \ref TutorialMapIntroduction
+ - \ref TutorialMapTypes
+ - \ref TutorialMapUsing
+ - \ref TutorialMapPlacementNew
+
+\section TutorialMapIntroduction Introduction
+
+Occasionally you may have a pre-defined array of numbers that you want to use within Eigen as a vector or matrix. While one option is to make a copy of the data, most commonly you probably want to re-use this memory as an Eigen type. Fortunately, this is very easy with the Map class.
+
+\section TutorialMapTypes Map types and declaring Map variables
+
+A Map object has a type defined by its Eigen equivalent:
+\code
+Map<Matrix<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime> >
+\endcode
+Note that, in this default case, a Map requires just a single template parameter.
+
+To construct a Map variable, you need two other pieces of information: a pointer to the region of memory defining the array of coefficients, and the desired shape of the matrix or vector. For example, to define a matrix of \c float with sizes determined at compile time, you might do the following:
+\code
+Map<MatrixXf> mf(pf,rows,columns);
+\endcode
+where \c pf is a \c float \c * pointing to the array of memory. A fixed-size read-only vector of integers might be declared as
+\code
+Map<const Vector4i> mi(pi);
+\endcode
+where \c pi is an \c int \c *. In this case the size does not have to be passed to the constructor, because it is already specified by the Matrix/Array type.
+
+Note that Map does not have a default constructor; you \em must pass a pointer to intialize the object. However, you can work around this requirement (see \ref TutorialMapPlacementNew).
+
+Map is flexible enough to accomodate a variety of different data representations. There are two other (optional) template parameters:
+\code
+Map<typename MatrixType,
+ int MapOptions,
+ typename StrideType>
+\endcode
+\li \c MapOptions specifies whether the pointer is \c #Aligned, or \c #Unaligned. The default is \c #Unaligned.
+\li \c StrideType allows you to specify a custom layout for the memory array, using the Stride class. One example would be to specify that the data array is organized in row-major format:
+<table class="example">
+<tr><th>Example:</th><th>Output:</th></tr>
+<tr>
+<td>\include Tutorial_Map_rowmajor.cpp </td>
+<td>\verbinclude Tutorial_Map_rowmajor.out </td>
+</table>
+However, Stride is even more flexible than this; for details, see the documentation for the Map and Stride classes.
+
+\section TutorialMapUsing Using Map variables
+
+You can use a Map object just like any other Eigen type:
+<table class="example">
+<tr><th>Example:</th><th>Output:</th></tr>
+<tr>
+<td>\include Tutorial_Map_using.cpp </td>
+<td>\verbinclude Tutorial_Map_using.out </td>
+</table>
+
+However, when writing functions taking Eigen types, it is important to realize that a Map type is \em not identical to its Dense equivalent. See \ref TopicFunctionTakingEigenTypesMultiarguments for details.
+
+\section TutorialMapPlacementNew Changing the mapped array
+
+It is possible to change the array of a Map object after declaration, using the C++ "placement new" syntax:
+<table class="example">
+<tr><th>Example:</th><th>Output:</th></tr>
+<tr>
+<td>\include Map_placement_new.cpp </td>
+<td>\verbinclude Map_placement_new.out </td>
+</table>
+Despite appearances, this does not invoke the memory allocator, because the syntax specifies the location for storing the result.
+
+This syntax makes it possible to declare a Map object without first knowing the mapped array's location in memory:
+\code
+Map<Matrix3f> A(NULL); // don't try to use this matrix yet!
+VectorXf b(n_matrices);
+for (int i = 0; i < n_matrices; i++)
+{
+ new (&A) Map<Matrix3f>(get_matrix_pointer(i));
+ b(i) = A.trace();
+}
+\endcode
+
+\li \b Next: \ref TODO
+
+*/
+
+}
diff --git a/doc/I13_FunctionsTakingEigenTypes.dox b/doc/I13_FunctionsTakingEigenTypes.dox
index ef71e6f19..f9e6fafed 100644
--- a/doc/I13_FunctionsTakingEigenTypes.dox
+++ b/doc/I13_FunctionsTakingEigenTypes.dox
@@ -47,9 +47,9 @@ void print_block(const DenseBase<Derived>& b, int x, int y, int r, int c)
Prints the maximum coefficient of the array or array-expression.
\code
template <typename Derived>
-void print_max(const ArrayBase<Derived>& a, const ArrayBase<Derived>& b)
+void print_max_coeff(const ArrayBase<Derived> &a)
{
- std::cout << "max: " << (a.max(b)).maxCoeff() << std::endl;
+ std::cout << "max: " << a.maxCoeff() << std::endl;
}
\endcode
<b> %MatrixBase Example </b><br/><br/>
@@ -63,6 +63,21 @@ void print_inv_cond(const MatrixBase<Derived>& a)
std::cout << "inv cond: " << sing_vals(sing_vals.size()-1) / sing_vals(0) << std::endl;
}
\endcode
+<b> Multiple templated arguments example </b><br/><br/>
+Calculate the Euclidean distance between two points.
+\code
+template <typename DerivedA,typename DerivedB>
+typename DerivedA::Scalar squaredist(const MatrixBase<DerivedA>& p1,const MatrixBase<DerivedB>& p2)
+{
+ return (p1-p2).squaredNorm();
+}
+\endcode
+Notice that we used two template parameters, one per argument. This permits the function to handle inputs of different types, e.g.,
+\code
+squaredist(v1,2*v2)
+\endcode
+where the first argument \c v1 is a vector and the second argument \c 2*v2 is an expression.
+<br/><br/>
These examples are just intended to give the reader a first impression of how functions can be written which take a plain and constant Matrix or Array argument. They are also intended to give the reader an idea about the most common base classes being the optimal candidates for functions. In the next section we will look in more detail at an example and the different ways it can be implemented, while discussing each implementation's problems and advantages. For the discussion below, Matrix and Array as well as MatrixBase and ArrayBase can be exchanged and all arguments still hold.
@@ -128,6 +143,8 @@ The implementation above does now not only work with temporary expressions but i
\b Note: The const cast hack will only work with templated functions. It will not work with the MatrixXf implementation because it is not possible to cast a Block expression to a Matrix reference!
+
+
\section TopicResizingInGenericImplementations How to resize matrices in generic implementations?
One might think we are done now, right? This is not completely true because in order for our covariance function to be generically applicable, we want the follwing code to work
diff --git a/doc/Overview.dox b/doc/Overview.dox
index 08dc5b5ed..113f691cb 100644
--- a/doc/Overview.dox
+++ b/doc/Overview.dox
@@ -27,6 +27,7 @@ For a first contact with Eigen, the best place is to have a look at the \ref Get
- \ref TutorialReductionsVisitorsBroadcasting
- \ref TutorialGeometry
- \ref TutorialSparse
+ - \ref TutorialMapClass
- \ref QuickRefPage
- <b>Advanced topics</b>
- \ref TopicAliasing
diff --git a/doc/snippets/Tutorial_Map_rowmajor.cpp b/doc/snippets/Tutorial_Map_rowmajor.cpp
new file mode 100644
index 000000000..fd45ace03
--- /dev/null
+++ b/doc/snippets/Tutorial_Map_rowmajor.cpp
@@ -0,0 +1,7 @@
+int array[8];
+for(int i = 0; i < 8; ++i) array[i] = i;
+cout << "Column-major:\n" << Map<Matrix<int,2,4> >(array) << endl;
+cout << "Row-major:\n" << Map<Matrix<int,2,4,RowMajor> >(array) << endl;
+cout << "Row-major using stride:\n" <<
+ Map<Matrix<int,2,4>, Unaligned, Stride<1,4> >(array) << endl;
+
diff --git a/doc/snippets/Tutorial_Map_using.cpp b/doc/snippets/Tutorial_Map_using.cpp
new file mode 100644
index 000000000..e5e499f1f
--- /dev/null
+++ b/doc/snippets/Tutorial_Map_using.cpp
@@ -0,0 +1,21 @@
+typedef Matrix<float,1,Dynamic> MatrixType;
+typedef Map<MatrixType> MapType;
+typedef Map<const MatrixType> MapTypeConst; // a read-only map
+const int n_dims = 5;
+
+MatrixType m1(n_dims), m2(n_dims);
+m1.setRandom();
+m2.setRandom();
+float *p = &m2(0); // get the address storing the data for m2
+MapType m2map(p,m2.size()); // m2map shares data with m2
+MapTypeConst m2mapconst(p,m2.size()); // a read-only accessor for m2
+
+cout << "m1: " << m1 << endl;
+cout << "m2: " << m2 << endl;
+cout << "Squared euclidean distance: " << (m1-m2).squaredNorm() << endl;
+cout << "Squared euclidean distance, using map: " <<
+ (m1-m2map).squaredNorm() << endl;
+m2map(3) = 7; // this will change m2, since they share the same array
+cout << "Updated m2: " << m2 << endl;
+cout << "m2 coefficient 2, constant accessor: " << m2mapconst(2) << endl;
+/* m2mapconst(2) = 5; */ // this yields a compile-time error