mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
big improvements to tutorial, especially page 2 (matrix arithmetic).
add placeholders for some 'special topic' pages.
This commit is contained in:
@@ -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
|
||||
|
||||
*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user