diff options
-rw-r--r-- | Eigen/Core | 1 | ||||
-rw-r--r-- | Eigen/src/Core/Assign.h | 2 | ||||
-rw-r--r-- | Eigen/src/Core/Flagged.h | 15 | ||||
-rw-r--r-- | Eigen/src/Core/MapBase.h | 4 | ||||
-rw-r--r-- | Eigen/src/Core/Matrix.h | 2 | ||||
-rw-r--r-- | Eigen/src/Core/MatrixBase.h | 13 | ||||
-rw-r--r-- | Eigen/src/Core/NoAlias.h | 94 | ||||
-rw-r--r-- | Eigen/src/Core/ProductBase.h | 8 | ||||
-rw-r--r-- | Eigen/src/Core/TriangularMatrix.h | 6 | ||||
-rw-r--r-- | Eigen/src/Core/products/GeneralUnrolled.h | 2 | ||||
-rw-r--r-- | Eigen/src/Core/util/Constants.h | 8 | ||||
-rw-r--r-- | Eigen/src/Core/util/ForwardDeclarations.h | 1 | ||||
-rw-r--r-- | test/product_notemporary.cpp | 8 | ||||
-rw-r--r-- | test/submatrices.cpp | 3 |
14 files changed, 138 insertions, 29 deletions
diff --git a/Eigen/Core b/Eigen/Core index 28ed09035..ff56c6ca2 100644 --- a/Eigen/Core +++ b/Eigen/Core @@ -154,6 +154,7 @@ namespace Eigen { #include "src/Core/NestByValue.h" #include "src/Core/ReturnByValue.h" #include "src/Core/Flagged.h" +#include "src/Core/NoAlias.h" #include "src/Core/Matrix.h" #include "src/Core/Cwise.h" #include "src/Core/CwiseBinaryOp.h" diff --git a/Eigen/src/Core/Assign.h b/Eigen/src/Core/Assign.h index 4bd1046a7..b0e69224e 100644 --- a/Eigen/src/Core/Assign.h +++ b/Eigen/src/Core/Assign.h @@ -434,7 +434,7 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived> } template<typename Derived, typename OtherDerived, - bool EvalBeforeAssigning = (int(OtherDerived::Flags) & EvalBeforeAssigningBit) != 0, + bool EvalBeforeAssigning = (int(OtherDerived::Flags) & MayAliasBit) != 0, bool NeedToTranspose = Derived::IsVectorAtCompileTime && OtherDerived::IsVectorAtCompileTime && ((int(Derived::RowsAtCompileTime) == 1 && int(OtherDerived::ColsAtCompileTime) == 1) diff --git a/Eigen/src/Core/Flagged.h b/Eigen/src/Core/Flagged.h index d5135e0be..7cd042918 100644 --- a/Eigen/src/Core/Flagged.h +++ b/Eigen/src/Core/Flagged.h @@ -25,7 +25,9 @@ #ifndef EIGEN_FLAGGED_H #define EIGEN_FLAGGED_H -/** \class Flagged +/** \deprecated it is only used by lazy() which is deprecated + * + * \class Flagged * * \brief Expression with modified flags * @@ -111,9 +113,9 @@ template<typename ExpressionType, unsigned int Added, unsigned int Removed> clas ExpressionTypeNested m_matrix; }; -/** \returns an expression of *this with added flags +/** \deprecated it is only used by lazy() which is deprecated * - * \addexample MarkExample \label How to mark a triangular matrix as triangular + * \returns an expression of *this with added flags * * Example: \include MatrixBase_marked.cpp * Output: \verbinclude MatrixBase_marked.out @@ -128,8 +130,9 @@ MatrixBase<Derived>::marked() const return derived(); } -/** \returns an expression of *this with the following flags removed: - * EvalBeforeNestingBit and EvalBeforeAssigningBit. +/** \deprecated use MatrixBase::noalias() + * + * \returns an expression of *this with the MayAliasBit flag removed. * * Example: \include MatrixBase_lazy.cpp * Output: \verbinclude MatrixBase_lazy.out @@ -137,7 +140,7 @@ MatrixBase<Derived>::marked() const * \sa class Flagged, marked() */ template<typename Derived> -inline const Flagged<Derived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit> +inline const Flagged<Derived, 0, MayAliasBit> MatrixBase<Derived>::lazy() const { return derived(); diff --git a/Eigen/src/Core/MapBase.h b/Eigen/src/Core/MapBase.h index 51e041db6..b9e9374be 100644 --- a/Eigen/src/Core/MapBase.h +++ b/Eigen/src/Core/MapBase.h @@ -179,11 +179,11 @@ template<typename Derived> class MapBase // explicitly add these two overloads. // Maybe there exists a better solution though. template<typename ProductDerived, typename Lhs,typename Rhs> - Derived& operator+=(const Flagged<ProductBase<ProductDerived,Lhs,Rhs>, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other) + Derived& operator+=(const Flagged<ProductBase<ProductDerived,Lhs,Rhs>, 0, MayAliasBit>& other) { return Base::operator+=(other); } template<typename ProductDerived, typename Lhs,typename Rhs> - Derived& operator-=(const Flagged<ProductBase<ProductDerived,Lhs,Rhs>, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other) + Derived& operator-=(const Flagged<ProductBase<ProductDerived,Lhs,Rhs>, 0, MayAliasBit>& other) { return Base::operator-=(other); } template<typename OtherDerived> diff --git a/Eigen/src/Core/Matrix.h b/Eigen/src/Core/Matrix.h index f58424ba2..d129535b6 100644 --- a/Eigen/src/Core/Matrix.h +++ b/Eigen/src/Core/Matrix.h @@ -577,7 +577,7 @@ class Matrix template<typename OtherDerived> EIGEN_STRONG_INLINE Matrix& _set(const MatrixBase<OtherDerived>& other) { - _set_selector(other.derived(), typename ei_meta_if<static_cast<bool>(int(OtherDerived::Flags) & EvalBeforeAssigningBit), ei_meta_true, ei_meta_false>::ret()); + _set_selector(other.derived(), typename ei_meta_if<static_cast<bool>(int(OtherDerived::Flags) & MayAliasBit), ei_meta_true, ei_meta_false>::ret()); return *this; } diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index 52d5f680c..a554de8e3 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -326,9 +326,10 @@ template<typename Derived> class MatrixBase template<typename OtherDerived> Derived& lazyAssign(const MatrixBase<OtherDerived>& other); - /** Overloaded for cache friendly product evaluation */ + /** \deprecated because .lazy() is deprecated + * Overloaded for cache friendly product evaluation */ template<typename OtherDerived> - Derived& lazyAssign(const Flagged<OtherDerived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other) + Derived& lazyAssign(const Flagged<OtherDerived, 0, MayAliasBit>& other) { return lazyAssign(other._expression()); } template<typename ProductDerived, typename Lhs, typename Rhs> @@ -336,11 +337,11 @@ template<typename Derived> class MatrixBase template<typename ProductDerived, typename Lhs, typename Rhs> Derived& operator+=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0, - EvalBeforeNestingBit | EvalBeforeAssigningBit>& other); + MayAliasBit>& other); template<typename ProductDerived, typename Lhs, typename Rhs> Derived& operator-=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0, - EvalBeforeNestingBit | EvalBeforeAssigningBit>& other); + MayAliasBit>& other); #endif // not EIGEN_PARSED_BY_DOXYGEN CommaInitializer<Derived> operator<< (const Scalar& s); @@ -614,7 +615,9 @@ template<typename Derived> class MatrixBase template<unsigned int Added> const Flagged<Derived, Added, 0> marked() const; - const Flagged<Derived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit> lazy() const; + const Flagged<Derived, 0, MayAliasBit> lazy() const; + + NoAlias<Derived> noalias(); /** \returns number of elements to skip to pass from one row (resp. column) to another * for a row-major (resp. column-major) matrix. diff --git a/Eigen/src/Core/NoAlias.h b/Eigen/src/Core/NoAlias.h new file mode 100644 index 000000000..5c2b6e3ca --- /dev/null +++ b/Eigen/src/Core/NoAlias.h @@ -0,0 +1,94 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2009 Gael Guennebaud <g.gael@free.fr> +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see <http://www.gnu.org/licenses/>. + +#ifndef EIGEN_NOALIAS_H +#define EIGEN_NOALIAS_H + +/** \class NoAlias + * + * \brief Pseudo expression providing an operator = assuming no aliasing + * + * \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=) + * assuming no aliasing between the target expression and the source expression. + * It is the return type of MatrixBase::noalias() + * and most of the time this is the only way it is used. + * + * \sa MatrixBase::noalias() + */ +template<typename ExpressionType> +class NoAlias +{ + public: + NoAlias(ExpressionType& expression) : m_expression(expression) {} + + /** Behaves like MatrixBase::lazyAssign() */ + template<typename OtherDerived> + ExpressionType& operator=(const MatrixBase<OtherDerived>& other) + { + return m_expression.lazyAssign(other.derived()); + } + + // TODO could be removed if we decide that += is noalias by default + template<typename OtherDerived> + ExpressionType& operator+=(const MatrixBase<OtherDerived>& other) + { + return m_expression.lazyAssign(m_expression + other.derived()); + } + + // TODO could be removed if we decide that += is noalias by default + template<typename OtherDerived> + ExpressionType& operator-=(const MatrixBase<OtherDerived>& other) + { + return m_expression.lazyAssign(m_expression - other.derived()); + } + + // 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().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; } + + protected: + ExpressionType& m_expression; +}; + + +/** \returns a pseudo expression of \c *this with an operator= assuming + * no aliasing between \c *this and the source expression + * + * \sa class NoAlias + */ +template<typename Derived> +NoAlias<Derived> MatrixBase<Derived>::noalias() +{ + return derived(); +} + +#endif // EIGEN_NOALIAS_H diff --git a/Eigen/src/Core/ProductBase.h b/Eigen/src/Core/ProductBase.h index b5ed5ae8f..867aa7a15 100644 --- a/Eigen/src/Core/ProductBase.h +++ b/Eigen/src/Core/ProductBase.h @@ -39,7 +39,7 @@ struct ei_traits<ProductBase<Derived,_Lhs,_Rhs> > ColsAtCompileTime = ei_traits<Rhs>::ColsAtCompileTime, MaxRowsAtCompileTime = ei_traits<Lhs>::MaxRowsAtCompileTime, MaxColsAtCompileTime = ei_traits<Rhs>::MaxColsAtCompileTime, - Flags = EvalBeforeNestingBit | EvalBeforeAssigningBit, + Flags = EvalBeforeNestingBit | MayAliasBit, CoeffReadCost = 0 // FIXME why is it needed ? }; }; @@ -119,7 +119,7 @@ class ProductBase : public MatrixBase<Derived> return res; } - const Flagged<ProductBase, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit> lazy() const + const Flagged<ProductBase, 0, MayAliasBit> lazy() const { return *this; } @@ -228,7 +228,7 @@ Derived& MatrixBase<Derived>::lazyAssign(const ProductBase<ProductDerived, Lhs,R template<typename Derived> template<typename ProductDerived, typename Lhs, typename Rhs> Derived& MatrixBase<Derived>::operator+=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0, - EvalBeforeNestingBit | EvalBeforeAssigningBit>& other) + MayAliasBit>& other) { other._expression().derived().addTo(derived()); return derived(); } @@ -238,7 +238,7 @@ Derived& MatrixBase<Derived>::operator+=(const Flagged<ProductBase<ProductDerive template<typename Derived> template<typename ProductDerived, typename Lhs, typename Rhs> Derived& MatrixBase<Derived>::operator-=(const Flagged<ProductBase<ProductDerived, Lhs,Rhs>, 0, - EvalBeforeNestingBit | EvalBeforeAssigningBit>& other) + MayAliasBit>& other) { other._expression().derived().subTo(derived()); return derived(); } diff --git a/Eigen/src/Core/TriangularMatrix.h b/Eigen/src/Core/TriangularMatrix.h index b0362f20c..cfaf89733 100644 --- a/Eigen/src/Core/TriangularMatrix.h +++ b/Eigen/src/Core/TriangularMatrix.h @@ -477,7 +477,7 @@ template<typename OtherDerived> inline TriangularView<MatrixType, Mode>& TriangularView<MatrixType, Mode>::operator=(const MatrixBase<OtherDerived>& other) { - if(OtherDerived::Flags & EvalBeforeAssigningBit) + if(OtherDerived::Flags & MayAliasBit) { typename OtherDerived::PlainMatrixType other_evaluated(other.rows(), other.cols()); other_evaluated.template triangularView<Mode>().lazyAssign(other.derived()); @@ -512,7 +512,7 @@ inline TriangularView<MatrixType, Mode>& TriangularView<MatrixType, Mode>::operator=(const TriangularBase<OtherDerived>& other) { ei_assert(Mode == OtherDerived::Mode); - if(ei_traits<OtherDerived>::Flags & EvalBeforeAssigningBit) + if(ei_traits<OtherDerived>::Flags & MayAliasBit) { typename OtherDerived::PlainMatrixType other_evaluated(other.rows(), other.cols()); other_evaluated.template triangularView<Mode>().lazyAssign(other.derived()); @@ -548,7 +548,7 @@ template<typename Derived> template<typename DenseDerived> void TriangularBase<Derived>::evalToDense(MatrixBase<DenseDerived> &other) const { - if(ei_traits<Derived>::Flags & EvalBeforeAssigningBit) + if(ei_traits<Derived>::Flags & MayAliasBit) { typename Derived::PlainMatrixType other_evaluated(rows(), cols()); evalToDenseLazy(other_evaluated); diff --git a/Eigen/src/Core/products/GeneralUnrolled.h b/Eigen/src/Core/products/GeneralUnrolled.h index 7241976a8..2961d9452 100644 --- a/Eigen/src/Core/products/GeneralUnrolled.h +++ b/Eigen/src/Core/products/GeneralUnrolled.h @@ -76,7 +76,7 @@ struct ei_traits<GeneralProduct<LhsNested,RhsNested,UnrolledProduct> > RemovedBits = ~(EvalToRowMajor ? 0 : RowMajorBit), Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & RemovedBits) - | EvalBeforeAssigningBit + | MayAliasBit | EvalBeforeNestingBit | (CanVectorizeLhs || CanVectorizeRhs ? PacketAccessBit : 0) | (LhsFlags & RhsFlags & AlignedBit), diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h index 21e7f62c3..1d55217f5 100644 --- a/Eigen/src/Core/util/Constants.h +++ b/Eigen/src/Core/util/Constants.h @@ -76,8 +76,10 @@ const unsigned int EvalBeforeNestingBit = 0x2; /** \ingroup flags * - * means the expression should be evaluated before any assignement */ -const unsigned int EvalBeforeAssigningBit = 0x4; + * Means the expression cannot be evaluated safely if the result alias one + * of the operands of the expression. Therefore it should be evaluated + * before any assignement. */ +const unsigned int MayAliasBit = 0x4; /** \ingroup flags * @@ -182,7 +184,7 @@ const unsigned int SparseBit = 0x1000; // list of flags that are inherited by default const unsigned int HereditaryBits = RowMajorBit | EvalBeforeNestingBit - | EvalBeforeAssigningBit + | MayAliasBit | SparseBit; // Possible values for the Mode parameter of part() diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index c9ce174d2..6f3e6a788 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -35,6 +35,7 @@ template<typename _Scalar, int _Rows, int _Cols, int _MaxRows = _Rows, int _MaxCols = _Cols> class Matrix; template<typename ExpressionType, unsigned int Added, unsigned int Removed> class Flagged; +template<typename ExpressionType> class NoAlias; template<typename ExpressionType> class NestByValue; template<typename ExpressionType> class SwapWrapper; template<typename MatrixType> class Minor; diff --git a/test/product_notemporary.cpp b/test/product_notemporary.cpp index d5d996e49..f6e8f4101 100644 --- a/test/product_notemporary.cpp +++ b/test/product_notemporary.cpp @@ -71,15 +71,19 @@ template<typename MatrixType> void product_notemporary(const MatrixType& m) VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()), 1); VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()).lazy(), 0); + VERIFY_EVALUATION_COUNT( m3.noalias() = m1 * m2.adjoint(), 0); + // NOTE in this case the slow product is used: // FIXME: -// VERIFY_EVALUATION_COUNT( m3 = s1 * (m1 * m2.transpose()).lazy(), 0); + VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * (m1 * m2.transpose()), 0); VERIFY_EVALUATION_COUNT( m3 = (s1 * m1 * s2 * m2.adjoint()).lazy(), 0); VERIFY_EVALUATION_COUNT( m3 = (s1 * m1 * s2 * (m1*s3+m2*s2).adjoint()).lazy(), 1); VERIFY_EVALUATION_COUNT( m3 = ((s1 * m1).adjoint() * s2 * m2).lazy(), 0); - VERIFY_EVALUATION_COUNT( m3 -= (s1 * (-m1*s3).adjoint() * (s2 * m2 * s3)).lazy(), 0); + VERIFY_EVALUATION_COUNT( m3 += (s1 * (-m1*s3).adjoint() * (s2 * m2 * s3)).lazy(), 0); + VERIFY_EVALUATION_COUNT( m3.noalias() += s1 * (-m1*s3).adjoint() * (s2 * m2 * s3), 0); VERIFY_EVALUATION_COUNT( m3 -= (s1 * (m1.transpose() * m2)).lazy(), 0); + VERIFY_EVALUATION_COUNT( m3.noalias() -= s1 * (m1.transpose() * m2), 0); VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1) += (-m1.block(r0,c0,r1,c1) * (s2*m2.block(r0,c0,r1,c1)).adjoint()).lazy() ), 0); VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1) -= (s1 * m1.block(r0,c0,r1,c1) * m2.block(c0,r0,c1,r1)).lazy() ), 0); diff --git a/test/submatrices.cpp b/test/submatrices.cpp index fc7fd09ea..a819cadc2 100644 --- a/test/submatrices.cpp +++ b/test/submatrices.cpp @@ -86,7 +86,8 @@ template<typename MatrixType> void submatrices(const MatrixType& m) //check row() and col() VERIFY_IS_APPROX(m1.col(c1).transpose(), m1.transpose().row(c1)); - VERIFY_IS_APPROX(m1.col(c1).dot(square.row(r1)), (square.lazy() * m1.conjugate()).eval()(r1,c1)); + // FIXME perhaps we should re-enable that without the .eval() + VERIFY_IS_APPROX(m1.col(c1).dot(square.row(r1)), (square * m1.conjugate()).eval()(r1,c1)); //check operator(), both constant and non-constant, on row() and col() m1.row(r1) += s1 * m1.row(r2); m1.col(c1) += s1 * m1.col(c2); |