mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
bugfix in compute_matrix_flags, optimization in LU,
improve doc, and workaround aliasing detection in MatrixBase_eval snippet (not very nice but I don't know how to do it in a better way)
This commit is contained in:
@@ -31,8 +31,9 @@
|
||||
*
|
||||
* \param ExpressionType the type of the object on which to do the lazy assignment
|
||||
*
|
||||
* This class represents an expression with a special assignment operator (operator=)
|
||||
* This class represents an expression with special assignment operators
|
||||
* assuming no aliasing between the target expression and the source expression.
|
||||
* More precisely it alloas to bypass the EvalBeforeAssignBit flag of the source expression.
|
||||
* It is the return type of MatrixBase::noalias()
|
||||
* and most of the time this is the only way it is used.
|
||||
*
|
||||
@@ -44,44 +45,61 @@ class NoAlias
|
||||
public:
|
||||
NoAlias(ExpressionType& expression) : m_expression(expression) {}
|
||||
|
||||
/** Behaves like MatrixBase::lazyAssign() */
|
||||
/** Behaves like MatrixBase::lazyAssign(other)
|
||||
* \sa MatrixBase::lazyAssign() */
|
||||
template<typename OtherDerived>
|
||||
ExpressionType& operator=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
return m_expression.lazyAssign(other.derived());
|
||||
}
|
||||
{ return m_expression.lazyAssign(other.derived()); }
|
||||
|
||||
// TODO could be removed if we decide that += is noalias by default
|
||||
/** \sa MatrixBase::operator+= */
|
||||
template<typename OtherDerived>
|
||||
ExpressionType& operator+=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
return m_expression.lazyAssign(m_expression + other.derived());
|
||||
}
|
||||
{ return m_expression.lazyAssign(m_expression + other.derived()); }
|
||||
|
||||
// TODO could be removed if we decide that += is noalias by default
|
||||
/** \sa MatrixBase::operator-= */
|
||||
template<typename OtherDerived>
|
||||
ExpressionType& operator-=(const MatrixBase<OtherDerived>& other)
|
||||
{
|
||||
return m_expression.lazyAssign(m_expression - other.derived());
|
||||
}
|
||||
{ return m_expression.lazyAssign(m_expression - other.derived()); }
|
||||
|
||||
// TODO could be removed if we decide that += is noalias by default
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||
ExpressionType& operator+=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
|
||||
{ other.derived().addTo(m_expression); return m_expression; }
|
||||
|
||||
// TODO could be removed if we decide that += is noalias by default
|
||||
template<typename ProductDerived, typename Lhs, typename Rhs>
|
||||
ExpressionType& operator-=(const ProductBase<ProductDerived, Lhs,Rhs>& other)
|
||||
{ other.derived().subTo(m_expression); return m_expression; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
ExpressionType& m_expression;
|
||||
};
|
||||
|
||||
|
||||
/** \returns a pseudo expression of \c *this with an operator= assuming
|
||||
* no aliasing between \c *this and the source expression
|
||||
* no aliasing between \c *this and the source expression.
|
||||
*
|
||||
* More precisely, noalias() allows to bypass the EvalBeforeAssignBit flag.
|
||||
* Currently, even though several expressions may alias, only product
|
||||
* expressions have this flag. Therefore, noalias() is only usefull when
|
||||
* the source expression contains a matrix product.
|
||||
*
|
||||
* Here are some examples where noalias is usefull:
|
||||
* \code
|
||||
* D.noalias() = A * B;
|
||||
* D.noalias() += A.transpose() * B;
|
||||
* D.noalias() -= 2 * A * B.adjoint();
|
||||
* \endcode
|
||||
*
|
||||
* On the other hand the following example will lead to a \b wrong result:
|
||||
* \code
|
||||
* A.noalias() = A * B;
|
||||
* \endcode
|
||||
* because the result matrix A is also an operand of the matrix product. Therefore,
|
||||
* there is no alternative than evaluating A * B in a temporary, that is the default
|
||||
* behavior when you write:
|
||||
* \code
|
||||
* A = A * B;
|
||||
* \endcode
|
||||
*
|
||||
* \sa class NoAlias
|
||||
*/
|
||||
|
||||
@@ -119,10 +119,8 @@ class ProductBase : public MatrixBase<Derived>
|
||||
return res;
|
||||
}
|
||||
|
||||
const Flagged<ProductBase, 0, EvalBeforeAssigningBit> lazy() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
EIGEN_DEPRECATED const Flagged<ProductBase, 0, EvalBeforeAssigningBit> lazy() const
|
||||
{ return *this; }
|
||||
|
||||
const _LhsNested& lhs() const { return m_lhs; }
|
||||
const _RhsNested& rhs() const { return m_rhs; }
|
||||
|
||||
@@ -90,7 +90,7 @@ class ei_compute_matrix_flags
|
||||
: MaxRows==1 ? MaxCols
|
||||
: row_major_bit ? MaxCols : MaxRows,
|
||||
is_big = inner_max_size == Dynamic,
|
||||
is_packet_size_multiple = Rows==Dynamic || Cols==Dynamic || ((Cols*Rows) % ei_packet_traits<Scalar>::size) == 0,
|
||||
is_packet_size_multiple = MaxRows==Dynamic || MaxCols==Dynamic || ((MaxCols*MaxRows) % ei_packet_traits<Scalar>::size) == 0,
|
||||
aligned_bit = (((Options&DontAlign)==0) && (is_big || is_packet_size_multiple)) ? AlignedBit : 0,
|
||||
packet_access_bit = ei_packet_traits<Scalar>::size > 1 && aligned_bit ? PacketAccessBit : 0
|
||||
};
|
||||
|
||||
@@ -437,7 +437,7 @@ LU<MatrixType>& LU<MatrixType>::compute(const MatrixType& matrix)
|
||||
if(k<rows-1)
|
||||
m_lu.col(k).end(rows-k-1) /= m_lu.coeff(k,k);
|
||||
if(k<size-1)
|
||||
m_lu.block(k+1,k+1,rows-k-1,cols-k-1) -= m_lu.col(k).end(rows-k-1) * m_lu.row(k).end(cols-k-1);
|
||||
m_lu.block(k+1,k+1,rows-k-1,cols-k-1).noalias() -= m_lu.col(k).end(rows-k-1) * m_lu.row(k).end(cols-k-1);
|
||||
}
|
||||
|
||||
for(int k = 0; k < matrix.rows(); ++k) m_p.coeffRef(k) = k;
|
||||
|
||||
@@ -248,7 +248,7 @@ struct ei_partial_lu_impl
|
||||
int rrows = rows-k-1;
|
||||
int rsize = size-k-1;
|
||||
lu.col(k).end(rrows) /= lu.coeff(k,k);
|
||||
lu.corner(BottomRight,rrows,rsize) -= (lu.col(k).end(rrows) * lu.row(k).end(rsize)).lazy();
|
||||
lu.corner(BottomRight,rrows,rsize).noalias() -= lu.col(k).end(rrows) * lu.row(k).end(rsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user