diff --git a/Eigen/src/Array/Functors.h b/Eigen/src/Array/Functors.h index fd259f7bc..120c56cc1 100644 --- a/Eigen/src/Array/Functors.h +++ b/Eigen/src/Array/Functors.h @@ -87,7 +87,7 @@ struct ei_functor_traits > { enum { Cost = 5 * NumTraits::MulCost, - PacketAccess = ei_packet_traits::HasCos && EIGEN_FAST_MATH + PacketAccess = ei_packet_traits::HasCos }; }; @@ -109,7 +109,7 @@ struct ei_functor_traits > { enum { Cost = 5 * NumTraits::MulCost, - PacketAccess = ei_packet_traits::HasSin && EIGEN_FAST_MATH + PacketAccess = ei_packet_traits::HasSin }; }; diff --git a/Eigen/src/Core/Assign.h b/Eigen/src/Core/Assign.h index 00febdc5d..d544a6198 100644 --- a/Eigen/src/Core/Assign.h +++ b/Eigen/src/Core/Assign.h @@ -484,6 +484,9 @@ EIGEN_STRONG_INLINE Derived& MatrixBase ei_assign_impl::run(derived(),other.derived()); #ifdef EIGEN_DEBUG_ASSIGN ei_assign_traits::debug(); +#endif +#ifndef EIGEN_NO_DEBUG + checkTransposeAliasing(other.derived()); #endif return derived(); } diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index 03d8d5f55..593108522 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -436,21 +436,12 @@ template class MatrixBase void transposeInPlace(); const AdjointReturnType adjoint() const; void adjointInPlace(); - #ifndef EIGEN_NO_DEBUG +#ifndef EIGEN_NO_DEBUG + protected: template - Derived& lazyAssign(const Transpose& other); - template - Derived& lazyAssign(const CwiseBinaryOp,Transpose,DerivedB>& other); - template - Derived& lazyAssign(const CwiseBinaryOp,DerivedA,Transpose >& other); - - template - Derived& lazyAssign(const CwiseUnaryOp, Eigen::Transpose >& other); - template - Derived& lazyAssign(const CwiseBinaryOp,CwiseUnaryOp, Eigen::Transpose >,DerivedB>& other); - template - Derived& lazyAssign(const CwiseBinaryOp,DerivedA,CwiseUnaryOp, Eigen::Transpose > >& other); - #endif + void checkTransposeAliasing(const OtherDerived& other) const; + public: +#endif RowXpr row(int i); const RowXpr row(int i) const; @@ -638,7 +629,7 @@ template class MatrixBase const CwiseBinaryOp binaryExpr(const MatrixBase &other, const CustomBinaryOp& func = CustomBinaryOp()) const; - + Scalar sum() const; Scalar mean() const; Scalar trace() const; @@ -818,7 +809,7 @@ template class MatrixBase INVALID_MATRIXBASE_TEMPLATE_PARAMETERS) #endif } - + private: explicit MatrixBase(int); MatrixBase(int,int); diff --git a/Eigen/src/Core/Transpose.h b/Eigen/src/Core/Transpose.h index 79aef9fa7..796ec8573 100644 --- a/Eigen/src/Core/Transpose.h +++ b/Eigen/src/Core/Transpose.h @@ -268,13 +268,7 @@ inline void MatrixBase::adjointInPlace() #ifndef EIGEN_NO_DEBUG -// The following is to detect aliasing problems in the following common cases: -// a = a.transpose() -// a = a.transpose() + X -// a = X + a.transpose() -// a = a.adjoint() -// a = a.adjoint() + X -// a = X + a.adjoint() +// The following is to detect aliasing problems in most common cases. template::ActualAccess> struct ei_extract_data_selector { @@ -294,63 +288,31 @@ template typename T::Scalar* ei_extract_data(const T& m) return ei_extract_data_selector::run(m); } +template +struct ei_check_transpose_aliasing_selector +{ + static bool run(const Scalar* dest, const OtherDerived& src) + { + return (ei_blas_traits::IsTransposed != DestIsTranposed) && (dest==ei_extract_data(src)); + } +}; + +template +struct ei_check_transpose_aliasing_selector > +{ + static bool run(const Scalar* dest, const CwiseBinaryOp& src) + { + return ((ei_blas_traits::IsTransposed != DestIsTranposed) && dest==ei_extract_data(src.lhs())) + || ((ei_blas_traits::IsTransposed != DestIsTranposed) && dest==ei_extract_data(src.rhs())); + } +}; + template template -Derived& MatrixBase::lazyAssign(const Transpose& other) +void MatrixBase::checkTransposeAliasing(const OtherDerived& other) const { - ei_assert(ei_extract_data(other) != ei_extract_data(derived()) - && "aliasing detected during tranposition, please use transposeInPlace()"); - return lazyAssign(static_cast >& >(other)); -} - -template -template -Derived& MatrixBase:: -lazyAssign(const CwiseBinaryOp,Transpose,DerivedB>& other) -{ - ei_assert(ei_extract_data(derived()) != ei_extract_data(other.lhs()) - && "aliasing detected during tranposition, please evaluate your expression"); - return lazyAssign(static_cast,Transpose,DerivedB> >& >(other)); -} - -template -template -Derived& MatrixBase:: -lazyAssign(const CwiseBinaryOp,DerivedA,Transpose >& other) -{ - ei_assert(ei_extract_data(derived()) != ei_extract_data(other.rhs()) - && "aliasing detected during tranposition, please evaluate your expression"); - return lazyAssign(static_cast,DerivedA,Transpose > >& >(other)); -} - -template -template Derived& -MatrixBase:: -lazyAssign(const CwiseUnaryOp, Eigen::Transpose >& other) -{ - ei_assert(ei_extract_data(other) != ei_extract_data(derived()) - && "aliasing detected during tranposition, please use adjointInPlace()"); - return lazyAssign(static_cast, Eigen::Transpose > >& >(other)); -} - -template -template -Derived& MatrixBase:: -lazyAssign(const CwiseBinaryOp,CwiseUnaryOp, Eigen::Transpose >,DerivedB>& other) -{ - ei_assert(ei_extract_data(derived()) != ei_extract_data(other.lhs()) - && "aliasing detected during tranposition, please evaluate your expression"); - return lazyAssign(static_cast,CwiseUnaryOp, Eigen::Transpose >,DerivedB> >& >(other)); -} - -template -template -Derived& MatrixBase:: -lazyAssign(const CwiseBinaryOp,DerivedA,CwiseUnaryOp, Eigen::Transpose > >& other) -{ - ei_assert(ei_extract_data(derived()) != ei_extract_data(other.rhs()) - && "aliasing detected during tranposition, please evaluate your expression"); - return lazyAssign(static_cast,DerivedA,CwiseUnaryOp, Eigen::Transpose > > >& >(other)); + ei_assert((!ei_check_transpose_aliasing_selector::IsTransposed,OtherDerived>::run(ei_extract_data(derived()), other)) + && "aliasing detected during tranposition, use transposeInPlace() or evaluate the rhs into a temporary using .eval()"); } #endif diff --git a/Eigen/src/Core/arch/SSE/PacketMath.h b/Eigen/src/Core/arch/SSE/PacketMath.h index 69f6979bd..dbdddb38d 100644 --- a/Eigen/src/Core/arch/SSE/PacketMath.h +++ b/Eigen/src/Core/arch/SSE/PacketMath.h @@ -58,8 +58,8 @@ template<> struct ei_packet_traits : ei_default_packet_traits { typedef Packet4f type; enum {size=4}; enum { - HasSin = 1, - HasCos = 1, + HasSin = EIGEN_FAST_MATH, + HasCos = EIGEN_FAST_MATH, HasLog = 1, HasExp = 1, HasSqrt = 1 diff --git a/Eigen/src/Core/util/BlasUtil.h b/Eigen/src/Core/util/BlasUtil.h index a012a6e12..fa21ceebb 100644 --- a/Eigen/src/Core/util/BlasUtil.h +++ b/Eigen/src/Core/util/BlasUtil.h @@ -160,6 +160,7 @@ template struct ei_blas_traits typedef XprType _ExtractType; enum { IsComplex = NumTraits::IsComplex, + IsTransposed = false, NeedToConjugate = false, ActualAccess = int(ei_traits::Flags)&DirectAccessBit ? HasDirectAccess : NoDirectAccess }; @@ -227,6 +228,9 @@ struct ei_blas_traits > ExtractType, typename ExtractType::PlainMatrixType >::ret DirectLinearAccessType; + enum { + IsTransposed = Base::IsTransposed ? 0 : 1 + }; static inline const ExtractType extract(const XprType& x) { return Base::extract(x._expression()); } static inline Scalar extractScalarFactor(const XprType& x) { return Base::extractScalarFactor(x._expression()); } }; diff --git a/test/adjoint.cpp b/test/adjoint.cpp index 344399257..b34112249 100644 --- a/test/adjoint.cpp +++ b/test/adjoint.cpp @@ -128,6 +128,14 @@ void test_adjoint() VERIFY_RAISES_ASSERT(a = a.adjoint()); VERIFY_RAISES_ASSERT(a = a.adjoint() + b); VERIFY_RAISES_ASSERT(a = b + a.adjoint()); + + // no assertion should be triggered for these cases: + a.transpose() = a.transpose(); + a.transpose() += a.transpose(); + a.transpose() += a.transpose() + b; + a.transpose() = a.adjoint(); + a.transpose() += a.adjoint(); + a.transpose() += a.adjoint() + b; } #endif }