big improvements to tutorial, especially page 2 (matrix arithmetic).

add placeholders for some 'special topic' pages.
This commit is contained in:
Benoit Jacob
2010-06-26 14:00:00 -04:00
parent 1c783e252f
commit e078bb2637
16 changed files with 350 additions and 202 deletions

View File

@@ -1,202 +1,125 @@
namespace Eigen {
/** \page TutorialMatrixArithmetic Tutorial - Matrix and vector arithmetic
/** \page TutorialMatrixArithmetic Tutorial page 2 - %Matrix and vector arithmetic
\ingroup Tutorial
This tutorial aims to provide an overview and some details on how to perform arithmetic between matrices, vectors and scalars with Eigen.
\li \b Previous: \ref TutorialMatrixClass
\li \b Next: \ref TutorialArrayClass
This tutorial aims to provide an overview and some details on how to perform arithmetic
between matrices, vectors and scalars with Eigen.
\b Table \b of \b contents
- \ref TutorialMatrixArithmCommaInitializer
- \ref TutorialMatrixArithmElementaryOperations
- \ref TutorialMatrixArithmExamples
- \ref TutorialMatrixArithmProduct
- \ref TutorialMatrixArithmSimpleExample
- \ref TutorialMatrixCombiningOperators
- \ref TutorialMatrixOperatorValidity
- \ref TutorialMatrixArithmReductionOperations
- \ref TutorialArithmeticIntroduction
- \ref TutorialArithmeticMentionCommaInitializer
- \ref TutorialArithmeticAddSub
- \ref TutorialArithmeticScalarMulDiv
- \ref TutorialArithmeticMentionXprTemplates
- \ref TutorialArithmeticMatrixMul
- \ref TutorialArithmeticDotAndCross
- \ref TutorialArithmeticRedux
- \ref TutorialArithmeticValidity
\section TutorialArithmeticIntroduction Introduction
\section TutorialMatrixArithmCommaInitializer Comma initializer
Eigen offers a comma initializer syntax which allows to set all the coefficients of any dense objects (matrix, vector, array, block, etc.) to specific values:
<table class="tutorial_code"><tr><td>
\code Matrix3f m;
m << 1, 2, 3,
4, 5, 6,
7, 8, 9;
cout << m;
\endcode
</td>
<td>
output:
Eigen offers matrix/vector arithmetic operations either through overloads of common C++ arithmetic operators such as +, -, *,
or through special methods such as dot(), cross(), etc.
For the Matrix class (matrices and vectors), operators are only overloaded to support
linear-algebraic operations. For example, \c matrix1 \c * \c matrix2 means matrix-matrix product,
and \c vector \c + \c scalar is just not allowed. If you want to perform all kinds of array operations,
not linear algebra, see \ref TutorialArrayClass "next page".
\section TutorialArithmeticMentionCommaInitializer A note about comma-initialization
In examples below, we'll be initializing matrices with a very convenient device known as the \em comma-initializer.
For now, it is enough to know this example:
\include Tutorial_commainit_01.cpp
Output: \verbinclude Tutorial_commainit_01.out
The comma initializer is discussed in \ref TutorialAdvancedInitialization "this page".
\section TutorialArithmeticAddSub Addition and substraction
The left hand side and right hand side must, of course, have the same numbers of rows and of columns. They must
also have the same \c Scalar type, as Eigen doesn't do automatic type promotion. The operators at hand here are:
\li binary operator + as in \c a+b
\li binary operator - as in \c a-b
\li unary operator - as in \c -a
\li compound operator += as in \c a+=b
\li compound operator -= as in \c a-=b
Example: \include tut_arithmetic_add_sub.cpp
Output: \verbinclude tut_arithmetic_add_sub.out
\section TutorialArithmeticScalarMulDiv Scalar multiplication and division
Multiplication and division by a scalar is very simple too. The operators at hand here are:
\li binary operator * as in \c matrix*scalar
\li binary operator * as in \c scalar*matrix
\li binary operator / as in \c matrix/scalar
\li compound operator *= as in \c matrix*=scalar
\li compound operator /= as in \c matrix/=scalar
Example: \include tut_arithmetic_scalar_mul_div.cpp
Output: \verbinclude tut_arithmetic_scalar_mul_div.out
\section TutorialArithmeticMentionXprTemplates A note about expression templates
This is an advanced topic that we explain in \ref TopicEigenExpressionTemplates "this page",
but it is useful to just mention it now. In Eigen, arithmetic operators such as \c operator+ don't
perform any computation by themselves, they just return an "expression object" describing the computation to be
performed. The actual computation happens later, when the whole expression is evaluated, typically in \c operator=.
While this might sound heavy, any modern optimizing compiler is able to optimize away that abstraction and
the result is perfectly optimized code. For example, when you do:
\code
1 2 3
4 5 6
7 8 9
VectorXf a(50), b(50), c(50), d(50);
...
a = 3*b + 4*c + 5*d;
\endcode
</td></tr></table>
Moreover, Eigen also supports to load a matrix through a set of blocks:
<table class="tutorial_code"><tr><td>
Eigen compiles it to just one for loop, so that the arrays are traversed only once. Simplyfying (e.g. ignoring
SIMD optimizations), this loop looks like this:
\code
int rows=5, cols=5;
MatrixXf m(rows,cols);
m << (Matrix3f() << 1, 2, 3, 4, 5, 6, 7, 8, 9).finished(),
MatrixXf::Zero(3,cols-3),
MatrixXf::Zero(rows-3,3),
MatrixXf::Identity(rows-3,cols-3);
cout << m;
for(int i = 0; i < 50; ++i)
a[i] = 3*b[i] + 4*c[i] + 5*d[i];
\endcode
</td>
<td>
output:
Thus, you should not be afraid of using relatively large arithmetic expressions with Eigen: it only gives Eigen
more opportunities for optimization.
\section TutorialArithmeticMatrixMul Matrix-matrix and matrix-vector multiplication
Matrix-matrix multiplication is again done with \c operator*. Since vectors are a special
case of matrices, they are implicitly handled there too, so matrix-vector product is really just a special
case of matrix-matrix product, and so is vector-vector outer product. Thus, all these cases are handled by just
two operators:
\li binary operator * as in \c a*b
\li compound operator *= as in \c a*=b
Example: \include tut_arithmetic_matrix_mul.cpp
Output: \verbinclude tut_arithmetic_matrix_mul.out
Note: if you read the above paragraph on expression templates and are worried that doing \c m=m*m might cause
aliasing issues, be reassured for now: Eigen treats matrix multiplication as a special case and takes care of
introducing a temporary here, so it will compile \c m=m*m as:
\code
1 2 3 0 0
4 5 6 0 0
7 8 9 0 0
0 0 0 1 0
0 0 0 0 1
tmp = m*m;
m = tmp;
\endcode
</td></tr></table>
For more details on this topic, see \ref TopicEigenExpressionTemplates "this page".
FIXME: is this still needed?
<span class="note">\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.</span>
\section TutorialArithmeticDotAndCross Dot product and cross product
\section TutorialMatrixArithmElementaryOperations Basic arithmetic operators
The above-discussed \c operator* does not allow to compute dot and cross products. For that, you need the dot() and cross() methods.
Example: \include tut_arithmetic_dot_cross.cpp
Output: \verbinclude tut_arithmetic_dot_cross.out
Eigen takes advantage of C++ operator overloading to make arithmetic operations intuitive. In the case of matrices and vectors, Eigen only supports arithmetic operations that have a linear-algebraic meaning. Therefore, adding an scalar to a vector or matrix cannot be written as \p scalar \p + \p matrix . Nonetheless, Eigen provides an Array class that is able to perform other types of operations such as column-wise and row-wise addition, substraction, etc. For more information see FIXME:link to Array class.
Remember that cross product is only for vectors of size 3. Dot product is for vectors of any sizes.
When using complex numbers, Eigen's dot product is conjugate-linear in the first variable and linear in the
second variable.
\subsection TutorialMatrixArithmExamples Usage examples
Some basic examples are presented in the following table, showing how easy it is to express arithmetic operations with Eigen.
\section TutorialArithmeticRedux Basic arithmetic reduction operations
Eigen also provides some reduction operations to obtain values such as the sum or the maximum
or minimum of all the coefficients in a given matrix or vector.
<table class="tutorial_code" align="center">
<tr><td>
matrix/vector product \matrixworld</td><td>\code
col2 = mat1 * col1;
row2 = row1 * mat1; row1 *= mat1;
mat3 = mat1 * mat2; mat3 *= mat1; \endcode
</td></tr>
<tr><td>
add/subtract</td><td>\code
mat3 = mat1 + mat2; mat3 += mat1;
mat3 = mat1 - mat2; mat3 -= mat1;\endcode
</td></tr>
<tr><td>
scalar product/division</td><td>\code
mat3 = mat1 * s1; mat3 = s1 * mat1; mat3 *= s1;
mat3 = mat1 / s1; mat3 /= s1;\endcode
</td></tr>
</table>
\subsection TutorialMatrixArithmProduct Product types
It is important to point out that the product operation can be understood in different ways between matrices and vectors. Eigen treats the \p * \operator as matrix product or multiplication by a scalar. However, dot and cross products are also supported through the \p .dot() and \p .cross() operations:
\code
Matrix3f m1,m2,m3;
Vector3f v1,v2,v3;
// matrix product
m1 = m2 * m3;
// vector cross product: v1 = v2 X v3
v1 = v2.cross(v3);
// vector dot product: v2 . v3 (returns scalar)
float dotResult = v2.dot(v3);
\endcode
<strong> Note:</strong> cross product is only defined for 3-dimensional vectors.
\subsection TutorialMatrixArithmSimpleExample A simple example with matrix linear algebra
The next piece of code shows a simple program that creates two dynamic 3x3 matrices and initializes them, performing some simple operations and displaying the results at each step.
\code
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
int main()
{
MatrixXf m(3,3); // Matrix m is 3x3
VectorXf n(3,3); // 3-component vector
m << 1,2,3, // Assign some values to m
4,5,6,
7,8,9;
n << 10,11,12, // Assign some values to n
13,14,15,
16,17,18;
// simple matrix-product-scalar
std::cout << "3*m = " << 3*m << std::endl;
// simple matrix-divided-by-scalar
std::cout << "m/3 = " << m/3 << std::endl;
// matrix multiplication
std::cout << "m*n = " << m*n << std::endl;
return 0;
}
\endcode
\subsection TutorialMatrixCombiningOperators Combining operators in a single statement
As said before, Eigen's classes already provide implementations for linear-algebra operations. Combining operators in more complex expressions is posssible and often desirable, since it may help to avoid temporary memory allocations, making code execution faster (FIXME: add reference to lazy evaluation?) :
\code
MatrixXf m(3,3), n(3,3);
MatrixXf q(3,3), p(3,3);
// initialize... etc
.....
// METHOD 1: use temporary allocation
{
MatrixXf tempMatrix;
tempMatrix = m + 3*n;
p = tempMatrix * q;
}
// METHOD 2: avoids extra memory allocation if possible
// (Eigen will take care of that automatically)
p = (m + 3*n) * q; // matrix addition and multiplication by a vector
\endcode
Eigen will try to do its best in order to avoid temporary allocation and evaluate the expressions as fast as possible. FIXME: anything else to say here, is this correct?
\subsection TutorialMatrixOperatorValidity Validity of operations
The validity of the operations between matrices depend on the data type. In order to report whether an operation is valid or not, Eigen makes use of both compile-time and run-time information. In the case that the size of the matrices and vectors involved in the operations are known at compile time (fixed-size matrices such as \p Matrix3f), Eigen will be able to perfom a compile-time check and stop the compiler with an error if one of the operations is not possible:
\code
Matrix3f m;
Vector4f v;
v = m*v; // Compile-time error: YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES
\endcode
On the other hand, operations between dynamic-size matrices will take place at run-time, generating a run-time assertion if invalid operands are detected. FIXME: link to how to change the handler?
\code
MatrixXf m(3,3);
VectorXf v(4);
v = m * v; // Run-time assertion: "invalid matrix product"
\endcode
\section TutorialMatrixArithmReductionOperations Basic arithmetic reduction operations
Eigen also provides some basic but extremely useful reduction arithmetic operators to obtain values such as the sum or the maximum or minimum of all the coefficients in a given matrix or vector. The following table presents the basic arithmetic reduction operations and their syntax.
TODO: convert this from table format to tutorial/examples format.
<table class="tutorial_code" align="center">
<tr><td align="center">\b Reduction \b operation</td><td align="center">\b Usage \b example</td></tr>
@@ -239,8 +162,29 @@ MatrixXf m;
float trace = m.trace();\endcode</td></tr>
</table>
\subsection TutorialArithmeticValidity Validity of operations
Eigen checks the validity of the operations that you perform. When possible,
it checks them at compile-time, producing compilation errors. These error messages can be long and ugly,
but Eigen writes the important message in UPPERCASE_LETTERS_SO_IT_STANDS_OUT. For example:
\code
Matrix3f m;
Vector4f v;
v = m*v; // Compile-time error: YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES
\endcode
Of course, in many cases, for example when checking dynamic sizes, the check cannot be performed at compile time.
Eigen then uses runtime assertions. This means that executing an illegal operation will result in a crash at runtime,
with an error message.
\code
MatrixXf m(3,3);
VectorXf v(4);
v = m * v; // Run-time assertion failure here: "invalid matrix product"
\endcode
For more details on this topic, see \ref TopicAssertions "this page".
\li \b Next: \ref TutorialArrayClass
*/