doc: Mention vec=vec.head(n) in aliasing page.

This commit is contained in:
Jitse Niesen 2013-07-02 13:35:36 +01:00
parent 1caeb814f0
commit 419b5cff44
2 changed files with 29 additions and 23 deletions

View File

@ -388,7 +388,7 @@ struct checkTransposeAliasing_impl
eigen_assert((!check_transpose_aliasing_run_time_selector eigen_assert((!check_transpose_aliasing_run_time_selector
<typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived> <typename Derived::Scalar,blas_traits<Derived>::IsTransposed,OtherDerived>
::run(extract_data(dst), other)) ::run(extract_data(dst), other))
&& "aliasing detected during tranposition, use transposeInPlace() " && "aliasing detected during transposition, use transposeInPlace() "
"or evaluate the rhs into a temporary using .eval()"); "or evaluate the rhs into a temporary using .eval()");
} }

View File

@ -2,7 +2,7 @@ namespace Eigen {
/** \eigenManualPage TopicAliasing Aliasing /** \eigenManualPage TopicAliasing Aliasing
In Eigen, aliasing refers to assignment statement in which the same matrix (or array or vector) appears on the In %Eigen, aliasing refers to assignment statement in which the same matrix (or array or vector) appears on the
left and on the right of the assignment operators. Statements like <tt>mat = 2 * mat;</tt> or <tt>mat = left and on the right of the assignment operators. Statements like <tt>mat = 2 * mat;</tt> or <tt>mat =
mat.transpose();</tt> exhibit aliasing. The aliasing in the first example is harmless, but the aliasing in the mat.transpose();</tt> exhibit aliasing. The aliasing in the first example is harmless, but the aliasing in the
second example leads to unexpected results. This page explains what aliasing is, when it is harmful, and what second example leads to unexpected results. This page explains what aliasing is, when it is harmful, and what
@ -32,7 +32,7 @@ This assignment exhibits aliasing: the coefficient \c mat(1,1) appears both in t
<tt>mat.bottomRightCorner(2,2)</tt> on the left-hand side of the assignment and the block <tt>mat.bottomRightCorner(2,2)</tt> on the left-hand side of the assignment and the block
<tt>mat.topLeftCorner(2,2)</tt> on the right-hand side. After the assignment, the (2,2) entry in the bottom <tt>mat.topLeftCorner(2,2)</tt> on the right-hand side. After the assignment, the (2,2) entry in the bottom
right corner should have the value of \c mat(1,1) before the assignment, which is 5. However, the output shows right corner should have the value of \c mat(1,1) before the assignment, which is 5. However, the output shows
that \c mat(2,2) is actually 1. The problem is that Eigen uses lazy evaluation (see that \c mat(2,2) is actually 1. The problem is that %Eigen uses lazy evaluation (see
\ref TopicEigenExpressionTemplates) for <tt>mat.topLeftCorner(2,2)</tt>. The result is similar to \ref TopicEigenExpressionTemplates) for <tt>mat.topLeftCorner(2,2)</tt>. The result is similar to
\code \code
mat(1,1) = mat(0,0); mat(1,1) = mat(0,0);
@ -43,10 +43,13 @@ mat(2,2) = mat(1,1);
Thus, \c mat(2,2) is assigned the \e new value of \c mat(1,1) instead of the old value. The next section Thus, \c mat(2,2) is assigned the \e new value of \c mat(1,1) instead of the old value. The next section
explains how to solve this problem by calling \link DenseBase::eval() eval()\endlink. explains how to solve this problem by calling \link DenseBase::eval() eval()\endlink.
Note that if \c mat were a bigger, then the blocks would not overlap, and there would be no aliasing Aliasing occurs more naturally when trying to shrink a matrix. For example, the expressions <tt>vec =
problem. This means that in general aliasing cannot be detected at compile time. However, Eigen does detect vec.head(n)</tt> and <tt>mat = mat.block(i,j,r,c)</tt> exhibit aliasing.
some instances of aliasing, albeit at run time. The following example exhibiting aliasing was mentioned in
\ref TutorialMatrixArithmetic : In general, aliasing cannot be detected at compile time: if \c mat in the first example were a bit bigger,
then the blocks would not overlap, and there would be no aliasing problem. However, %Eigen does detect some
instances of aliasing, albeit at run time. The following example exhibiting aliasing was mentioned in \ref
TutorialMatrixArithmetic :
<table class="example"> <table class="example">
<tr><th>Example</th><th>Output</th></tr> <tr><th>Example</th><th>Output</th></tr>
@ -57,24 +60,24 @@ some instances of aliasing, albeit at run time. The following example exhibitin
\verbinclude tut_arithmetic_transpose_aliasing.out \verbinclude tut_arithmetic_transpose_aliasing.out
</td></tr></table> </td></tr></table>
Again, the output shows the aliasing issue. However, by default Eigen uses a run-time assertion to detect this Again, the output shows the aliasing issue. However, by default %Eigen uses a run-time assertion to detect this
and exits with a message like and exits with a message like
\verbatim \verbatim
void Eigen::DenseBase<Derived>::checkTransposeAliasing(const OtherDerived&) const void Eigen::DenseBase<Derived>::checkTransposeAliasing(const OtherDerived&) const
[with OtherDerived = Eigen::Transpose<Eigen::Matrix<int, 2, 2, 0, 2, 2> >, Derived = Eigen::Matrix<int, 2, 2, 0, 2, 2>]: [with OtherDerived = Eigen::Transpose<Eigen::Matrix<int, 2, 2, 0, 2, 2> >, Derived = Eigen::Matrix<int, 2, 2, 0, 2, 2>]:
Assertion `(!internal::check_transpose_aliasing_selector<Scalar,internal::blas_traits<Derived>::IsTransposed,OtherDerived>::run(internal::extract_data(derived()), other)) Assertion `(!internal::check_transpose_aliasing_selector<Scalar,internal::blas_traits<Derived>::IsTransposed,OtherDerived>::run(internal::extract_data(derived()), other))
&& "aliasing detected during tranposition, use transposeInPlace() or evaluate the rhs into a temporary using .eval()"' failed. && "aliasing detected during transposition, use transposeInPlace() or evaluate the rhs into a temporary using .eval()"' failed.
\endverbatim \endverbatim
The user can turn Eigen's run-time assertions like the one to detect this aliasing problem off by defining the The user can turn %Eigen's run-time assertions like the one to detect this aliasing problem off by defining the
EIGEN_NO_DEBUG macro, and the above program was compiled with this macro turned off in order to illustrate the EIGEN_NO_DEBUG macro, and the above program was compiled with this macro turned off in order to illustrate the
aliasing problem. See \ref TopicAssertions for more information about Eigen's run-time assertions. aliasing problem. See \ref TopicAssertions for more information about %Eigen's run-time assertions.
\section TopicAliasingSolution Resolving aliasing issues \section TopicAliasingSolution Resolving aliasing issues
If you understand the cause of the aliasing issue, then it is obvious what must happen to solve it: Eigen has If you understand the cause of the aliasing issue, then it is obvious what must happen to solve it: %Eigen has
to evaluate the right-hand side fully into a temporary matrix/array and then assign it to the left-hand to evaluate the right-hand side fully into a temporary matrix/array and then assign it to the left-hand
side. The function \link DenseBase::eval() eval() \endlink does precisely that. side. The function \link DenseBase::eval() eval() \endlink does precisely that.
@ -93,7 +96,7 @@ Now, \c mat(2,2) equals 5 after the assignment, as it should be.
The same solution also works for the second example, with the transpose: simply replace the line The same solution also works for the second example, with the transpose: simply replace the line
<tt>a = a.transpose();</tt> with <tt>a = a.transpose().eval();</tt>. However, in this common case there is a <tt>a = a.transpose();</tt> with <tt>a = a.transpose().eval();</tt>. However, in this common case there is a
better solution. Eigen provides the special-purpose function better solution. %Eigen provides the special-purpose function
\link DenseBase::transposeInPlace() transposeInPlace() \endlink which replaces a matrix by its transpose. \link DenseBase::transposeInPlace() transposeInPlace() \endlink which replaces a matrix by its transpose.
This is shown below: This is shown below:
@ -107,7 +110,7 @@ This is shown below:
</td></tr></table> </td></tr></table>
If an xxxInPlace() function is available, then it is best to use it, because it indicates more clearly what you If an xxxInPlace() function is available, then it is best to use it, because it indicates more clearly what you
are doing. This may also allow Eigen to optimize more aggressively. These are some of the xxxInPlace() are doing. This may also allow %Eigen to optimize more aggressively. These are some of the xxxInPlace()
functions provided: functions provided:
<table class="manual"> <table class="manual">
@ -120,6 +123,9 @@ functions provided:
<tr class="alt"> <td> DenseBase::transpose() </td> <td> DenseBase::transposeInPlace() </td> </tr> <tr class="alt"> <td> DenseBase::transpose() </td> <td> DenseBase::transposeInPlace() </td> </tr>
</table> </table>
In the special case where a matrix or vector is shrunk using an expression like <tt>vec = vec.head(n)</tt>,
you can use \link PlainObjectBase::conservativeResize() conservativeResize() \endlink.
\section TopicAliasingCwise Aliasing and component-wise operations \section TopicAliasingCwise Aliasing and component-wise operations
@ -128,8 +134,8 @@ right-hand side of an assignment operator, and it is then often necessary to eva
explicitly. However, applying component-wise operations (such as matrix addition, scalar multiplication and explicitly. However, applying component-wise operations (such as matrix addition, scalar multiplication and
array multiplication) is safe. array multiplication) is safe.
The following example has only component-wise operations. Thus, there is no need for .eval() even though The following example has only component-wise operations. Thus, there is no need for \link DenseBase::eval()
the same matrix appears on both sides of the assignments. eval() \endlink even though the same matrix appears on both sides of the assignments.
<table class="example"> <table class="example">
<tr><th>Example</th><th>Output</th></tr> <tr><th>Example</th><th>Output</th></tr>
@ -147,8 +153,8 @@ not necessary to evaluate the right-hand side explicitly.
\section TopicAliasingMatrixMult Aliasing and matrix multiplication \section TopicAliasingMatrixMult Aliasing and matrix multiplication
Matrix multiplication is the only operation in Eigen that assumes aliasing by default. Thus, if \c matA is a Matrix multiplication is the only operation in %Eigen that assumes aliasing by default. Thus, if \c matA is a
matrix, then the statement <tt>matA = matA * matA;</tt> is safe. All other operations in Eigen assume that matrix, then the statement <tt>matA = matA * matA;</tt> is safe. All other operations in %Eigen assume that
there are no aliasing problems, either because the result is assigned to a different matrix or because it is a there are no aliasing problems, either because the result is assigned to a different matrix or because it is a
component-wise operation. component-wise operation.
@ -161,14 +167,14 @@ component-wise operation.
\verbinclude TopicAliasing_mult1.out \verbinclude TopicAliasing_mult1.out
</td></tr></table> </td></tr></table>
However, this comes at a price. When executing the expression <tt>matA = matA * matA</tt>, Eigen evaluates the However, this comes at a price. When executing the expression <tt>matA = matA * matA</tt>, %Eigen evaluates the
product in a temporary matrix which is assigned to \c matA after the computation. This is fine. But Eigen does product in a temporary matrix which is assigned to \c matA after the computation. This is fine. But %Eigen does
the same when the product is assigned to a different matrix (e.g., <tt>matB = matA * matA</tt>). In that case, the same when the product is assigned to a different matrix (e.g., <tt>matB = matA * matA</tt>). In that case,
it is more efficient to evaluate the product directly into \c matB instead of evaluating it first into a it is more efficient to evaluate the product directly into \c matB instead of evaluating it first into a
temporary matrix and copying that matrix to \c matB. temporary matrix and copying that matrix to \c matB.
The user can indicate with the \link MatrixBase::noalias() noalias()\endlink function that there is no The user can indicate with the \link MatrixBase::noalias() noalias()\endlink function that there is no
aliasing, as follows: <tt>matB.noalias() = matA * matA</tt>. This allows Eigen to evaluate the matrix product aliasing, as follows: <tt>matB.noalias() = matA * matA</tt>. This allows %Eigen to evaluate the matrix product
<tt>matA * matA</tt> directly into \c matB. <tt>matA * matA</tt> directly into \c matB.
<table class="example"> <table class="example">
@ -199,9 +205,9 @@ Aliasing occurs when the same matrix or array coefficients appear both on the le
an assignment operator. an assignment operator.
- Aliasing is harmless with coefficient-wise computations; this includes scalar multiplication and matrix or - Aliasing is harmless with coefficient-wise computations; this includes scalar multiplication and matrix or
array addition. array addition.
- When you multiply two matrices, Eigen assumes that aliasing occurs. If you know that there is no aliasing, - When you multiply two matrices, %Eigen assumes that aliasing occurs. If you know that there is no aliasing,
then you can use \link MatrixBase::noalias() noalias()\endlink. then you can use \link MatrixBase::noalias() noalias()\endlink.
- In all other situations, Eigen assumes that there is no aliasing issue and thus gives the wrong result if - In all other situations, %Eigen assumes that there is no aliasing issue and thus gives the wrong result if
aliasing does in fact occur. To prevent this, you have to use \link DenseBase::eval() eval() \endlink or aliasing does in fact occur. To prevent this, you have to use \link DenseBase::eval() eval() \endlink or
one of the xxxInPlace() functions. one of the xxxInPlace() functions.