Tutorial page 3: add more cwise operations, condense rest.

This commit is contained in:
Jitse Niesen 2010-07-12 22:45:57 +01:00
parent 8e776c94c1
commit 140ad0908d
9 changed files with 121 additions and 160 deletions

View File

@ -7,7 +7,7 @@ namespace Eigen {
\li \b Next: \ref TutorialBlockOperations
This tutorial aims to provide an overview and explanations on how to use
Eigen's \link ArrayBase Array \endlink class
Eigen's Array class.
\b Table \b of \b contents
- \ref TutorialArrayClassIntro
@ -15,6 +15,7 @@ Eigen's \link ArrayBase Array \endlink class
- \ref TutorialArrayClassAccess
- \ref TutorialArrayClassAddSub
- \ref TutorialArrayClassMult
- \ref TutorialArrayClassCwiseOther
- \ref TutorialArrayClassConvert
\section TutorialArrayClassIntro What is the Array class?
@ -27,17 +28,17 @@ such as adding a constant to every coefficient in the array or multiplying two a
\section TutorialArrayClassTypes Array types
Array is a class template taking the same template parameters as Matrix.
As with Matrix, the first 3 template parameters are mandatory:
As with Matrix, the first three template parameters are mandatory:
\code
Array<typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime>
\endcode
And the last 3 template parameters are optional. Since this is exactly the same as for Matrix,
we won't reexplain it and just refer to \ref TutorialMatrixClass "this page".
The last three template parameters are optional. Since this is exactly the same as for Matrix,
we won't explain it again here and just refer to \ref TutorialMatrixClass.
Eigen also provides typedefs for some common cases, in a way that is similar to the Matrix typedefs
but with some slight differences, as the word "array" is used for both 1-dimensional and 2-dimensional arrays.
We adopt that convention that typedefs of the form ArrayNt stand for 1-dimensional arrays, where N and t are
as in the Matrix typedefs explained on \ref TutorialMatrixClass "this page". For 2-dimensional arrays, we
the size and the scalar type, as in the Matrix typedefs explained on \ref TutorialMatrixClass "this page". For 2-dimensional arrays, we
use typedefs of the form ArrayNNt. Some examples are shown in the following table:
<table class="tutorial_code" align="center">
@ -71,69 +72,103 @@ use typedefs of the form ArrayNNt. Some examples are shown in the following tabl
\section TutorialArrayClassAccess Accessing values inside an Array
Write and read access to coefficients of an array expression is done in the same way as with matrix expressions.
For example:
\include Tutorial_ArrayClass_accessors.cpp
Output:
\verbinclude Tutorial_ArrayClass_accessors.out
The parenthesis operator is overloaded to provide write and read access to the coefficients of an array, just as with matrices.
Furthermore, the \c << operator can be used to initialize arrays (via the comma initializer) or to print them.
For more information about the comma initializer, refer to \ref TutorialAdvancedInitialization "this page".
<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ArrayClass_accessors.cpp
</td>
<td>
Output: \verbinclude Tutorial_ArrayClass_accessors.out
</td></tr></table>
For more information about the comma initializer, see \ref TutorialAdvancedInitialization.
\section TutorialArrayClassAddSub Addition and substraction
\section TutorialArrayClassAddSub Addition and subtraction
Adding and subtracting two arrays is the same as for matrices.
The operation is valid if both arrays have the same size, and the addition or subtraction is done coefficient-wise.
Arrays also support expressions of the form <tt>array + scalar</tt> which add a scalar to each coefficient in the array.
This provides a functionality that is not directly available for Matrix objects.
<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ArrayClass_addition.cpp
</td>
<td>
Output: \verbinclude Tutorial_ArrayClass_addition.out
</td></tr></table>
Adding and substracting two arrays has the same result as for Matrices.
This is valid as long as both arrays have the same sizes:
\include Tutorial_ArrayClass_addition.cpp
Output:
\verbinclude Tutorial_ArrayClass_addition.out
It is also allowed to add a scalar to each coefficient in an Array,
providing a functionality that was not available for Matrix objects:
\include Tutorial_ArrayClass_addition_scalar.cpp
Output:
\verbinclude Tutorial_ArrayClass_addition_scalar.out
\subsection TutorialArrayClassMult Array multiplication
\section TutorialArrayClassMult Array multiplication
First of all, of course you can multiply an array by a scalar, this works in the same way as matrices. Where arrays
are fundamentally different from matrices, is when you multiply two arrays together. While Matrices interprete
multiplication as matrix product, arrays interprete multiplication as coefficient-wise product. For example:
are fundamentally different from matrices, is when you multiply two together. Matrices interpret
multiplication as the matrix product and arrays interpret multiplication as the coefficient-wise product. Thus, two
arrays can be multiplied if they have the same size.
\include Tutorial_ArrayClass_mult.cpp
Output:
\verbinclude Tutorial_ArrayClass_mult.out
<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ArrayClass_mult.cpp
</td>
<td>
Output: \verbinclude Tutorial_ArrayClass_mult.out
</td></tr></table>
\section TutorialArrayClassCwiseOther Other coefficient-wise operations
The Array class defined other coefficient-wise operations besides the addition, subtraction and multiplication
operators described about. For example, the \link ArrayBase::abs() .abs() \endlink method takes the absolute
value of each coefficient, while \link ArrayBase::sqrt() .sqrt() \endlink computes the square root of the
coefficients. If you have two arrays of the same size, you can call \link ArrayBase::min() .min() \endlink to
construct the array whose coefficients are the minimum of the corresponding coefficients of the two given
arrays. These operations are illustrated in the following example.
<table class="tutorial_code"><tr><td>
Example: \include Tutorial_ArrayClass_cwise_other.cpp
</td>
<td>
Output: \verbinclude Tutorial_ArrayClass_cwise_other.out
</td></tr></table>
More coefficient-wise operations can be found in the \ref QuickRefPage.
\section TutorialArrayClassConvert Converting between array and matrix expressions
It is possible to wrap a matrix expression as an array expression and conversely. This gives access to all operations
regardless of the choice of declaring objects as arrays or as matrices.
When should you use objects of the Matrix class and when should you use objects of the Array class? You cannot
apply Matrix operations on arrays, or Array operations on matrices. Thus, if you need to do linear algebraic
operations such as matrix multiplication, then you should use matrices; if you need to do coefficient-wise
operations, then you should use arrays. However, sometimes it is not that simple, but you need to use both
Matrix and Array operations. In that case, you need to convert a matrix to an array or reversely. This gives
access to all operations regardless of the choice of declaring objects as arrays or as matrices.
\link MatrixBase Matrix expressions \endlink have a \link MatrixBase::array() .array() \endlink method that
\link MatrixBase Matrix expressions \endlink have an \link MatrixBase::array() .array() \endlink method that
'converts' them into \link ArrayBase array expressions\endlink, so that coefficient-wise operations
can be applied easily. Conversely, \link ArrayBase array expressions \endlink
have a \link ArrayBase::matrix() .matrix() \endlink method. As with all Eigen expression abstractions,
this doesn't have any runtime cost (provided that you let your compiler optimize).
Both \link MatrixBase::array() .array() \endlink and \link ArrayBase::matrix() .matrix() \endlink
can be used as rvalues and as lvalues.
Mixing matrices and arrays in an expression is forbidden with Eigen. However,
Mixing matrices and arrays in an expression is forbidden with Eigen. For instance, you cannot add a amtrix and
array directly; the operands of a \c + operator should either both be matrices or both be arrays. However,
it is easy to convert from one to the other with \link MatrixBase::array() .array() \endlink and
\link ArrayBase::matrix() .matrix() \endlink.
\link ArrayBase::matrix() .matrix()\endlink. The exception to this rule is the assignment operator: it is
allowed to assign a matrix expression to an array variable, or to assign an array expression to a matrix
variable.
On the other hand, assigning a matrix (resp. array) expression to an array (resp. matrix) expression is allowed.
The following example shows how to use array operations on a Matrix object by employing the
\link MatrixBase::array() .array() \endlink method. For example, the statement
<tt>result = m.array() * n.array()</tt> takes two matrices \c m and \c n, converts them both to an array, uses
* to multiply them coefficient-wise and assigns the result to the matrix variable \c result (this is legal
because Eigen allows assigning array expressions to matrix variables).
\subsection TutorialArrayClassInteropMatrix Matrix to array example
The following example shows how to use array operations on a Matrix object by employing
the \link MatrixBase::array() .array() \endlink method:
As a matter of fact, this usage case is so common that Eigen provides a \link MatrixBase::cwiseProduct()
.cwiseProduct() \endlink method for matrices to compute the coefficient-wise product. This is also shown in
the example program.
<table class="tutorial_code"><tr><td>
\include Tutorial_ArrayClass_interop_matrix.cpp
@ -143,21 +178,13 @@ Output:
\verbinclude Tutorial_ArrayClass_interop_matrix.out
</td></tr></table>
Similarly, if \c array1 and \c array2 are arrays, then the expression <tt>array1.matrix() * array2.matrix()</tt>
computes their matrix product.
\subsection TutorialArrayClassInteropArray Array to matrix example
The following example shows how to use matrix operations with an Array
object by employing the \link ArrayBase::matrix() .matrix() \endlink method:
<table class="tutorial_code"><tr><td>
\include Tutorial_ArrayClass_interop_array.cpp
</td>
<td>
Output:
\verbinclude Tutorial_ArrayClass_interop_array.out
</td></tr></table>
\subsection TutorialArrayClassInteropCombination Example with combinations of .array() and .matrix()
Here is a more advanced example:
Here is a more advanced example. The expression <tt>(m.array() + 4).matrix() * m</tt> adds 4 to every
coefficient in the matrix \c m and then computes the matrix product of the result with \c m. Similarly, the
expression <tt>(m.array() * n.array()).matrix() * m</tt> computes the coefficient-wise product of the matrices
\c m and \c n and then the matrix product of the result with \c m.
<table class="tutorial_code"><tr><td>
\include Tutorial_ArrayClass_interop.cpp

View File

@ -10,7 +10,7 @@ int main()
// assign some values coefficient by coefficient
m(0,0) = 1.0; m(0,1) = 2.0;
m(1,0) = 3.0; m(1,1) = 4.0;
m(1,0) = 3.0; m(1,1) = m(0,1) + m(1,0);
// print values to standard output
cout << m << endl << endl;

View File

@ -8,15 +8,16 @@ int main()
{
ArrayXXf a(3,3);
ArrayXXf b(3,3);
a << 1,2,3,
4,5,6,
7,8,9;
b << 1,2,3,
1,2,3,
1,2,3;
cout << "a + b = " << endl
<< a + b << endl;
// Adding two arrays
cout << "a + b = " << endl << a + b << endl << endl;
// Subtracting a scalar from an array
cout << "a - 2 = " << endl << a - 2 << endl;
}

View File

@ -1,17 +0,0 @@
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
ArrayXXf a(3,3);
a << 1,2,3,
4,5,6,
7,8,9;
cout << "a + 2 = " << endl
<< a + 2 << endl;
}

View File

@ -0,0 +1,19 @@
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
ArrayXf a = ArrayXf::Random(5);
a *= 2;
cout << "a =" << endl
<< a << endl;
cout << "a.abs() =" << endl
<< a.abs() << endl;
cout << "a.abs().sqrt() =" << endl
<< a.abs().sqrt() << endl;
cout << "a.min(a.abs().sqrt()) =" << endl
<< a.min(a.abs().sqrt()) << endl;
}

View File

@ -8,31 +8,15 @@ int main()
{
MatrixXf m(2,2);
MatrixXf n(2,2);
MatrixXf result(2,2);
//initialize matrices
m << 1,2,
3,4;
n << 5,6,
7,8;
// mix of array and matrix operations
// first coefficient-wise addition
// then the result is used with matrix multiplication
result = (m.array() + 4).matrix() * m;
cout << "-- Combination 1: --" << endl
<< result << endl << endl;
// mix of array and matrix operations
// first coefficient-wise multiplication
// then the result is used with matrix multiplication
cout << "-- Combination 1: --" << endl << result << endl << endl;
result = (m.array() * n.array()).matrix() * m;
cout << "-- Combination 2: --" << endl
<< result << endl << endl;
cout << "-- Combination 2: --" << endl << result << endl << endl;
}

View File

@ -1,34 +0,0 @@
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
using namespace std;
int main()
{
ArrayXXf m(2,2);
ArrayXXf n(2,2);
ArrayXXf result(2,2);
//initialize arrays
m << 1,2,
3,4;
n << 5,6,
7,8;
// --> array multiplication
result = m * n;
cout << "-- Array m*n: --" << endl
<< result << endl << endl;
// --> Matrix multiplication
result = m.matrix() * n.matrix();
cout << "-- Matrix m*n: --" << endl
<< result << endl << endl;
}

View File

@ -8,34 +8,19 @@ int main()
{
MatrixXf m(2,2);
MatrixXf n(2,2);
MatrixXf result(2,2);
//initialize matrices
m << 1,2,
3,4;
n << 5,6,
7,8;
// --> matrix multiplication
result = m * n;
cout << "-- Matrix m*n: --" << endl
<< result << endl << endl;
// --> coeff-wise multiplication
cout << "-- Matrix m*n: --" << endl << result << endl << endl;
result = m.array() * n.array();
cout << "-- Array m*n: --" << endl
<< result << endl << endl;
// ->> coeff-wise addition of a scalar
cout << "-- Array m*n: --" << endl << result << endl << endl;
result = m.cwiseProduct(n);
cout << "-- With cwiseProduct: --" << endl << result << endl << endl;
result = m.array() + 4;
cout << "-- Array m + 4: --" << endl
<< result << endl << endl;
cout << "-- Array m + 4: --" << endl << result << endl << endl;
}

View File

@ -8,13 +8,9 @@ int main()
{
ArrayXXf a(2,2);
ArrayXXf b(2,2);
a << 1,2,
3,4;
b << 5,6,
7,8;
cout << "a * b = " << endl
<< a * b << endl;
cout << "a * b = " << endl << a * b << endl;
}