From 41ea92d3559e03278ecc7d61bfd3f8fc2087697e Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sun, 4 Jul 2010 10:14:47 +0200 Subject: * update the general TOC * integrate the old geometry/sparse tutorial into the new one (they are better than nothing) * remove the old tutorial on the core module --- doc/C01_TutorialCore.dox | 756 ----------------------------------- doc/C03_TutorialGeometry.dox | 253 ------------ doc/C06_TutorialLinearAlgebra.dox | 4 +- doc/C07_TutorialSparse.dox | 233 ----------- doc/C08_TutorialGeometry.dox | 250 ++++++++++++ doc/C09_TutorialSparse.dox | 222 ++++++++++ doc/D01_StlContainers.dox | 8 +- doc/D03_WrongStackAlignment.dox | 6 +- doc/D07_PassingByValue.dox | 4 +- doc/D09_StructHavingEigenMembers.dox | 8 +- doc/D11_UnalignedArrayAssert.dox | 20 +- doc/I00_CustomizingEigen.dox | 2 +- doc/I01_TopicLazyEvaluation.dox | 2 +- doc/I02_HiPerformance.dox | 2 +- doc/I03_InsideEigenExample.dox | 2 +- doc/I05_FixedSizeVectorizable.dox | 2 +- doc/Overview.dox | 25 +- 17 files changed, 522 insertions(+), 1277 deletions(-) delete mode 100644 doc/C01_TutorialCore.dox delete mode 100644 doc/C03_TutorialGeometry.dox delete mode 100644 doc/C07_TutorialSparse.dox create mode 100644 doc/C08_TutorialGeometry.dox create mode 100644 doc/C09_TutorialSparse.dox diff --git a/doc/C01_TutorialCore.dox b/doc/C01_TutorialCore.dox deleted file mode 100644 index 242a70ed3..000000000 --- a/doc/C01_TutorialCore.dox +++ /dev/null @@ -1,756 +0,0 @@ -namespace Eigen { - -/** \page TutorialCore Tutorial 1/4 - Core features - \ingroup Tutorial - -

WARNING this page is deprecated, and will be removed soon, don't look at it :)

- -
\ref index "Overview" - | \b Core \b features - | \ref TutorialGeometry "Geometry" - | \ref TutorialAdvancedLinearAlgebra "Advanced linear algebra" - | \ref TutorialSparse "Sparse matrix" -
- -\b Table \b of \b contents - - \ref TutorialCoreGettingStarted - - \ref TutorialCoreSimpleExampleFixedSize - - \ref TutorialCoreSimpleExampleDynamicSize - - \ref TutorialCoreMatrixTypes - - \ref TutorialCoreCoefficients - - \ref TutorialCoreMatrixInitialization - - \ref TutorialCoreArithmeticOperators - - \ref TutorialCoreReductions - - \ref TutorialCoreMatrixBlocks - - \ref TutorialCoreDiagonalMatrices - - \ref TutorialCoreTransposeAdjoint - - \ref TutorialCoreDotNorm - - \ref TutorialCoreTriangularMatrix - - \ref TutorialCoreSelfadjointMatrix - - \ref TutorialCoreSpecialTopics -\n - -
- -\section TutorialCoreGettingStarted Getting started - -In order to use Eigen, you just need to download and extract Eigen's source code. It is not necessary to use CMake or install anything. - -Here are some quick compilation instructions with GCC. To quickly test an example program, just do - -\code g++ -I /path/to/eigen/ my_program.cpp -o my_program \endcode - -There is no library to link to. For good performance, add the \c -O2 compile-flag. Note however that this makes it impossible to debug inside Eigen code, as many functions get inlined. In some cases, performance can be further improved by disabling Eigen assertions: use \c -DEIGEN_NO_DEBUG or \c -DNDEBUG to disable them. - -On the x86 architecture, the SSE2 instruction set is not enabled by default. Use \c -msse2 to enable it, and Eigen will then automatically enable its vectorized paths. On x86-64 and AltiVec-based architectures, vectorization is enabled by default. To turn off Eigen's vectorization use \c-DEIGEN_DONT_VECTORIZE. - -\section TutorialCoreSimpleExampleFixedSize Simple example with fixed-size matrices and vectors - -By fixed-size, we mean that the number of rows and columns are fixed at compile-time. In this case, Eigen avoids dynamic memory allocation, and unroll loops when that makes sense. This is useful for very small sizes: typically up to 4x4, sometimes up to 16x16. - - -
-\include Tutorial_simple_example_fixed_size.cpp - -output: -\include Tutorial_simple_example_fixed_size.out -
- -top -\section TutorialCoreSimpleExampleDynamicSize Simple example with dynamic-size matrices and vectors - -By dynamic-size, we mean that the numbers of rows and columns are not fixed at compile-time. In this case, they are stored as runtime variables and the arrays are dynamically allocated. - - -
-\include Tutorial_simple_example_dynamic_size.cpp - -output: -\include Tutorial_simple_example_dynamic_size.out -
- - -\warning \redstar In most cases it is enough to include the \c Eigen/Core header only to get started with Eigen. However, some features presented in this tutorial require the Array module to be included (\c \#include \c ). Those features are highlighted with a red star \redstar. Notice that if you want to include all Eigen functionality at once, you can do: -\code -#include -\endcode -This slows compilation down but at least you don't have to worry anymore about including the correct files! There also is the Eigen/Dense header including all dense functionality i.e. leaving out the Sparse module. - - -top -\section TutorialCoreMatrixTypes Array, matrix and vector types - -Eigen provides two kinds of dense objects: mathematical matrices and vectors which are both represented by the template class Matrix, and 1D and 2D arrays represented by the template class Array. While the former (Matrix) is specialized for the representation of mathematical objects, the latter (Array) represents a collection of scalar values arranged in a 1D or 2D fashion. As a major difference, all operations performed on arrays are coefficient wise. Matrix and Array have a lot of similarities since they both inherits the DenseBase and DenseStorageBase classes. In the rest of this tutorial we will use the following symbols to emphasize the features which are specifics to a given kind of object: -\li \matrixworld for matrix/vector only features -\li \arrayworld for array only features - -Note that conversion between the two worlds can be done using the MatrixBase::array() and ArrayBase::matrix() functions respectively without any overhead. - -In most cases, you can simply use one of the convenience typedefs for \ref matrixtypedefs "matrices" and \ref arraytypedefs "arrays". - -The template class Matrix (just like the class Array) take a number of template parameters, but for now it is enough to understand the 3 first ones (and the others can then be left unspecified): - -\code -Matrix -Array -\endcode - -\li \c Scalar is the scalar type, i.e. the type of the coefficients. That is, if you want a vector of floats, choose \c float here. -\li \c RowsAtCompileTime and \c ColsAtCompileTime are the number of rows and columns of the matrix as known at compile-time. - -For example, \c Vector3d is a typedef for \code Matrix \endcode - -For dynamic-size, that is in order to left the number of rows or of columns unspecified at compile-time, use the special value Eigen::Dynamic. For example, \c VectorXd is a typedef for \code Matrix \endcode - -All combinations are allowed: you can have a matrix with a fixed number of rows and a dynamic number of columns, etc. The following are all valid: - -\code -Matrix // Dynamic number of columns -Matrix // Dynamic number of rows -Matrix // Fully dynamic -Matrix // Fully fixed -\endcode - -Fixed-size and partially-dynamic-size matrices may use all the same API calls as fully dynamic -matrices, but the fixed dimension(s) must remain constant, or an assertion failure will occur. - -Finally, note that the default typedefs for array containers is slighlty different as we have to distinghish between 1D and 2D arrays: -\code -ArrayXf // 1D dynamic array of floats -Array2i // 1D array of integers of size 2 -ArrayXXd // 2D fully dynamic array of doubles -Array44f // 2D array of floats of size 4x4 -\endcode - - -top -\section TutorialCoreCoefficients Coefficient access - -Eigen supports the following syntaxes for read and write coefficient access of matrices, vectors and arrays: - -\code -matrix(i,j); -vector(i) -vector[i] -\endcode -Vectors support also the following additional read-write accessors: -\code -vector.x() // first coefficient -vector.y() // second coefficient -vector.z() // third coefficient -vector.w() // fourth coefficient -\endcode - -Notice that these coefficient access methods have assertions checking the ranges. So if you do a lot of coefficient access, these assertion can have an important cost. There are then two possibilities if you want avoid paying this cost: -\li Either you can disable assertions altogether, by defining EIGEN_NO_DEBUG or NDEBUG. Notice that some IDEs like MS Visual Studio define NDEBUG automatically in "Release Mode". -\li Or you can disable the checks on a case-by-case basis by using the coeff() and coeffRef() methods: see DenseBase::coeff(int,int) const, DenseBase::coeffRef(int,int), etc. - - -top -\section TutorialCoreMatrixInitialization Matrix and vector creation and initialization - -\subsection TutorialCtors Matrix constructors - -The default constructor leaves coefficients uninitialized. Any dynamic size is set to 0, in which case the matrix/vector is considered uninitialized (no array is allocated). - -\code -Matrix3f A; // construct 3x3 matrix with uninitialized coefficients -A(0,0) = 5; // OK -MatrixXf B; // construct 0x0 matrix without allocating anything -B(0,0) = 5; // Error, B is uninitialized, doesn't have any coefficients to address -\endcode - -In the above example, B is an uninitialized matrix. What to do with such a matrix? You can call resize() on it, or you can assign another matrix to it. Like this: - -\code -MatrixXf B; // uninitialized matrix -B.resize(3,5); // OK, now B is a 3x5 matrix with uninitialized coefficients -B(0,0) = 5; // OK -MatrixXf C; // uninitialized matrix -C = B; // OK, C is initialized as a copy of B -\endcode - -There also are constructors taking size parameters, allowing to directly initialize dynamic-size matrices: - -\code -MatrixXf B(3,5); // B is a 3x5 matrix with uninitialized coefficients -\endcode - -Note that even if one of the dimensions is known at compile time, you must specify it. The only exception is vectors (i.e. matrices where one of the dimensions is known at compile time to be 1). - -\code -VectorXf v(10); // OK, v is a vector of size 10 with uninitialized coefficients -Matrix m(10); // Error: m is not a vector, must provide explicitly the 2 sizes -Matrix m(2,10); // OK -Matrix2f m(2,2); // OK. Of course it's redundant to pass the parameters here, but it's allowed. -\endcode - -For small fixed-size vectors, we also allow constructors passing the coefficients: -\code -Vector2f u(1.2f, 3.4f); -Vector3f v(1.2f, 3.4f, 5.6f); -Vector4f w(1.2f, 3.4f, 5.6f, 7.8f); -\endcode - -\subsection TutorialPredefMat Predefined Matrices -Eigen offers several static methods to create special matrix expressions, and non-static methods to assign these expressions to existing matrices. -The following are - - - - - - - - - - - - - - - - - - - - - -
Fixed-size matrix or vectorDynamic-size matrixDynamic-size vector
-\code -typedef {Matrix3f|Array33f} FixedXD; -FixedXD x; - -x = FixedXD::Zero(); -x = FixedXD::Ones(); -x = FixedXD::Constant(value); -x = FixedXD::Identity(); -x = FixedXD::Random(); - -x.setZero(); -x.setOnes(); -x.setIdentity(); -x.setConstant(value); -x.setRandom(); -\endcode - -\code -typedef {MatrixXf|ArrayXXf} Dynamic2D; -Dynamic2D x; - -x = Dynamic2D::Zero(rows, cols); -x = Dynamic2D::Ones(rows, cols); -x = Dynamic2D::Constant(rows, cols, value); -x = Dynamic2D::Identity(rows, cols); -x = Dynamic2D::Random(rows, cols); - -x.setZero(rows, cols); -x.setOnes(rows, cols); -x.setConstant(rows, cols, value); -x.setIdentity(rows, cols); -x.setRandom(rows, cols); -\endcode - -\code -typedef {VectorXf|ArrayXf} Dynamic1D; -Dynamic1D x; - -x = Dynamic1D::Zero(size); -x = Dynamic1D::Ones(size); -x = Dynamic1D::Constant(size, value); -x = Dynamic1D::Identity(size); -x = Dynamic1D::Random(size); - -x.setZero(size); -x.setOnes(size); -x.setConstant(size, value); -N/A -x.setRandom(size); -\endcode -
\redstar the Random() and setRandom() functions require the inclusion of the Array module (\c \#include \c )
The following are for matrix only: \matrixworld
-\code -x = FixedXD::Identity(); -x.setIdentity(); -\endcode - -\code -x = Dynamic2D::Identity(rows, cols); -x.setIdentity(rows, cols); -\endcode - -
Basis vectors \matrixworld \link MatrixBase::Unit [details]\endlink
\code -Vector3f::UnitX() // 1 0 0 -Vector3f::UnitY() // 0 1 0 -Vector3f::UnitZ() // 0 0 1 -\endcode\code -VectorXf::Unit(size,i) -VectorXf::Unit(4,1) == Vector4f(0,1,0,0) - == Vector4f::UnitY() -\endcode -
- -Here is an usage example: - -
-\code -cout << MatrixXf::Constant(2, 3, sqrt(2)) << endl; -RowVector3i v; -v.setConstant(6); -cout << "v = " << v << endl; -\endcode - -output: -\code -1.41 1.41 1.41 -1.41 1.41 1.41 - -v = 6 6 6 -\endcode -
- - -\subsection TutorialCasting Casting - -In Eigen, any matrices of same size and same scalar type are all naturally compatible. The scalar type can be explicitly casted to another one using the template DenseBase::cast() function: -\code -Matrix3d md(1,2,3); -Matrix3f mf = md.cast(); -\endcode -Note that casting to the same scalar type in an expression is free. - -The destination matrix is automatically resized in any assignment: -\code -MatrixXf res(10,10); -Matrix3f a, b; -res = a+b; // OK: res is resized to size 3x3 -\endcode -Of course, fixed-size matrices can't be resized. - -An array object or expression can be directly assigned to a matrix, and vice versa: -\code -Matrix4f res; -Array44f a, b; -res = a * b; -\endcode -On the other hand, an array and a matrix expressions cannot be mixed in an expression, and one have to be converted to the other using the MatrixBase::array() \matrixworld and ArrayBase::matrix() \arrayworld functions respectively: -\code -Matrix4f m1, m2; -Array44f a1, a2; -m2 = a1 * m1.array(); // coeffwise product -a2 = a1.matrix() * m1; // matrix product -\endcode -Finally it is possible to declare a variable wrapping a matrix as an array object and vice versa: -\code -MatrixXf m1; -ArrayWrapper a1(m1); // a1 and m1 share the same coefficients -// now you can use a1 as an alias for m1.array() -ArrayXXf a2; -MatrixWrapper m2(a1); // a2 and m2 share the same coefficients -// ... -\endcode - -\subsection TutorialMap Map -Any memory buffer can be mapped as an Eigen expression using the Map() static method: -\code -std::vector stlarray(10); -VectorXf::Map(&stlarray[0], stlarray.size()).squaredNorm(); -\endcode -Here VectorXf::Map returns an object of class Map, which behaves like a VectorXf except that it uses the existing array. You can write to this object, that will write to the existing array. You can also construct a named obtect to reuse it: -\code -float data[rows*cols]; -Map m(data,rows,cols); -m = othermatrix1 * othermatrix2; -m.eigenvalues(); -\endcode -In the fixed-size case, no need to pass sizes: -\code -float data[9]; -Map m(data); -Matrix3d::Map(data).setIdentity(); -\endcode - - -\subsection TutorialCommaInit Comma initializer -Eigen also offers a \ref MatrixBaseCommaInitRef "comma initializer syntax" which allows you to set all the coefficients of any dense objects (matrix, vector, array, block, etc.) to specific values: - -
-\include Tutorial_commainit_01.cpp - -output: -\verbinclude Tutorial_commainit_01.out -
- -Not excited by the above example? Then look at the following one where the matrix is set by blocks: - -
-\include Tutorial_commainit_02.cpp - -output: -\verbinclude Tutorial_commainit_02.out -
- -\b Side \b note: here \link CommaInitializer::finished() .finished() \endlink -is used to get the actual matrix object once the comma initialization -of our temporary submatrix is done. Note that despite the apparent complexity of such an expression, -Eigen's comma initializer usually compiles to very optimized code without any overhead. - - - -top -\section TutorialCoreArithmeticOperators Arithmetic Operators - -In short, all arithmetic operators can be used right away as in the following example. Note however that for matrices and vectors arithmetic operators are only given their usual meaning from mathematics tradition while all array operators are performed coefficient wise. - -Here is an example demonstrating basic arithmetic operators: -\code -mat4 -= mat1*1.5 + mat2 * (mat3/4); -\endcode -which includes two matrix scalar products ("mat1*1.5" and "mat3/4"), a matrix-matrix product ("mat2 * (mat3/4)"), -a matrix addition ("+") and subtraction with assignment ("-="). - - - - - - -
-matrix/vector product \matrixworld\code -col2 = mat1 * col1; -row2 = row1 * mat1; row1 *= mat1; -mat3 = mat1 * mat2; mat3 *= mat1; \endcode -
-add/subtract\code -mat3 = mat1 + mat2; mat3 += mat1; -mat3 = mat1 - mat2; mat3 -= mat1;\endcode -
-scalar product\code -mat3 = mat1 * s1; mat3 = s1 * mat1; mat3 *= s1; -mat3 = mat1 / s1; mat3 /= s1;\endcode -
-Other coefficient wise operators\code -mat1.cwiseProduct(mat2); mat1.cwiseQuotient(mat2); -mat1.cwiseMin(mat2); mat1.cwiseMax(mat2); -mat1.cwiseAbs2(); mat1.cwiseSqrt(); -mat1.cwiseAbs();\endcode -
- -In addition to the above operators, array objects supports all kind of coefficient wise operators which usually apply to scalar values. Recall that those operators can be used on matrices by converting them to arrays using the array() function (see \ref TutorialCasting Casting). - - -
- - - - - - -
Coefficient wise \link ArrayBase::operator*() product \arrayworld \endlink\code array3 = array1 * array2; \endcode -
-Add a scalar to all coefficients\code -array3 = array1 + scalar; -array3 += scalar; -array3 -= scalar; -\endcode -
-Coefficient wise \link ArrayBase::operator/() division \endlink \arrayworld\code -array3 = array1 / array2; \endcode -
-Coefficient wise \link ArrayBase::inverse() reciprocal \endlink \arrayworld\code -array3 = array1.inverse(); \endcode -
-Coefficient wise comparisons \arrayworld \n -(support all operators)\code -array3 = array1 < array2; -array3 = array1 <= array2; -array3 = array1 > array2; -etc. -\endcode -
-
- - - -
-\b Trigo \arrayworld: \n -\link ArrayBase::sin sin \endlink, \link ArrayBase::cos cos \endlink\code -array3 = array1.sin(); -etc. -\endcode -
-\b Power \arrayworld: \n \link ArrayBase::pow() pow \endlink, -\link ArrayBase::square square \endlink, -\link ArrayBase::cube cube \endlink, \n -\link ArrayBase::sqrt sqrt \endlink, -\link ArrayBase::exp exp \endlink, -\link ArrayBase::log log \endlink \code -array3 = array1.square(); -array3 = array1.pow(5); -array3 = array1.log(); -etc. -\endcode -
-\link ArrayBase::min min \endlink, \link ArrayBase::max max \endlink, \n -absolute value (\link ArrayBase::abs() abs \endlink, \link ArrayBase::abs2() abs2 \endlink \arrayworld) -\code -array3 = array1.min(array2); -array3 = array1.max(array2); -array3 = array1.abs(); -array3 = array1.abs2(); -\endcode
-
- -So far, we saw the notation \code mat1*mat2 \endcode for matrix product, and \code array1*array2 \endcode for coefficient-wise product. What about other kinds of products, which in some other libraries also use arithmetic operators? In Eigen, they are accessed as follows -- note that here we are anticipating on further sections, for convenience. - - - - -
\link MatrixBase::dot() dot product \endlink (inner product) \matrixworld\code -scalar = vec1.dot(vec2);\endcode -
-outer product \matrixworld\code -mat = vec1 * vec2.transpose();\endcode -
-\link MatrixBase::cross() cross product \endlink \matrixworld\code -#include -vec3 = vec1.cross(vec2);\endcode
- - - -top -\section TutorialCoreReductions Reductions - -Eigen provides several reduction methods such as: -\link DenseBase::minCoeff() minCoeff() \endlink, \link DenseBase::maxCoeff() maxCoeff() \endlink, -\link DenseBase::sum() sum() \endlink, \link MatrixBase::trace() trace() \endlink \matrixworld, -\link MatrixBase::norm() norm() \endlink \matrixworld, \link MatrixBase::squaredNorm() squaredNorm() \endlink \matrixworld, -\link DenseBase::all() all() \endlink \redstar,and \link DenseBase::any() any() \endlink \redstar. -All reduction operations can be done matrix-wise, -\link DenseBase::colwise() column-wise \endlink \redstar or -\link DenseBase::rowwise() row-wise \endlink \redstar. Usage example: - - - - -
\code - 5 3 1 -mat = 2 7 8 - 9 4 6 \endcode - \code mat.minCoeff(); \endcode\code 1 \endcode
\code mat.colwise().minCoeff(); \endcode\code 2 3 1 \endcode
\code mat.rowwise().minCoeff(); \endcode\code -1 -2 -4 -\endcode
- -Also note that maxCoeff and minCoeff can takes optional arguments returning the coordinates of the respective min/max coeff: \link DenseBase::maxCoeff(int*,int*) const maxCoeff(int* i, int* j) \endlink, \link DenseBase::minCoeff(int*,int*) const minCoeff(int* i, int* j) \endlink. - -\b Side \b note: The all() and any() functions are especially useful in combination with coeff-wise comparison operators. - - - - - -top\section TutorialCoreMatrixBlocks Matrix blocks - -Read-write access to a \link DenseBase::col(int) column \endlink -or a \link DenseBase::row(int) row \endlink of a matrix (or array): -\code -mat1.row(i) = mat2.col(j); -mat1.col(j1).swap(mat1.col(j2)); -\endcode - -Read-write access to sub-vectors: - - - - - - - - - - - - - - - - -
Default versionsOptimized versions when the size \n is known at compile time
\code vec1.head(n)\endcode\code vec1.head()\endcodethe first \c n coeffs
\code vec1.tail(n)\endcode\code vec1.tail()\endcodethe last \c n coeffs
\code vec1.segment(pos,n)\endcode\code vec1.segment(pos)\endcodethe \c size coeffs in \n the range [\c pos : \c pos + \c n [
- -Read-write access to sub-matrices:
\code mat1.block(i,j,rows,cols)\endcode - \link DenseBase::block(int,int,int,int) (more) \endlink\code mat1.block(i,j)\endcode - \link DenseBase::block(int,int) (more) \endlinkthe \c rows x \c cols sub-matrix \n starting from position (\c i,\c j)
\code - mat1.topLeftCorner(rows,cols) - mat1.topRightCorner(rows,cols) - mat1.bottomLeftCorner(rows,cols) - mat1.bottomRightCorner(rows,cols)\endcode - \code - mat1.topLeftCorner() - mat1.topRightCorner() - mat1.bottomLeftCorner() - mat1.bottomRightCorner()\endcode - the \c rows x \c cols sub-matrix \n taken in one of the four corners
- - - -top\section TutorialCoreDiagonalMatrices Diagonal matrices -\matrixworld - - - - - - -
-\link MatrixBase::asDiagonal() make a diagonal matrix \endlink from a vector \n -this product is automatically optimized !\code -mat3 = mat1 * vec2.asDiagonal();\endcode -
Access \link MatrixBase::diagonal() the diagonal of a matrix \endlink as a vector (read/write)\code - vec1 = mat1.diagonal(); - mat1.diagonal() = vec1; - \endcode -
- - - -top -\section TutorialCoreTransposeAdjoint Transpose and Adjoint operations - - - - -
-\link DenseBase::transpose() transposition \endlink (read-write)\code -mat3 = mat1.transpose() * mat2; -mat3.transpose() = mat1 * mat2.transpose(); -\endcode -
-\link MatrixBase::adjoint() adjoint \endlink (read only) \matrixworld\n\code -mat3 = mat1.adjoint() * mat2; -\endcode -
- - - -top -\section TutorialCoreDotNorm Dot-product, vector norm, normalization \matrixworld - - - - - -
-\link MatrixBase::dot() Dot-product \endlink of two vectors -\code vec1.dot(vec2);\endcode -
-\link MatrixBase::norm() norm \endlink of a vector \n -\link MatrixBase::squaredNorm() squared norm \endlink of a vector -\code vec.norm(); \endcode \n \code vec.squaredNorm() \endcode -
-returns a \link MatrixBase::normalized() normalized \endlink vector \n -\link MatrixBase::normalize() normalize \endlink a vector -\code -vec3 = vec1.normalized(); -vec1.normalize();\endcode -
- - - -top -\section TutorialCoreTriangularMatrix Dealing with triangular matrices \matrixworld - -Currently, Eigen does not provide any explicit triangular matrix, with storage class. Instead, we -can reference a triangular part of a square matrix or expression to perform special treatment on it. -This is achieved by the class TriangularView and the MatrixBase::triangularView template function. -Note that the opposite triangular part of the matrix is never referenced, and so it can, e.g., store -a second triangular matrix. - - - - - - - -
-Reference a read/write triangular part of a given \n -matrix (or expression) m with optional unit diagonal: -\code -m.triangularView() -m.triangularView() -m.triangularView() -m.triangularView()\endcode -
-Writing to a specific triangular part:\n (only the referenced triangular part is evaluated) -\code -m1.triangularView() = m2 + m3 \endcode -
-Conversion to a dense matrix setting the opposite triangular part to zero: -\code -m2 = m1.triangularView()\endcode -
-Products: -\code -m3 += s1 * m1.adjoint().triangularView() * m2 -m3 -= s1 * m2.conjugate() * m1.adjoint().triangularView() \endcode -
-Solving linear equations:\n(\f$ m_2 := m_1^{-1} m_2 \f$) -\code -m1.triangularView().solveInPlace(m2) -m1.adjoint().triangularView().solveInPlace(m2)\endcode -
- - - -top -\section TutorialCoreSelfadjointMatrix Dealing with symmetric/selfadjoint matrices \matrixworld - -Just as for triangular matrix, you can reference any triangular part of a square matrix to see it a selfadjoint -matrix to perform special and optimized operations. Again the opposite triangular is never referenced and can be -used to store other information. - - - - - - - -
-Conversion to a dense matrix: -\code -m2 = m.selfadjointView();\endcode -
-Product with another general matrix or vector: -\code -m3 = s1 * m1.conjugate().selfadjointView() * m3; -m3 -= s1 * m3.adjoint() * m1.selfadjointView();\endcode -
-Rank 1 and rank K update: -\code -// fast version of m1 += s1 * m2 * m2.adjoint(): -m1.selfadjointView().rankUpdate(m2,s1); -// fast version of m1 -= m2.adjoint() * m2: -m1.selfadjointView().rankUpdate(m2.adjoint(),-1); \endcode -
-Rank 2 update: (\f$ m += s u v^* + s v u^* \f$) -\code -m.selfadjointView().rankUpdate(u,v,s); -\endcode -
-Solving linear equations:\n(\f$ m_2 := m_1^{-1} m_2 \f$) -\code -// via a standard Cholesky factorization -m1.selfadjointView().llt().solveInPlace(m2); -// via a Cholesky factorization with pivoting -m1.selfadjointView().ldlt().solveInPlace(m2); -\endcode -
- - -top -\section TutorialCoreSpecialTopics Special Topics - -\ref TopicLazyEvaluation "Lazy Evaluation and Aliasing": Thanks to expression templates, Eigen is able to apply lazy evaluation wherever that is beneficial. - -*/ - -} diff --git a/doc/C03_TutorialGeometry.dox b/doc/C03_TutorialGeometry.dox deleted file mode 100644 index 6d02df40c..000000000 --- a/doc/C03_TutorialGeometry.dox +++ /dev/null @@ -1,253 +0,0 @@ -namespace Eigen { - -/** \page TutorialGeometry Tutorial 2/4 - Geometry - \ingroup Tutorial - -
\ref index "Overview" - | \ref TutorialCore "Core features" - | \b Geometry - | \ref TutorialAdvancedLinearAlgebra "Advanced linear algebra" - | \ref TutorialSparse "Sparse matrix" -
- -In this tutorial chapter we will shortly introduce the many possibilities offered by the \ref Geometry_Module "geometry module", -namely 2D and 3D rotations and affine transformations. - -\b Table \b of \b contents - - \ref TutorialGeoElementaryTransformations - - \ref TutorialGeoCommontransformationAPI - - \ref TutorialGeoTransform - - \ref TutorialGeoEulerAngles - -Eigen's Geometry module provides two different kinds of geometric transformations: - - Abstract transformations, such as rotations (represented by \ref AngleAxis "angle and axis" or by a \ref Quaternion "quaternion"), \ref Translation "translations", \ref Scaling "scalings". These transformations are NOT represented as matrices, but you can nevertheless mix them with matrices and vectors in expressions, and convert them to matrices if you wish. - - Affine transformation matrices: see the Transform class. These are really matrices. - -\note If you are working with OpenGL 4x4 matrices then Transform3f and Transform3d are what you want. Since Eigen defaults to column-major storage, you can directly use the Transform::data() method to pass your transformation matrix to OpenGL. - -You can construct a Transform from an abstract transformation, like this: -\code - Transform t(AngleAxis(angle,axis)); -\endcode -or like this: -\code - Transform t; - t = AngleAxis(angle,axis); -\endcode -But note that unfortunately, because of how C++ works, you can \b not do this: -\code - Transform t = AngleAxis(angle,axis); -\endcode -\b Explanation: In the C++ language, this would require Transform to have a non-explicit conversion constructor from AngleAxis, but we really don't want to allow implicit casting here. - - -\section TutorialGeoElementaryTransformations Transformation types - - - - - - - - - - -
Transformation typeTypical initialization code
-\ref Rotation2D "2D rotation" from an angle\code -Rotation2D rot2(angle_in_radian);\endcode
-3D rotation as an \ref AngleAxis "angle + axis"\code -AngleAxis aa(angle_in_radian, Vector3f(ax,ay,az));\endcode
-3D rotation as a \ref Quaternion "quaternion"\code -Quaternion q = AngleAxis(angle_in_radian, axis);\endcode
-N-D Scaling\code -Scaling(sx, sy) -Scaling(sx, sy, sz) -Scaling(s) -Scaling(vecN)\endcode
-N-D Translation\code -Translation(tx, ty) -Translation(tx, ty, tz) -Translation(s) -Translation(vecN)\endcode
-N-D \ref TutorialGeoTransform "Affine transformation"\code -Transform t = concatenation_of_any_transformations; -Transform t = Translation3f(p) * AngleAxisf(a,axis) * Scaling3f(s);\endcode
-N-D Linear transformations \n -(pure rotations, \n scaling, etc.)\code -Matrix t = concatenation_of_rotations_and_scalings; -Matrix t = Rotation2Df(a) * Scaling2f(s); -Matrix t = AngleAxisf(a,axis) * Scaling3f(s);\endcode
- -Notes on rotations\n To transform more than a single vector the preferred -representations are rotation matrices, while for other usages Quaternion is the -representation of choice as they are compact, fast and stable. Finally Rotation2D and -AngleAxis are mainly convenient types to create other rotation objects. - -Notes on Translation and Scaling\n Likewise AngleAxis, these classes were -designed to simplify the creation/initialization of linear (Matrix) and affine (Transform) -transformations. Nevertheless, unlike AngleAxis which is inefficient to use, these classes -might still be interesting to write generic and efficient algorithms taking as input any -kind of transformations. - -Any of the above transformation types can be converted to any other types of the same nature, -or to a more generic type. Here are some additional examples: - - -
\code -Rotation2Df r = Matrix2f(..); // assumes a pure rotation matrix -AngleAxisf aa = Quaternionf(..); -AngleAxisf aa = Matrix3f(..); // assumes a pure rotation matrix -Matrix2f m = Rotation2Df(..); -Matrix3f m = Quaternionf(..); Matrix3f m = Scaling3f(..); -Transform3f m = AngleAxis3f(..); Transform3f m = Scaling3f(..); -Transform3f m = Translation3f(..); Transform3f m = Matrix3f(..); -\endcode
- - -top\section TutorialGeoCommontransformationAPI Common API across transformation types - -To some extent, Eigen's \ref Geometry_Module "geometry module" allows you to write -generic algorithms working on any kind of transformation representations: - - - - - -
-Concatenation of two transformations\code -gen1 * gen2;\endcode
Apply the transformation to a vector\code -vec2 = gen1 * vec1;\endcode
Get the inverse of the transformation\code -gen2 = gen1.inverse();\endcode
Spherical interpolation \n (Rotation2D and Quaternion only)\code -rot3 = rot1.slerp(alpha,rot2);\endcode
- - - -top\section TutorialGeoTransform Affine transformations -Generic affine transformations are represented by the Transform class which internaly -is a (Dim+1)^2 matrix. In Eigen we have chosen to not distinghish between points and -vectors such that all points are actually represented by displacement vectors from the -origin ( \f$ \mathbf{p} \equiv \mathbf{p}-0 \f$ ). With that in mind, real points and -vector distinguish when the transformation is applied. - - - - - - - -
-Apply the transformation to a \b point \code -VectorNf p1, p2; -p2 = t * p1;\endcode
-Apply the transformation to a \b vector \code -VectorNf vec1, vec2; -vec2 = t.linear() * vec1;\endcode
-Apply a \em general transformation \n to a \b normal \b vector -(explanations)\code -VectorNf n1, n2; -MatrixNf normalMatrix = t.linear().inverse().transpose(); -n2 = (normalMatrix * n1).normalized();\endcode
-Apply a transformation with \em pure \em rotation \n to a \b normal \b vector -(no scaling, no shear)\code -n2 = t.linear() * n1;\endcode
-OpenGL compatibility \b 3D \code -glLoadMatrixf(t.data());\endcode
-OpenGL compatibility \b 2D \code -Transform3f aux(Transform3f::Identity); -aux.linear().topLeftCorner<2,2>() = t.linear(); -aux.translation().start<2>() = t.translation(); -glLoadMatrixf(aux.data());\endcode
- -\b Component \b accessors - - - - - - -
-full read-write access to the internal matrix\code -t.matrix() = matN1xN1; // N1 means N+1 -matN1xN1 = t.matrix(); -\endcode
-coefficient accessors\code -t(i,j) = scalar; <=> t.matrix()(i,j) = scalar; -scalar = t(i,j); <=> scalar = t.matrix()(i,j); -\endcode
-translation part\code -t.translation() = vecN; -vecN = t.translation(); -\endcode
-linear part\code -t.linear() = matNxN; -matNxN = t.linear(); -\endcode
-extract the rotation matrix\code -matNxN = t.extractRotation(); -\endcode
- - -\b Transformation \b creation \n -While transformation objects can be created and updated concatenating elementary transformations, -the Transform class also features a procedural API: - - - - - - -
\b procedurale \b API \b equivalent \b natural \b API
Translation\code -t.translate(Vector_(tx,ty,..)); -t.pretranslate(Vector_(tx,ty,..)); -\endcode\code -t *= Translation_(tx,ty,..); -t = Translation_(tx,ty,..) * t; -\endcode
\b Rotation \n In 2D and for the procedural API, any_rotation can also \n be an angle in radian\code -t.rotate(any_rotation); -t.prerotate(any_rotation); -\endcode\code -t *= any_rotation; -t = any_rotation * t; -\endcode
Scaling\code -t.scale(Vector_(sx,sy,..)); -t.scale(s); -t.prescale(Vector_(sx,sy,..)); -t.prescale(s); -\endcode\code -t *= Scaling_(sx,sy,..); -t *= Scaling_(s); -t = Scaling_(sx,sy,..) * t; -t = Scaling_(s) * t; -\endcode
Shear transformation \n ( \b 2D \b only ! )\code -t.shear(sx,sy); -t.preshear(sx,sy); -\endcode
- -Note that in both API, any many transformations can be concatenated in a single expression as shown in the two following equivalent examples: - - - -
\code -t.pretranslate(..).rotate(..).translate(..).scale(..); -\endcode
\code -t = Translation_(..) * t * RotationType(..) * Translation_(..) * Scaling_(..); -\endcode
- - - -top\section TutorialGeoEulerAngles Euler angles - - -
-Euler angles might be convenient to create rotation objects. -On the other hand, since there exist 24 differents convension,they are pretty confusing to use. This example shows how -to create a rotation matrix according to the 2-1-2 convention.\code -Matrix3f m; -m = AngleAxisf(angle1, Vector3f::UnitZ()) -* * AngleAxisf(angle2, Vector3f::UnitY()) -* * AngleAxisf(angle3, Vector3f::UnitZ()); -\endcode
- -*/ - -} diff --git a/doc/C06_TutorialLinearAlgebra.dox b/doc/C06_TutorialLinearAlgebra.dox index c3bb7b40d..f4c3ecc01 100644 --- a/doc/C06_TutorialLinearAlgebra.dox +++ b/doc/C06_TutorialLinearAlgebra.dox @@ -4,7 +4,7 @@ namespace Eigen { \ingroup Tutorial \li \b Previous: \ref TutorialAdvancedInitialization -\li \b Next: TODO +\li \b Next: \ref TutorialGeometry This tutorial explains how to solve linear systems, compute various decompositions such as LU, QR, %SVD, eigendecompositions... for more advanced topics, don't miss our special page on @@ -240,7 +240,7 @@ decomposition after you've changed the threshold. -\li \b Next: TODO +\li \b Next: TutorialGeometry */ diff --git a/doc/C07_TutorialSparse.dox b/doc/C07_TutorialSparse.dox deleted file mode 100644 index ee8a1a100..000000000 --- a/doc/C07_TutorialSparse.dox +++ /dev/null @@ -1,233 +0,0 @@ -namespace Eigen { - -/** \page TutorialSparse Tutorial 4/4 - Getting started with the sparse module - \ingroup Tutorial - -
\ref index "Overview" - | \ref TutorialCore "Core features" - | \ref TutorialGeometry "Geometry" - | \ref TutorialAdvancedLinearAlgebra "Advanced linear algebra" - | \b Sparse \b matrix -
- -\b Table \b of \b contents \n - - \ref TutorialSparseIntro - - \ref TutorialSparseFilling - - \ref TutorialSparseFeatureSet - - \ref TutorialSparseDirectSolvers -
- -\section TutorialSparseIntro Sparse matrix representations - -In many applications (e.g., finite element methods) it is common to deal with very large matrices where only a few coefficients are different than zero. Both in term of memory consumption and performance, it is fundamental to use an adequate representation storing only nonzero coefficients. Such a matrix is called a sparse matrix. - -\b Declaring \b sparse \b matrices \b and \b vectors \n -The SparseMatrix class is the main sparse matrix representation of the Eigen's sparse module which offers high performance, low memory usage, and compatibility with most of sparse linear algebra packages. Because of its limited flexibility, we also provide a DynamicSparseMatrix variante taillored for low-level sparse matrix assembly. Both of them can be either row major or column major: - -\code -#include -SparseMatrix > m1(1000,2000); // declare a 1000x2000 col-major compressed sparse matrix of complex -SparseMatrix m2(1000,2000); // declare a 1000x2000 row-major compressed sparse matrix of double -DynamicSparseMatrix > m1(1000,2000); // declare a 1000x2000 col-major dynamic sparse matrix of complex -DynamicSparseMatrix m2(1000,2000); // declare a 1000x2000 row-major dynamic sparse matrix of double -\endcode - -Although a sparse matrix could also be used to represent a sparse vector, for that purpose it is better to use the specialized SparseVector class: -\code -SparseVector > v1(1000); // declare a column sparse vector of complex of size 1000 -SparseVector v2(1000); // declare a row sparse vector of double of size 1000 -\endcode -Note that here the size of a vector denotes its dimension and not the number of nonzero coefficients which is initially zero (like sparse matrices). - - -\b Overview \b of \b the \b internal \b sparse \b storage \n -In order to get the best of the Eigen's sparse objects, it is important to have a rough idea of the way they are internally stored. The SparseMatrix class implements the common and generic Compressed Column/Row Storage scheme. It consists of three compact arrays storing the values with their respective inner coordinates, and pointer indices to the begining of each outer vector. For instance, let \c m be a column-major sparse matrix. Then its nonzero coefficients are sequentially stored in memory in a column-major order (\em values). A second array of integer stores the respective row index of each coefficient (\em inner \em indices). Finally, a third array of integer, having the same length than the number of columns, stores the index in the previous arrays of the first element of each column (\em outer \em indices). - -Here is an example, with the matrix: - - - - - - -
03000
2200017
75010
00000
001408
- -and its internal representation using the Compressed Column Storage format: - - - -
Values: 22735141178
Inner indices: 1202 42 14
-Outer indices:
02456\em 7
- -As you can guess, here the storage order is even more important than with dense matrix. We will therefore often make a clear difference between the \em inner and \em outer dimensions. For instance, it is easy to loop over the coefficients of an \em inner \em vector (e.g., a column of a column-major matrix), but completely inefficient to do the same for an \em outer \em vector (e.g., a row of a col-major matrix). - -The SparseVector class implements the same compressed storage scheme but, of course, without any outer index buffer. - -Since all nonzero coefficients of such a matrix are sequentially stored in memory, random insertion of new nonzeros can be extremely costly. To overcome this limitation, Eigen's sparse module provides a DynamicSparseMatrix class which is basically implemented as an array of SparseVector. In other words, a DynamicSparseMatrix is a SparseMatrix where the values and inner-indices arrays have been splitted into multiple small and resizable arrays. Assuming the number of nonzeros per inner vector is relatively low, this slight modification allow for very fast random insertion at the cost of a slight memory overhead and a lost of compatibility with other sparse libraries used by some of our highlevel solvers. Note that the major memory overhead comes from the extra memory preallocated by each inner vector to avoid an expensive memory reallocation at every insertion. - -To summarize, it is recommanded to use a SparseMatrix whenever this is possible, and reserve the use of DynamicSparseMatrix for matrix assembly purpose when a SparseMatrix is not flexible enough. The respective pro/cons of both representations are summarized in the following table: - - - - - - - - - - - - - - - -
SparseMatrixDynamicSparseMatrix
memory usage*****
sorted insertion******
random insertion \n in sorted inner vector****
sorted insertion \n in random inner vector-***
random insertion-**
coeff wise unary operators******
coeff wise binary operators******
matrix products*****(*)
transpose*****
redux*****
*= scalar*****
Compatibility with highlevel solvers \n (TAUCS, Cholmod, SuperLU, UmfPack)***-
- - -\b Matrix \b and \b vector \b properties \n - -Here mat and vec represents any sparse-matrix and sparse-vector types respectively. - - - - - - - - - - -
Standard \n dimensions\code -mat.rows() -mat.cols()\endcode\code -vec.size() \endcode
Sizes along the \n inner/outer dimensions\code -mat.innerSize() -mat.outerSize()\endcode
Number of non \n zero coefficiens\code -mat.nonZeros() \endcode\code -vec.nonZeros() \endcode
- - -\b Iterating \b over \b the \b nonzero \b coefficients \n - -Iterating over the coefficients of a sparse matrix can be done only in the same order than the storage order. Here is an example: - - -
-\code -SparseMatrixType mat(rows,cols); -for (int k=0; k\ -\code -SparseVector vec(size); -for (SparseVector::InnerIterator it(vec); it; ++it) -{ - it.value(); // == vec[ it.index() ] - it.index(); -} -\endcode -
- - -\section TutorialSparseFilling Filling a sparse matrix - -Owing to the special storage scheme of a SparseMatrix, it is obvious that for performance reasons a sparse matrix cannot be filled as easily as a dense matrix. For instance the cost of a purely random insertion into a SparseMatrix is in O(nnz) where nnz is the current number of non zeros. In order to cover all uses cases with best efficiency, Eigen provides various mechanisms, from the easiest but slowest, to the fastest but restrictive one. - -If you don't have any prior knowledge about the order your matrix will be filled, then the best choice is to use a DynamicSparseMatrix. With a DynamicSparseMatrix, you can add or modify any coefficients at any time using the coeffRef(row,col) method. Here is an example: -\code -DynamicSparseMatrix aux(1000,1000); -aux.reserve(estimated_number_of_non_zero); // optional -for (...) - for each j // the j can be random - for each i interacting with j // the i can be random - aux.coeffRef(i,j) += foo(i,j); -\endcode -Then the DynamicSparseMatrix object can be converted to a compact SparseMatrix to be used, e.g., by one of our supported solver: -\code -SparseMatrix mat(aux); -\endcode - -In order to optimize this process, instead of the generic coeffRef(i,j) method one can also use: - - \code m.insert(i,j) = value; \endcode which assumes the coefficient of coordinate (row,col) does not already exist (otherwise this is a programming error and your program will stop). - - \code m.insertBack(i,j) = value; \endcode which, in addition to the requirements of insert(), also assumes that the coefficient of coordinate (row,col) will be inserted at the end of the target inner-vector. More precisely, if the matrix m is column major, then the row index of the last non zero coefficient of the j-th column must be smaller than i. - - -Actually, the SparseMatrix class also supports random insertion via the insert() method. However, its uses should be reserved in cases where the inserted non zero is nearly the last one of the compact storage array. In practice, this means it should be used only to perform random (or sorted) insertion into the current inner-vector while filling the inner-vectors in an increasing order. Moreover, with a SparseMatrix an insertion session must be closed by a call to finalize() before any use of the matrix. Here is an example for a column major matrix: - -\code -SparseMatrix mat(1000,1000); -mat.reserve(estimated_number_of_non_zero); // optional -for each j // should be in increasing order for performance reasons - for each i interacting with j // the i can be random - mat.insert(i,j) = foo(i,j); // optional for a DynamicSparseMatrix -mat.finalize(); -\endcode - -Finally, the fastest way to fill a SparseMatrix object is to insert the elements in a purely coherence order (increasing inner index per increasing outer index). To this end, Eigen provides a very low but optimal API and illustrated below: - -\code -SparseMatrix mat(1000,1000); -mat.reserve(estimated_number_of_non_zero); // optional -for(int j=0; j<1000; ++j) -{ - mat.startVec(j); // optional for a DynamicSparseMatrix - for each i interacting with j // with increasing i - mat.insertBack(i,j) = foo(i,j); -} -mat.finalize(); // optional for a DynamicSparseMatrix -\endcode -Note that there also exist the insertBackByOuterInner(Index outer, Index, inner) function which allows to write code agnostic to the storage order. - -\section TutorialSparseFeatureSet Supported operators and functions - -In the following \em sm denote a sparse matrix, \em sv a sparse vector, \em dm a dense matrix, and \em dv a dense vector. -In Eigen's sparse module we chose to expose only the subset of the dense matrix API which can be efficiently implemented. Moreover, all combinations are not always possible. For instance, it is not possible to add two sparse matrices having two different storage order. On the other hand it is perfectly fine to evaluate a sparse matrix/expression to a matrix having a different storage order: -\code -SparseMatrixType sm1, sm2, sm3; -sm3 = sm1.transpose() + sm2; // invalid -sm3 = SparseMatrixType(sm1.transpose()) + sm2; // correct -\endcode - -Here are some examples of the supported operations: -\code -s_1 *= 0.5; -sm4 = sm1 + sm2 + sm3; // only if s_1, s_2 and s_3 have the same storage order -sm3 = sm1 * sm2; -dv3 = sm1 * dv2; -dm3 = sm1 * dm2; -dm3 = dm2 * sm1; -sm3 = sm1.cwise() * sm2; // only if s_1 and s_2 have the same storage order -dv2 = sm1.marked().solveTriangular(dv2); -\endcode - -The product of a sparse matrix A time a dense matrix/vector dv with A symmetric can be optimized by telling that to Eigen: -\code -res = A.marked() * dv; // if all coefficients of A are stored -res = A.marked() * dv; // if only the upper part of A is stored -res = A.marked() * dv; // if only the lower part of A is stored -\endcode - - -\section TutorialSparseDirectSolvers Using the direct solvers - -TODO - -\subsection TutorialSparseDirectSolvers_LLT LLT -Cholmod, Taucs. - -\subsection TutorialSparseDirectSolvers_LDLT LDLT - - -\subsection TutorialSparseDirectSolvers_LU LU -SuperLU, UmfPack. - -*/ - -} diff --git a/doc/C08_TutorialGeometry.dox b/doc/C08_TutorialGeometry.dox new file mode 100644 index 000000000..7d0e9f835 --- /dev/null +++ b/doc/C08_TutorialGeometry.dox @@ -0,0 +1,250 @@ +namespace Eigen { + +/** \page TutorialGeometry Tutorial page 8 - Geometry + \ingroup Tutorial + +\li \b Previous: \ref TutorialLinearAlgebra +\li \b Next: \ref TutorialSparse + +In this tutorial, we will shortly introduce the many possibilities offered by the \ref Geometry_Module "geometry module", namely 2D and 3D rotations and projective or affine transformations. + +\b Table \b of \b contents + - \ref TutorialGeoElementaryTransformations + - \ref TutorialGeoCommontransformationAPI + - \ref TutorialGeoTransform + - \ref TutorialGeoEulerAngles + +Eigen's Geometry module provides two different kinds of geometric transformations: + - Abstract transformations, such as rotations (represented by \ref AngleAxis "angle and axis" or by a \ref Quaternion "quaternion"), \ref Translation "translations", \ref Scaling "scalings". These transformations are NOT represented as matrices, but you can nevertheless mix them with matrices and vectors in expressions, and convert them to matrices if you wish. + - Projective or affine transformation matrices: see the Transform class. These are really matrices. + +\note If you are working with OpenGL 4x4 matrices then Transform3f and Transform3d are what you want. Since Eigen defaults to column-major storage, you can directly use the Transform::data() method to pass your transformation matrix to OpenGL. + +You can construct a Transform from an abstract transformation, like this: +\code + Transform t(AngleAxis(angle,axis)); +\endcode +or like this: +\code + Transform t; + t = AngleAxis(angle,axis); +\endcode +But note that unfortunately, because of how C++ works, you can \b not do this: +\code + Transform t = AngleAxis(angle,axis); +\endcode +\b Explanation: In the C++ language, this would require Transform to have a non-explicit conversion constructor from AngleAxis, but we really don't want to allow implicit casting here. + + +\section TutorialGeoElementaryTransformations Transformation types + + + + + + + + + + +
Transformation typeTypical initialization code
+\ref Rotation2D "2D rotation" from an angle\code +Rotation2D rot2(angle_in_radian);\endcode
+3D rotation as an \ref AngleAxis "angle + axis"\code +AngleAxis aa(angle_in_radian, Vector3f(ax,ay,az));\endcode
+3D rotation as a \ref Quaternion "quaternion"\code +Quaternion q = AngleAxis(angle_in_radian, axis);\endcode
+N-D Scaling\code +Scaling(sx, sy) +Scaling(sx, sy, sz) +Scaling(s) +Scaling(vecN)\endcode
+N-D Translation\code +Translation(tx, ty) +Translation(tx, ty, tz) +Translation(s) +Translation(vecN)\endcode
+N-D \ref TutorialGeoTransform "Affine transformation"\code +Transform t = concatenation_of_any_transformations; +Transform t = Translation3f(p) * AngleAxisf(a,axis) * Scaling3f(s);\endcode
+N-D Linear transformations \n +(pure rotations, \n scaling, etc.)\code +Matrix t = concatenation_of_rotations_and_scalings; +Matrix t = Rotation2Df(a) * Scaling2f(s); +Matrix t = AngleAxisf(a,axis) * Scaling3f(s);\endcode
+ +Notes on rotations\n To transform more than a single vector the preferred +representations are rotation matrices, while for other usages Quaternion is the +representation of choice as they are compact, fast and stable. Finally Rotation2D and +AngleAxis are mainly convenient types to create other rotation objects. + +Notes on Translation and Scaling\n Likewise AngleAxis, these classes were +designed to simplify the creation/initialization of linear (Matrix) and affine (Transform) +transformations. Nevertheless, unlike AngleAxis which is inefficient to use, these classes +might still be interesting to write generic and efficient algorithms taking as input any +kind of transformations. + +Any of the above transformation types can be converted to any other types of the same nature, +or to a more generic type. Here are some additional examples: + + +
\code +Rotation2Df r = Matrix2f(..); // assumes a pure rotation matrix +AngleAxisf aa = Quaternionf(..); +AngleAxisf aa = Matrix3f(..); // assumes a pure rotation matrix +Matrix2f m = Rotation2Df(..); +Matrix3f m = Quaternionf(..); Matrix3f m = Scaling3f(..); +Transform3f m = AngleAxis3f(..); Transform3f m = Scaling3f(..); +Transform3f m = Translation3f(..); Transform3f m = Matrix3f(..); +\endcode
+ + +top\section TutorialGeoCommontransformationAPI Common API across transformation types + +To some extent, Eigen's \ref Geometry_Module "geometry module" allows you to write +generic algorithms working on any kind of transformation representations: + + + + + +
+Concatenation of two transformations\code +gen1 * gen2;\endcode
Apply the transformation to a vector\code +vec2 = gen1 * vec1;\endcode
Get the inverse of the transformation\code +gen2 = gen1.inverse();\endcode
Spherical interpolation \n (Rotation2D and Quaternion only)\code +rot3 = rot1.slerp(alpha,rot2);\endcode
+ + + +top\section TutorialGeoTransform Affine transformations +Generic affine transformations are represented by the Transform class which internaly +is a (Dim+1)^2 matrix. In Eigen we have chosen to not distinghish between points and +vectors such that all points are actually represented by displacement vectors from the +origin ( \f$ \mathbf{p} \equiv \mathbf{p}-0 \f$ ). With that in mind, real points and +vector distinguish when the transformation is applied. + + + + + + + +
+Apply the transformation to a \b point \code +VectorNf p1, p2; +p2 = t * p1;\endcode
+Apply the transformation to a \b vector \code +VectorNf vec1, vec2; +vec2 = t.linear() * vec1;\endcode
+Apply a \em general transformation \n to a \b normal \b vector +(explanations)\code +VectorNf n1, n2; +MatrixNf normalMatrix = t.linear().inverse().transpose(); +n2 = (normalMatrix * n1).normalized();\endcode
+Apply a transformation with \em pure \em rotation \n to a \b normal \b vector +(no scaling, no shear)\code +n2 = t.linear() * n1;\endcode
+OpenGL compatibility \b 3D \code +glLoadMatrixf(t.data());\endcode
+OpenGL compatibility \b 2D \code +Transform3f aux(Transform3f::Identity); +aux.linear().topLeftCorner<2,2>() = t.linear(); +aux.translation().start<2>() = t.translation(); +glLoadMatrixf(aux.data());\endcode
+ +\b Component \b accessors + + + + + + +
+full read-write access to the internal matrix\code +t.matrix() = matN1xN1; // N1 means N+1 +matN1xN1 = t.matrix(); +\endcode
+coefficient accessors\code +t(i,j) = scalar; <=> t.matrix()(i,j) = scalar; +scalar = t(i,j); <=> scalar = t.matrix()(i,j); +\endcode
+translation part\code +t.translation() = vecN; +vecN = t.translation(); +\endcode
+linear part\code +t.linear() = matNxN; +matNxN = t.linear(); +\endcode
+extract the rotation matrix\code +matNxN = t.extractRotation(); +\endcode
+ + +\b Transformation \b creation \n +While transformation objects can be created and updated concatenating elementary transformations, +the Transform class also features a procedural API: + + + + + + +
\b procedurale \b API \b equivalent \b natural \b API
Translation\code +t.translate(Vector_(tx,ty,..)); +t.pretranslate(Vector_(tx,ty,..)); +\endcode\code +t *= Translation_(tx,ty,..); +t = Translation_(tx,ty,..) * t; +\endcode
\b Rotation \n In 2D and for the procedural API, any_rotation can also \n be an angle in radian\code +t.rotate(any_rotation); +t.prerotate(any_rotation); +\endcode\code +t *= any_rotation; +t = any_rotation * t; +\endcode
Scaling\code +t.scale(Vector_(sx,sy,..)); +t.scale(s); +t.prescale(Vector_(sx,sy,..)); +t.prescale(s); +\endcode\code +t *= Scaling_(sx,sy,..); +t *= Scaling_(s); +t = Scaling_(sx,sy,..) * t; +t = Scaling_(s) * t; +\endcode
Shear transformation \n ( \b 2D \b only ! )\code +t.shear(sx,sy); +t.preshear(sx,sy); +\endcode
+ +Note that in both API, any many transformations can be concatenated in a single expression as shown in the two following equivalent examples: + + + +
\code +t.pretranslate(..).rotate(..).translate(..).scale(..); +\endcode
\code +t = Translation_(..) * t * RotationType(..) * Translation_(..) * Scaling_(..); +\endcode
+ + + +top\section TutorialGeoEulerAngles Euler angles + + +
+Euler angles might be convenient to create rotation objects. +On the other hand, since there exist 24 differents convension,they are pretty confusing to use. This example shows how +to create a rotation matrix according to the 2-1-2 convention.\code +Matrix3f m; +m = AngleAxisf(angle1, Vector3f::UnitZ()) +* * AngleAxisf(angle2, Vector3f::UnitY()) +* * AngleAxisf(angle3, Vector3f::UnitZ()); +\endcode
+ +\li \b Next: \ref TutorialSparse + +*/ + +} diff --git a/doc/C09_TutorialSparse.dox b/doc/C09_TutorialSparse.dox new file mode 100644 index 000000000..e46939e32 --- /dev/null +++ b/doc/C09_TutorialSparse.dox @@ -0,0 +1,222 @@ +namespace Eigen { + +/** \page TutorialSparse Tutorial page 9 - Sparse Matrix + \ingroup Tutorial + +\li \b Previous: \ref TutorialGeometry +\li \b Next: TODO + +\b Table \b of \b contents \n + - \ref TutorialSparseIntro + - \ref TutorialSparseFilling + - \ref TutorialSparseFeatureSet + - \ref TutorialSparseDirectSolvers +
+ +\section TutorialSparseIntro Sparse matrix representations + +In many applications (e.g., finite element methods) it is common to deal with very large matrices where only a few coefficients are different than zero. Both in term of memory consumption and performance, it is fundamental to use an adequate representation storing only nonzero coefficients. Such a matrix is called a sparse matrix. + +\b Declaring \b sparse \b matrices \b and \b vectors \n +The SparseMatrix class is the main sparse matrix representation of the Eigen's sparse module which offers high performance, low memory usage, and compatibility with most of sparse linear algebra packages. Because of its limited flexibility, we also provide a DynamicSparseMatrix variante taillored for low-level sparse matrix assembly. Both of them can be either row major or column major: + +\code +#include +SparseMatrix > m1(1000,2000); // declare a 1000x2000 col-major compressed sparse matrix of complex +SparseMatrix m2(1000,2000); // declare a 1000x2000 row-major compressed sparse matrix of double +DynamicSparseMatrix > m1(1000,2000); // declare a 1000x2000 col-major dynamic sparse matrix of complex +DynamicSparseMatrix m2(1000,2000); // declare a 1000x2000 row-major dynamic sparse matrix of double +\endcode + +Although a sparse matrix could also be used to represent a sparse vector, for that purpose it is better to use the specialized SparseVector class: +\code +SparseVector > v1(1000); // declare a column sparse vector of complex of size 1000 +SparseVector v2(1000); // declare a row sparse vector of double of size 1000 +\endcode +Note that here the size of a vector denotes its dimension and not the number of nonzero coefficients which is initially zero (like sparse matrices). + + +\b Overview \b of \b the \b internal \b sparse \b storage \n +In order to get the best of the Eigen's sparse objects, it is important to have a rough idea of the way they are internally stored. The SparseMatrix class implements the common and generic Compressed Column/Row Storage scheme. It consists of three compact arrays storing the values with their respective inner coordinates, and pointer indices to the begining of each outer vector. For instance, let \c m be a column-major sparse matrix. Then its nonzero coefficients are sequentially stored in memory in a column-major order (\em values). A second array of integer stores the respective row index of each coefficient (\em inner \em indices). Finally, a third array of integer, having the same length than the number of columns, stores the index in the previous arrays of the first element of each column (\em outer \em indices). + +Here is an example, with the matrix: + + + + + + +
03000
2200017
75010
00000
001408
+ +and its internal representation using the Compressed Column Storage format: + + + +
Values: 22735141178
Inner indices: 1202 42 14
+Outer indices:
02456\em 7
+ +As you can guess, here the storage order is even more important than with dense matrix. We will therefore often make a clear difference between the \em inner and \em outer dimensions. For instance, it is easy to loop over the coefficients of an \em inner \em vector (e.g., a column of a column-major matrix), but completely inefficient to do the same for an \em outer \em vector (e.g., a row of a col-major matrix). + +The SparseVector class implements the same compressed storage scheme but, of course, without any outer index buffer. + +Since all nonzero coefficients of such a matrix are sequentially stored in memory, random insertion of new nonzeros can be extremely costly. To overcome this limitation, Eigen's sparse module provides a DynamicSparseMatrix class which is basically implemented as an array of SparseVector. In other words, a DynamicSparseMatrix is a SparseMatrix where the values and inner-indices arrays have been splitted into multiple small and resizable arrays. Assuming the number of nonzeros per inner vector is relatively low, this slight modification allow for very fast random insertion at the cost of a slight memory overhead and a lost of compatibility with other sparse libraries used by some of our highlevel solvers. Note that the major memory overhead comes from the extra memory preallocated by each inner vector to avoid an expensive memory reallocation at every insertion. + +To summarize, it is recommanded to use a SparseMatrix whenever this is possible, and reserve the use of DynamicSparseMatrix for matrix assembly purpose when a SparseMatrix is not flexible enough. The respective pro/cons of both representations are summarized in the following table: + + + + + + + + + + + + + + + +
SparseMatrixDynamicSparseMatrix
memory usage*****
sorted insertion******
random insertion \n in sorted inner vector****
sorted insertion \n in random inner vector-***
random insertion-**
coeff wise unary operators******
coeff wise binary operators******
matrix products*****(*)
transpose*****
redux*****
*= scalar*****
Compatibility with highlevel solvers \n (TAUCS, Cholmod, SuperLU, UmfPack)***-
+ + +\b Matrix \b and \b vector \b properties \n + +Here mat and vec represents any sparse-matrix and sparse-vector types respectively. + + + + + + + + + + +
Standard \n dimensions\code +mat.rows() +mat.cols()\endcode\code +vec.size() \endcode
Sizes along the \n inner/outer dimensions\code +mat.innerSize() +mat.outerSize()\endcode
Number of non \n zero coefficiens\code +mat.nonZeros() \endcode\code +vec.nonZeros() \endcode
+ + +\b Iterating \b over \b the \b nonzero \b coefficients \n + +Iterating over the coefficients of a sparse matrix can be done only in the same order than the storage order. Here is an example: + + +
+\code +SparseMatrixType mat(rows,cols); +for (int k=0; k\ +\code +SparseVector vec(size); +for (SparseVector::InnerIterator it(vec); it; ++it) +{ + it.value(); // == vec[ it.index() ] + it.index(); +} +\endcode +
+ + +\section TutorialSparseFilling Filling a sparse matrix + +Owing to the special storage scheme of a SparseMatrix, it is obvious that for performance reasons a sparse matrix cannot be filled as easily as a dense matrix. For instance the cost of a purely random insertion into a SparseMatrix is in O(nnz) where nnz is the current number of non zeros. In order to cover all uses cases with best efficiency, Eigen provides various mechanisms, from the easiest but slowest, to the fastest but restrictive one. + +If you don't have any prior knowledge about the order your matrix will be filled, then the best choice is to use a DynamicSparseMatrix. With a DynamicSparseMatrix, you can add or modify any coefficients at any time using the coeffRef(row,col) method. Here is an example: +\code +DynamicSparseMatrix aux(1000,1000); +aux.reserve(estimated_number_of_non_zero); // optional +for (...) + for each j // the j can be random + for each i interacting with j // the i can be random + aux.coeffRef(i,j) += foo(i,j); +\endcode +Then the DynamicSparseMatrix object can be converted to a compact SparseMatrix to be used, e.g., by one of our supported solver: +\code +SparseMatrix mat(aux); +\endcode + +In order to optimize this process, instead of the generic coeffRef(i,j) method one can also use: + - \code m.insert(i,j) = value; \endcode which assumes the coefficient of coordinate (row,col) does not already exist (otherwise this is a programming error and your program will stop). + - \code m.insertBack(i,j) = value; \endcode which, in addition to the requirements of insert(), also assumes that the coefficient of coordinate (row,col) will be inserted at the end of the target inner-vector. More precisely, if the matrix m is column major, then the row index of the last non zero coefficient of the j-th column must be smaller than i. + + +Actually, the SparseMatrix class also supports random insertion via the insert() method. However, its uses should be reserved in cases where the inserted non zero is nearly the last one of the compact storage array. In practice, this means it should be used only to perform random (or sorted) insertion into the current inner-vector while filling the inner-vectors in an increasing order. Moreover, with a SparseMatrix an insertion session must be closed by a call to finalize() before any use of the matrix. Here is an example for a column major matrix: + +\code +SparseMatrix mat(1000,1000); +mat.reserve(estimated_number_of_non_zero); // optional +for each j // should be in increasing order for performance reasons + for each i interacting with j // the i can be random + mat.insert(i,j) = foo(i,j); // optional for a DynamicSparseMatrix +mat.finalize(); +\endcode + +Finally, the fastest way to fill a SparseMatrix object is to insert the elements in a purely coherence order (increasing inner index per increasing outer index). To this end, Eigen provides a very low but optimal API and illustrated below: + +\code +SparseMatrix mat(1000,1000); +mat.reserve(estimated_number_of_non_zero); // optional +for(int j=0; j<1000; ++j) +{ + mat.startVec(j); // optional for a DynamicSparseMatrix + for each i interacting with j // with increasing i + mat.insertBack(i,j) = foo(i,j); +} +mat.finalize(); // optional for a DynamicSparseMatrix +\endcode +Note that there also exist the insertBackByOuterInner(Index outer, Index, inner) function which allows to write code agnostic to the storage order. + +\section TutorialSparseFeatureSet Supported operators and functions + +In the following \em sm denote a sparse matrix, \em sv a sparse vector, \em dm a dense matrix, and \em dv a dense vector. +In Eigen's sparse module we chose to expose only the subset of the dense matrix API which can be efficiently implemented. Moreover, all combinations are not always possible. For instance, it is not possible to add two sparse matrices having two different storage order. On the other hand it is perfectly fine to evaluate a sparse matrix/expression to a matrix having a different storage order: +\code +SparseMatrixType sm1, sm2, sm3; +sm3 = sm1.transpose() + sm2; // invalid +sm3 = SparseMatrixType(sm1.transpose()) + sm2; // correct +\endcode + +Here are some examples of the supported operations: +\code +s_1 *= 0.5; +sm4 = sm1 + sm2 + sm3; // only if s_1, s_2 and s_3 have the same storage order +sm3 = sm1 * sm2; +dv3 = sm1 * dv2; +dm3 = sm1 * dm2; +dm3 = dm2 * sm1; +sm3 = sm1.cwiseProduct(sm2); // only if s_1 and s_2 have the same storage order +dv2 = sm1.triangularView().solve(dv2); +\endcode + +The product of a sparse matrix A by a dense matrix/vector dv with A symmetric can be optimized by telling that to Eigen: +\code +res = A.selfadjointView<>() * dv; // if all coefficients of A are stored +res = A.selfadjointView() * dv; // if only the upper part of A is stored +res = A.selfadjointView() * dv; // if only the lower part of A is stored +\endcode + + +\section TutorialSparseDirectSolvers Using the direct solvers + +TODO + +\li \b Next: TODO + +*/ + +} diff --git a/doc/D01_StlContainers.dox b/doc/D01_StlContainers.dox index 83e930e50..e6c96c679 100644 --- a/doc/D01_StlContainers.dox +++ b/doc/D01_StlContainers.dox @@ -1,6 +1,6 @@ namespace Eigen { -/** \page StlContainers Troubleshooting - Using STL Containers with Eigen +/** \page TopicStlContainers Using STL Containers with Eigen \b Table \b of \b contents - \ref summary @@ -9,16 +9,16 @@ namespace Eigen { \section summary Executive summary -Using STL containers on \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types", or classes having members of such types, requires taking the following two steps: +Using STL containers on \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types", or classes having members of such types, requires taking the following two steps: \li A 16-byte-aligned allocator must be used. Eigen does provide one ready for use: aligned_allocator. \li If you want to use the std::vector container, you need to \#include . -These issues arise only with \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types" and \ref StructHavingEigenMembers "structures having such Eigen objects as member". For other Eigen types, such as Vector3f or MatrixXd, no special care is needed when using STL containers. +These issues arise only with \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types" and \ref TopicStructHavingEigenMembers "structures having such Eigen objects as member". For other Eigen types, such as Vector3f or MatrixXd, no special care is needed when using STL containers. \section allocator Using an aligned allocator -STL containers take an optional template parameter, the allocator type. When using STL containers on \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types", you need tell the container to use an allocator that will always allocate memory at 16-byte-aligned locations. Fortunately, Eigen does provide such an allocator: Eigen::aligned_allocator. +STL containers take an optional template parameter, the allocator type. When using STL containers on \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types", you need tell the container to use an allocator that will always allocate memory at 16-byte-aligned locations. Fortunately, Eigen does provide such an allocator: Eigen::aligned_allocator. For example, instead of \code diff --git a/doc/D03_WrongStackAlignment.dox b/doc/D03_WrongStackAlignment.dox index 09711af9c..3e6fc03d6 100644 --- a/doc/D03_WrongStackAlignment.dox +++ b/doc/D03_WrongStackAlignment.dox @@ -1,6 +1,6 @@ namespace Eigen { -/** \page WrongStackAlignment Troubleshooting - Compiler making a wrong assumption on stack alignment +/** \page TopicWrongStackAlignment Compiler making a wrong assumption on stack alignment This is an issue that, so far, we met only with GCC on Windows: for instance, MinGW and TDM-GCC. @@ -16,7 +16,7 @@ void foo() GCC assumes that the stack is already 16-byte-aligned so that the object \a q will be created at a 16-byte-aligned location. For this reason, it doesn't take any special care to explicitly align the object \a q, as Eigen requires. -The problem is that, in some particular cases, this assumption can be wrong on Windows, where the stack is only guaranteed to have 4-byte alignment. Indeed, even though GCC takes care of aligning the stack in the main function and does its best to keep it aligned, when a function is called from another thread or from a binary compiled with another compiler, the stack alignment can be corrupted. This results in the object 'q' being created at an unaligned location, making your program crash with the \ref UnalignedArrayAssert "assertion on unaligned arrays". So far we found the three following solutions. +The problem is that, in some particular cases, this assumption can be wrong on Windows, where the stack is only guaranteed to have 4-byte alignment. Indeed, even though GCC takes care of aligning the stack in the main function and does its best to keep it aligned, when a function is called from another thread or from a binary compiled with another compiler, the stack alignment can be corrupted. This results in the object 'q' being created at an unaligned location, making your program crash with the \ref TopicUnalignedArrayAssert "assertion on unaligned arrays". So far we found the three following solutions. \section sec_sol1 Local solution @@ -38,7 +38,7 @@ A global solution is to edit your project so that when compiling with GCC on Win \code -mincoming-stack-boundary=2 \endcode -Explanation: this tells GCC that the stack is only required to be aligned to 2^2=4 bytes, so that GCC now knows that it really must take extra care to honor the 16 byte alignment of \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types" when needed. +Explanation: this tells GCC that the stack is only required to be aligned to 2^2=4 bytes, so that GCC now knows that it really must take extra care to honor the 16 byte alignment of \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types" when needed. Another global solution is to pass this option to gcc: \code diff --git a/doc/D07_PassingByValue.dox b/doc/D07_PassingByValue.dox index d15b375a6..b1e5e683b 100644 --- a/doc/D07_PassingByValue.dox +++ b/doc/D07_PassingByValue.dox @@ -1,10 +1,10 @@ namespace Eigen { -/** \page PassingByValue Troubleshooting - Passing Eigen objects by value to functions +/** \page TopicPassingByValue Passing Eigen objects by value to functions Passing objects by value is almost always a very bad idea in C++, as this means useless copies, and one should pass them by reference instead. -With Eigen, this is even more important: passing \ref FixedSizeVectorizable "fixed-size vectorizable Eigen objects" by value is not only inefficient, it can be illegal or make your program crash! And the reason is that these Eigen objects have alignment modifiers that aren't respected when they are passed by value. +With Eigen, this is even more important: passing \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen objects" by value is not only inefficient, it can be illegal or make your program crash! And the reason is that these Eigen objects have alignment modifiers that aren't respected when they are passed by value. So for example, a function like this, where v is passed by value: diff --git a/doc/D09_StructHavingEigenMembers.dox b/doc/D09_StructHavingEigenMembers.dox index 07b6570dc..d6a24d951 100644 --- a/doc/D09_StructHavingEigenMembers.dox +++ b/doc/D09_StructHavingEigenMembers.dox @@ -1,6 +1,6 @@ namespace Eigen { -/** \page StructHavingEigenMembers Troubleshooting - Structures Having Eigen Members +/** \page TopicStructHavingEigenMembers Structures Having Eigen Members \b Table \b of \b contents - \ref summary @@ -13,7 +13,7 @@ namespace Eigen { \section summary Executive Summary -If you define a structure having members of \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types", you must overload its "operator new" so that it generates 16-bytes-aligned pointers. Fortunately, Eigen provides you with a macro EIGEN_MAKE_ALIGNED_OPERATOR_NEW that does that for you. +If you define a structure having members of \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types", you must overload its "operator new" so that it generates 16-bytes-aligned pointers. Fortunately, Eigen provides you with a macro EIGEN_MAKE_ALIGNED_OPERATOR_NEW that does that for you. \section what What kind of code needs to be changed? @@ -32,7 +32,7 @@ class Foo Foo *foo = new Foo; \endcode -In other words: you have a class that has as a member a \ref FixedSizeVectorizable "fixed-size vectorizable Eigen object", and then you dynamically create an object of that class. +In other words: you have a class that has as a member a \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen object", and then you dynamically create an object of that class. \section how How should such code be modified? @@ -102,7 +102,7 @@ public: \section dynamicsize What about dynamic-size matrices and vectors? -Dynamic-size matrices and vectors, such as Eigen::VectorXd, allocate dynamically their own array of coefficients, so they take care of requiring absolute alignment automatically. So they don't cause this issue. The issue discussed here is only with \ref FixedSizeVectorizable "fixed-size vectorizable matrices and vectors". +Dynamic-size matrices and vectors, such as Eigen::VectorXd, allocate dynamically their own array of coefficients, so they take care of requiring absolute alignment automatically. So they don't cause this issue. The issue discussed here is only with \ref TopicFixedSizeVectorizable "fixed-size vectorizable matrices and vectors". \section bugineigen So is this a bug in Eigen? diff --git a/doc/D11_UnalignedArrayAssert.dox b/doc/D11_UnalignedArrayAssert.dox index 23ab3a94d..1a0e5140c 100644 --- a/doc/D11_UnalignedArrayAssert.dox +++ b/doc/D11_UnalignedArrayAssert.dox @@ -1,6 +1,6 @@ namespace Eigen { -/** \page UnalignedArrayAssert Troubleshooting - Explanation of the assertion on unaligned arrays +/** \page TopicUnalignedArrayAssert Explanation of the assertion on unaligned arrays Hello! You are seeing this webpage because your program terminated on an assertion failure like this one:
@@ -49,9 +49,9 @@ class Foo
 Foo *foo = new Foo;
 \endcode
 
-then you need to read this separate page: \ref StructHavingEigenMembers "Structures Having Eigen Members".
+then you need to read this separate page: \ref TopicStructHavingEigenMembers "Structures Having Eigen Members".
 
-Note that here, Eigen::Vector2d is only used as an example, more generally the issue arises for all \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types".
+Note that here, Eigen::Vector2d is only used as an example, more generally the issue arises for all \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types".
 
 \section c2 Cause 2: STL Containers
 
@@ -63,9 +63,9 @@ struct my_class { ... Eigen::Matrix2f m; ... };
 std::map my_map;
 \endcode
 
-then you need to read this separate page: \ref StlContainers "Using STL Containers with Eigen".
+then you need to read this separate page: \ref TopicStlContainers "Using STL Containers with Eigen".
 
-Note that here, Eigen::Matrix2f is only used as an example, more generally the issue arises for all \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types" and \ref StructHavingEigenMembers "structures having such Eigen objects as member".
+Note that here, Eigen::Matrix2f is only used as an example, more generally the issue arises for all \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types" and \ref TopicStructHavingEigenMembers "structures having such Eigen objects as member".
 
 \section c3 Cause 3: Passing Eigen objects by value
 
@@ -75,9 +75,9 @@ If some function in your code is getting an Eigen object passed by value, like t
 void func(Eigen::Vector4d v);
 \endcode
 
-then you need to read this separate page: \ref PassingByValue "Passing Eigen objects by value to functions".
+then you need to read this separate page: \ref TopicPassingByValue "Passing Eigen objects by value to functions".
 
-Note that here, Eigen::Vector4d is only used as an example, more generally the issue arises for all \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types".
+Note that here, Eigen::Vector4d is only used as an example, more generally the issue arises for all \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types".
 
 \section c4 Cause 4: Compiler making a wrong assumption on stack alignment (for instance GCC on Windows)
 
@@ -91,13 +91,13 @@ void foo()
 }
 \endcode
 
-then you need to read this separate page: \ref WrongStackAlignment "Compiler making a wrong assumption on stack alignment".
+then you need to read this separate page: \ref TopicWrongStackAlignment "Compiler making a wrong assumption on stack alignment".
 
-Note that here, Eigen::Quaternionf is only used as an example, more generally the issue arises for all \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types".
+Note that here, Eigen::Quaternionf is only used as an example, more generally the issue arises for all \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types".
 
 \section explanation General explanation of this assertion
 
-\ref FixedSizeVectorizable "fixed-size vectorizable Eigen objects" must absolutely be created at 16-byte-aligned locations, otherwise SIMD instructions adressing them will crash.
+\ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen objects" must absolutely be created at 16-byte-aligned locations, otherwise SIMD instructions adressing them will crash.
 
 Eigen normally takes care of these alignment issues for you, by setting an alignment attribute on them and by overloading their "operator new".
 
diff --git a/doc/I00_CustomizingEigen.dox b/doc/I00_CustomizingEigen.dox
index cc4218f0c..fddd42348 100644
--- a/doc/I00_CustomizingEigen.dox
+++ b/doc/I00_CustomizingEigen.dox
@@ -1,6 +1,6 @@
 namespace Eigen {
 
-/** \page CustomizingEigen Advanced - Customizing/Extending Eigen
+/** \page TopicCustomizingEigen Customizing/Extending Eigen
 
 Eigen can be extended in several ways, for instance, by defining global methods, \ref ExtendingMatrixBase "by adding custom methods to MatrixBase", adding support to \ref CustomScalarType "custom types" etc.
 
diff --git a/doc/I01_TopicLazyEvaluation.dox b/doc/I01_TopicLazyEvaluation.dox
index 68fa1e2df..393bc41d8 100644
--- a/doc/I01_TopicLazyEvaluation.dox
+++ b/doc/I01_TopicLazyEvaluation.dox
@@ -1,6 +1,6 @@
 namespace Eigen {
 
-/** \page TopicLazyEvaluation Advanced - Lazy Evaluation and Aliasing
+/** \page TopicLazyEvaluation Lazy Evaluation and Aliasing
 
 Executive summary: Eigen has intelligent compile-time mechanisms to enable lazy evaluation and removing temporaries where appropriate.
 It will handle aliasing automatically in most cases, for example with matrix products. The automatic behavior can be overridden
diff --git a/doc/I02_HiPerformance.dox b/doc/I02_HiPerformance.dox
index c2148ab4d..a7d271109 100644
--- a/doc/I02_HiPerformance.dox
+++ b/doc/I02_HiPerformance.dox
@@ -1,7 +1,7 @@
 
 namespace Eigen {
 
-/** \page HiPerformance Advanced - Using Eigen with high performance
+/** \page TopicHiPerformance Using Eigen with high performance
 
 In general achieving good performance with Eigen does no require any special effort:
 simply write your expressions in the most high level way. This is especially true
diff --git a/doc/I03_InsideEigenExample.dox b/doc/I03_InsideEigenExample.dox
index 95cbe6800..e0f8d52a9 100644
--- a/doc/I03_InsideEigenExample.dox
+++ b/doc/I03_InsideEigenExample.dox
@@ -1,6 +1,6 @@
 namespace Eigen {
 
-/** \page InsideEigenExample Advanced - What happens inside Eigen, on a simple example
+/** \page TopicInsideEigenExample What happens inside Eigen, on a simple example
 
 \b Table \b of \b contents
   - \ref WhyInteresting
diff --git a/doc/I05_FixedSizeVectorizable.dox b/doc/I05_FixedSizeVectorizable.dox
index 9ec36898e..db8f10b5c 100644
--- a/doc/I05_FixedSizeVectorizable.dox
+++ b/doc/I05_FixedSizeVectorizable.dox
@@ -1,6 +1,6 @@
 namespace Eigen {
 
-/** \page FixedSizeVectorizable Advanced - Fixed-size vectorizable Eigen objects
+/** \page TopicFixedSizeVectorizable Fixed-size vectorizable Eigen objects
 
 The goal of this page is to explain what we mean by "fixed-size vectorizable".
 
diff --git a/doc/Overview.dox b/doc/Overview.dox
index e6f7349da..8bbdf1f1a 100644
--- a/doc/Overview.dox
+++ b/doc/Overview.dox
@@ -15,18 +15,33 @@ Eigen2 users: here is a \ref Eigen2ToEigen3 guide to help porting your applicati
 For a first contact with Eigen, the best place is to have a look at the \ref GettingStarted "tutorial". The \ref QuickRefPage "short reference" page gives you a quite complete description of the API in a very condensed format that is specially useful to recall the syntax of a particular features, or to have a quick look at the API. For Matlab users, there is also a ASCII quick reference with Matlab translations.
 
 \b Table \b of \b contents
+  - \ref Eigen2ToEigen3
   - \ref GettingStarted
   - \b Tutorial
     - \ref TutorialMatrixClass
     - \ref TutorialMatrixArithmetic
     - \ref TutorialArrayClass
     - \ref TutorialBlockOperations
-    - "Dense linear algebra"
-    - "Geometry"
-    - "Reductions, visitors, and broadcasting"
-    - "Sparse matrices"
+    - \ref TutorialAdvancedInitialization
+    - Comming soon: "Reductions, visitors, and broadcasting"
+    - \ref TutorialLinearAlgebra
+    - \ref TutorialGeometry
+    - \ref TutorialSparseMatrix
   - \ref QuickRefPage
-  - \ref Eigen2ToEigen3
+  - \b Advanced \b topics
+    - \ref TopicLazyEvaluation
+    - \ref TopicLinearAlgebraDecompositions
+    - \ref TopicCustomizingEigen
+    - \ref TopicInsideEigenExample
+    - \ref TopicHiPerformance
+  - Topics related to alignment issues
+    - \ref TopicUnalignedArrayAssert
+    - \ref TopicFixedSizeVectorizable
+    - \ref TopicStlContainers
+    - \ref TopicStructHavingEigenMembers
+    - \ref TopicPassingByValue
+    - \ref TopicWrongStackAlignment
+  
    
 
 Want more? Checkout the \ref Unsupported_modules "unsupported modules" documentation.
-- 
cgit v1.2.3