mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-04-24 02:29:33 +08:00
doc: Mention vec=vec.head(n) in aliasing page.
This commit is contained in:
parent
1caeb814f0
commit
419b5cff44
@ -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()");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user