diff --git a/Eigen/src/Core/BandMatrix.h b/Eigen/src/Core/BandMatrix.h index 3f2608c13..a1f71d5f6 100644 --- a/Eigen/src/Core/BandMatrix.h +++ b/Eigen/src/Core/BandMatrix.h @@ -181,9 +181,9 @@ class BandMatrixBase : public EigenBase * \param Supers Number of super diagonal * \param Subs Number of sub diagonal * \param _Options A combination of either \b RowMajor or \b ColMajor, and of \b SelfAdjoint - * The former controls storage order, and defaults to column-major. The latter controls - * whether the matrix represent a selfadjoint matrix in which case either Supers of Subs - * have to be null. + * The former controls \ref TopicStorageOrders "storage order", and defaults to + * column-major. The latter controls whether the matrix represents a selfadjoint + * matrix in which case either Supers of Subs have to be null. * * \sa class TridiagonalMatrix */ diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index b8fa9d1cd..91465f026 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -185,8 +185,8 @@ template class DenseBase /** \returns the outer size. * * \note For a vector, this returns just 1. For a matrix (non-vector), this is the major dimension - * with respect to the storage order, i.e., the number of columns for a column-major matrix, - * and the number of rows for a row-major matrix. */ + * with respect to the \ref TopicStorageOrders "storage order", i.e., the number of columns for a + * column-major matrix, and the number of rows for a row-major matrix. */ Index outerSize() const { return IsVectorAtCompileTime ? 1 @@ -196,8 +196,8 @@ template class DenseBase /** \returns the inner size. * * \note For a vector, this is just the size. For a matrix (non-vector), this is the minor dimension - * with respect to the storage order, i.e., the number of rows for a column-major matrix, - * and the number of columns for a row-major matrix. */ + * with respect to the \ref TopicStorageOrders "storage order", i.e., the number of rows for a + * column-major matrix, and the number of columns for a row-major matrix. */ Index innerSize() const { return IsVectorAtCompileTime ? this->size() diff --git a/Eigen/src/Core/Map.h b/Eigen/src/Core/Map.h index f78e87e39..8f0d87b51 100644 --- a/Eigen/src/Core/Map.h +++ b/Eigen/src/Core/Map.h @@ -44,7 +44,7 @@ * data is laid out contiguously in memory. You can however override this by explicitly specifying * inner and outer strides. * - * Here's an example of simply mapping a contiguous array as a column-major matrix: + * Here's an example of simply mapping a contiguous array as a \ref TopicStorageOrders "column-major" matrix: * \include Map_simple.cpp * Output: \verbinclude Map_simple.out * @@ -74,7 +74,7 @@ * * This class is the return type of Matrix::Map() but can also be used directly. * - * \sa Matrix::Map() + * \sa Matrix::Map(), \ref TopicStorageOrders */ namespace internal { diff --git a/Eigen/src/Core/Matrix.h b/Eigen/src/Core/Matrix.h index 2b7202c62..7e3279094 100644 --- a/Eigen/src/Core/Matrix.h +++ b/Eigen/src/Core/Matrix.h @@ -45,7 +45,7 @@ * The remaining template parameters are optional -- in most cases you don't have to worry about them. * \tparam _Options \anchor matrix_tparam_options A combination of either \b RowMajor or \b ColMajor, and of either * \b AutoAlign or \b DontAlign. - * The former controls storage order, and defaults to column-major. The latter controls alignment, which is required + * The former controls \ref TopicStorageOrders "storage order", and defaults to column-major. The latter controls alignment, which is required * for vectorization. It defaults to aligning matrices except for fixed sizes that aren't a multiple of the packet size. * \tparam _MaxRows Maximum number of rows. Defaults to \a _Rows (\ref maxrows "note"). * \tparam _MaxCols Maximum number of columns. Defaults to \a _Cols (\ref maxrows "note"). @@ -107,7 +107,8 @@ * are the dimensions of the original matrix, while _Rows and _Cols are Dynamic. * * - * \see MatrixBase for the majority of the API methods for matrices, \ref TopicClassHierarchy + * \see MatrixBase for the majority of the API methods for matrices, \ref TopicClassHierarchy, + * \ref TopicStorageOrders */ namespace internal { diff --git a/Eigen/src/Core/Stride.h b/Eigen/src/Core/Stride.h index 9425253ec..0430f1116 100644 --- a/Eigen/src/Core/Stride.h +++ b/Eigen/src/Core/Stride.h @@ -51,7 +51,7 @@ * \include Map_general_stride.cpp * Output: \verbinclude Map_general_stride.out * - * \sa class InnerStride, class OuterStride + * \sa class InnerStride, class OuterStride, \ref TopicStorageOrders */ template class Stride diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h index 7ba91d6db..2ffeb7948 100644 --- a/Eigen/src/Core/util/Constants.h +++ b/Eigen/src/Core/util/Constants.h @@ -56,7 +56,8 @@ const int Infinity = -1; * for a matrix, this means that the storage order is row-major. * If this bit is not set, the storage order is column-major. * For an expression, this determines the storage order of - * the matrix created by evaluation of that expression. */ + * the matrix created by evaluation of that expression. + * \sa \ref TopicStorageOrders */ const unsigned int RowMajorBit = 0x1; /** \ingroup flags diff --git a/doc/I08_StorageOrders.dox b/doc/I08_StorageOrders.dox deleted file mode 100644 index 0ceb771d3..000000000 --- a/doc/I08_StorageOrders.dox +++ /dev/null @@ -1,11 +0,0 @@ -namespace Eigen { - -/** \page TopicStorageOrders Storage orders - - -TODO: write this dox page! - -Is linked from the tutorial on the Matrix class. - -*/ -} diff --git a/doc/I15_StorageOrders.dox b/doc/I15_StorageOrders.dox new file mode 100644 index 000000000..6b56ca8f8 --- /dev/null +++ b/doc/I15_StorageOrders.dox @@ -0,0 +1,91 @@ +namespace Eigen { + +/** \page TopicStorageOrders Storage orders + +There are two different storage orders for matrices and two-dimensional arrays: column-major and row-major. +This page explains these storage orders and how to specify which one should be used. + +Table of contents + - \ref TopicStorageOrdersIntro + - \ref TopicStorageOrdersInEigen + - \ref TopicStorageOrdersWhich + + +\section TopicStorageOrdersIntro Column-major and row-major storage + +The entries of a matrix form a two-dimensional grid. However, when the matrix is stored in memory, the entries +have to somehow be laid out linearly. There are two main ways to do this, by row and by column. + +We say that a matrix is stored in \b row-major order if it is stored row by row. The entire first row is +stored first, followed by the entire second row, and so on. Consider for example the matrix + +\f[ +A = \begin{bmatrix} +8 & 2 & 2 & 9 \\ +9 & 1 & 4 & 4 \\ +3 & 5 & 4 & 5 +\end{bmatrix}. +\f] + +If this matrix is stored in row-major order, then the entries are laid out in memory as follows: + +\code 8 2 2 9 9 1 4 4 3 5 4 5 \endcode + +On the other hand, a matrix is stored in \b column-major order if it is stored column by column, starting with +the entire first column, followed by the entire second column, and so on. If the above matrix is stored in +column-major order, it is laid out as follows: + +\code 8 9 3 2 1 5 2 4 4 9 4 5 \endcode + +This example is illustrated by the following Eigen code. It uses the PlainObjectBase::data() function, which +returns a pointer to the memory location of the first entry of the matrix. + + + + +
ExampleOutput
+\include TopicStorageOrders_example.cpp + +\verbinclude TopicStorageOrders_example.out +
+ + +\section TopicStorageOrdersInEigen Storage orders in Eigen + +The storage order of a matrix or a two-dimensional array can be set by specifying the \c Options template +parameter for Matrix or Array. As \ref TutorialMatrixClass explains, the %Matrix class template has six +template parameters, of which three are compulsory (\c Scalar, \c RowsAtCompileTime and \c ColsAtCompileTime) +and three are optional (\c Options, \c MaxRowsAtCompileTime and \c MaxColsAtCompileTime). If the \c Options +parameter is set to \c RowMajor, then the matrix or array is stored in row-major order; if it is set to +\c ColMajor, then it is stored in column-major order. This mechanism is used in the above Eigen program to +specify the storage order. + +If the storage order is not specified, then Eigen normally defaults to storing the entry in column-major +order. This is also the case if one of the convenience typedefs (\c Matrix3f, \c ArrayXXd, etc.) is +used. However, it is possible to change the default to row-major order by defining the +\c EIGEN_DEFAULT_TO_ROW_MAJOR \ref TopicPreprocessorDirectives "preprocessor directive". + +Matrices and arrays using one storage order can be assigned to matrices and arrays using the other storage +order, as happens in the above program when \c Arowmajor is initialized using \c Acolmajor. Eigen will reorder +the entries automatically. More generally, row-major and column-major matrices can be mixed in an expression +as we want. + + +\section TopicStorageOrdersWhich Which storage order to choose? + +So, which storage order should you use in your program? There is no simple answer to this question; it depends +on your application. Here are some points to keep in mind: + + - Your users may expect you to use a specific storage order. Alternatively, you may use other libraries than + Eigen, and these other libraries may expect a certain storage order. In these cases it may be easiest and + fastest to use this storage order in your whole program. + - Algorithms that traverse a matrix row by row will go faster when the matrix is stored in row-major order + because of better data locality. Similarly, column-by-column traversal is faster for column-major + matrices. It may be worthwhile to experiment a bit to find out what is faster for your particular + application. + - The default in Eigen is column-major. Naturally, most of the development and testing of the Eigen library + is thus done with column-major matrices. This means that, even though we aim to support column-major and + row-major storage orders transparently, the Eigen library may well work best with column-major matrices. + +*/ +} diff --git a/doc/Overview.dox b/doc/Overview.dox index a4c4cde5d..04bc075f0 100644 --- a/doc/Overview.dox +++ b/doc/Overview.dox @@ -34,6 +34,7 @@ For a first contact with Eigen, the best place is to have a look at the \ref Get - \ref TopicLinearAlgebraDecompositions - \ref TopicCustomizingEigen - \ref TopicPreprocessorDirectives + - \ref TopicStorageOrders - \ref TopicInsideEigenExample - \ref TopicWritingEfficientProductExpression - \ref TopicClassHierarchy diff --git a/doc/snippets/TopicStorageOrders_example.cpp b/doc/snippets/TopicStorageOrders_example.cpp new file mode 100644 index 000000000..0623ef0c2 --- /dev/null +++ b/doc/snippets/TopicStorageOrders_example.cpp @@ -0,0 +1,18 @@ +Matrix Acolmajor; +Acolmajor << 8, 2, 2, 9, + 9, 1, 4, 4, + 3, 5, 4, 5; +cout << "The matrix A:" << endl; +cout << Acolmajor << endl << endl; + +cout << "In memory (column-major):" << endl; +for (int i = 0; i < Acolmajor.size(); i++) + cout << *(Acolmajor.data() + i) << " "; +cout << endl << endl; + +Matrix Arowmajor = Acolmajor; +cout << "In memory (row-major):" << endl; +for (int i = 0; i < Arowmajor.size(); i++) + cout << *(Arowmajor.data() + i) << " "; +cout << endl; +