mirror of
https://gitlab.com/libeigen/eigen.git
synced 2024-12-15 07:10:37 +08:00
248 lines
8.1 KiB
Plaintext
248 lines
8.1 KiB
Plaintext
|
namespace Eigen {
|
||
|
|
||
|
/** \page TutorialMatrixArithmetic Tutorial - 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.
|
||
|
|
||
|
\b Table \b of \b contents
|
||
|
- \ref TutorialMatrixArithmCommaInitializer
|
||
|
- \ref TutorialMatrixArithmElementaryOperations
|
||
|
- \ref TutorialMatrixArithmExamples
|
||
|
- \ref TutorialMatrixArithmProduct
|
||
|
- \ref TutorialMatrixArithmSimpleExample
|
||
|
- \ref TutorialMatrixCombiningOperators
|
||
|
- \ref TutorialMatrixOperatorValidity
|
||
|
- \ref TutorialMatrixArithmReductionOperations
|
||
|
|
||
|
|
||
|
\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:
|
||
|
\code
|
||
|
1 2 3
|
||
|
4 5 6
|
||
|
7 8 9
|
||
|
\endcode
|
||
|
</td></tr></table>
|
||
|
|
||
|
Moreover, Eigen also supports to load a matrix through a set of blocks:
|
||
|
<table class="tutorial_code"><tr><td>
|
||
|
\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;
|
||
|
\endcode
|
||
|
</td>
|
||
|
<td>
|
||
|
output:
|
||
|
\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
|
||
|
\endcode
|
||
|
</td></tr></table>
|
||
|
|
||
|
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 TutorialMatrixArithmElementaryOperations Basic arithmetic operators
|
||
|
|
||
|
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.
|
||
|
|
||
|
\subsection TutorialMatrixArithmExamples Usage examples
|
||
|
Some basic examples are presented in the following table, showing how easy it is to express arithmetic operations with Eigen.
|
||
|
|
||
|
<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.
|
||
|
|
||
|
<table class="tutorial_code" align="center">
|
||
|
<tr><td align="center">\b Reduction \b operation</td><td align="center">\b Usage \b example</td></tr>
|
||
|
<tr><td>
|
||
|
Sum of all the coefficients in a matrix</td><td>\code
|
||
|
MatrixXf m;
|
||
|
float totalSum = m.sum();\endcode</td></tr>
|
||
|
<tr><td>
|
||
|
Maximum coefficient in a matrix</td><td>\code
|
||
|
MatrixXf m;
|
||
|
int row, col;
|
||
|
|
||
|
// minimum value will be stored in minValue
|
||
|
// and the row and column where it was found in row and col,
|
||
|
// (these two parameters are optional)
|
||
|
float minValue = m.minCoeff(&row,&col);\endcode</td></tr>
|
||
|
<tr><td>
|
||
|
Maximum coefficient in a matrix</td><td>\code
|
||
|
MatrixXf m;
|
||
|
int row, col;
|
||
|
|
||
|
// maximum value will be stored in maxValue
|
||
|
// and the row and column where it was found in row and col,
|
||
|
// (these two parameters are optional)
|
||
|
float maxValue = m.maxCoeff(&row,&col);\endcode</td></tr>
|
||
|
<tr><td>
|
||
|
Product between all coefficients in a matrix</td><td>\code
|
||
|
MatrixXf m;
|
||
|
|
||
|
float product = m.prod();\endcode</td></tr>
|
||
|
<tr><td>
|
||
|
Mean of coefficients in a matrix</td><td>\code
|
||
|
MatrixXf m;
|
||
|
|
||
|
float mean = m.mean();\endcode</td></tr>
|
||
|
<tr><td>
|
||
|
Matrix's trace</td><td>\code
|
||
|
MatrixXf m;
|
||
|
|
||
|
float trace = m.trace();\endcode</td></tr>
|
||
|
</table>
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
*/
|
||
|
|
||
|
}
|