mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-04-19 16:19:37 +08:00
* fix aliasing checks when the lhs is also transposed. At the same time,
significantly simplify the code of these checks while extending them to catch much more expressions! * move the enabling/disabling of vectorized sin/cos to the architecture traits
This commit is contained in:
parent
0d8ffe5240
commit
6db6774c46
@ -87,7 +87,7 @@ struct ei_functor_traits<ei_scalar_cos_op<Scalar> >
|
||||
{
|
||||
enum {
|
||||
Cost = 5 * NumTraits<Scalar>::MulCost,
|
||||
PacketAccess = ei_packet_traits<Scalar>::HasCos && EIGEN_FAST_MATH
|
||||
PacketAccess = ei_packet_traits<Scalar>::HasCos
|
||||
};
|
||||
};
|
||||
|
||||
@ -109,7 +109,7 @@ struct ei_functor_traits<ei_scalar_sin_op<Scalar> >
|
||||
{
|
||||
enum {
|
||||
Cost = 5 * NumTraits<Scalar>::MulCost,
|
||||
PacketAccess = ei_packet_traits<Scalar>::HasSin && EIGEN_FAST_MATH
|
||||
PacketAccess = ei_packet_traits<Scalar>::HasSin
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -484,6 +484,9 @@ EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>
|
||||
ei_assign_impl<Derived, OtherDerived>::run(derived(),other.derived());
|
||||
#ifdef EIGEN_DEBUG_ASSIGN
|
||||
ei_assign_traits<Derived, OtherDerived>::debug();
|
||||
#endif
|
||||
#ifndef EIGEN_NO_DEBUG
|
||||
checkTransposeAliasing(other.derived());
|
||||
#endif
|
||||
return derived();
|
||||
}
|
||||
|
@ -436,21 +436,12 @@ template<typename Derived> class MatrixBase
|
||||
void transposeInPlace();
|
||||
const AdjointReturnType adjoint() const;
|
||||
void adjointInPlace();
|
||||
#ifndef EIGEN_NO_DEBUG
|
||||
#ifndef EIGEN_NO_DEBUG
|
||||
protected:
|
||||
template<typename OtherDerived>
|
||||
Derived& lazyAssign(const Transpose<OtherDerived>& other);
|
||||
template<typename DerivedA, typename DerivedB>
|
||||
Derived& lazyAssign(const CwiseBinaryOp<ei_scalar_sum_op<Scalar>,Transpose<DerivedA>,DerivedB>& other);
|
||||
template<typename DerivedA, typename DerivedB>
|
||||
Derived& lazyAssign(const CwiseBinaryOp<ei_scalar_sum_op<Scalar>,DerivedA,Transpose<DerivedB> >& other);
|
||||
|
||||
template<typename OtherDerived>
|
||||
Derived& lazyAssign(const CwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, Eigen::Transpose<OtherDerived> >& other);
|
||||
template<typename DerivedA, typename DerivedB>
|
||||
Derived& lazyAssign(const CwiseBinaryOp<ei_scalar_sum_op<Scalar>,CwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, Eigen::Transpose<DerivedA> >,DerivedB>& other);
|
||||
template<typename DerivedA, typename DerivedB>
|
||||
Derived& lazyAssign(const CwiseBinaryOp<ei_scalar_sum_op<Scalar>,DerivedA,CwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, Eigen::Transpose<DerivedB> > >& 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<typename Derived> class MatrixBase
|
||||
const CwiseBinaryOp<CustomBinaryOp, Derived, OtherDerived>
|
||||
binaryExpr(const MatrixBase<OtherDerived> &other, const CustomBinaryOp& func = CustomBinaryOp()) const;
|
||||
|
||||
|
||||
|
||||
Scalar sum() const;
|
||||
Scalar mean() const;
|
||||
Scalar trace() const;
|
||||
@ -818,7 +809,7 @@ template<typename Derived> class MatrixBase
|
||||
INVALID_MATRIXBASE_TEMPLATE_PARAMETERS)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
explicit MatrixBase(int);
|
||||
MatrixBase(int,int);
|
||||
|
@ -268,13 +268,7 @@ inline void MatrixBase<Derived>::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<typename T, int Access=ei_blas_traits<T>::ActualAccess>
|
||||
struct ei_extract_data_selector {
|
||||
@ -294,63 +288,31 @@ template<typename T> typename T::Scalar* ei_extract_data(const T& m)
|
||||
return ei_extract_data_selector<T>::run(m);
|
||||
}
|
||||
|
||||
template<typename Scalar, bool DestIsTranposed, typename OtherDerived>
|
||||
struct ei_check_transpose_aliasing_selector
|
||||
{
|
||||
static bool run(const Scalar* dest, const OtherDerived& src)
|
||||
{
|
||||
return (ei_blas_traits<OtherDerived>::IsTransposed != DestIsTranposed) && (dest==ei_extract_data(src));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Scalar, bool DestIsTranposed, typename BinOp, typename DerivedA, typename DerivedB>
|
||||
struct ei_check_transpose_aliasing_selector<Scalar,DestIsTranposed,CwiseBinaryOp<BinOp,DerivedA,DerivedB> >
|
||||
{
|
||||
static bool run(const Scalar* dest, const CwiseBinaryOp<BinOp,DerivedA,DerivedB>& src)
|
||||
{
|
||||
return ((ei_blas_traits<DerivedA>::IsTransposed != DestIsTranposed) && dest==ei_extract_data(src.lhs()))
|
||||
|| ((ei_blas_traits<DerivedB>::IsTransposed != DestIsTranposed) && dest==ei_extract_data(src.rhs()));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
Derived& MatrixBase<Derived>::lazyAssign(const Transpose<OtherDerived>& other)
|
||||
void MatrixBase<Derived>::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<const MatrixBase<Transpose<OtherDerived> >& >(other));
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
template<typename DerivedA, typename DerivedB>
|
||||
Derived& MatrixBase<Derived>::
|
||||
lazyAssign(const CwiseBinaryOp<ei_scalar_sum_op<Scalar>,Transpose<DerivedA>,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<const MatrixBase<CwiseBinaryOp<ei_scalar_sum_op<Scalar>,Transpose<DerivedA>,DerivedB> >& >(other));
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
template<typename DerivedA, typename DerivedB>
|
||||
Derived& MatrixBase<Derived>::
|
||||
lazyAssign(const CwiseBinaryOp<ei_scalar_sum_op<Scalar>,DerivedA,Transpose<DerivedB> >& other)
|
||||
{
|
||||
ei_assert(ei_extract_data(derived()) != ei_extract_data(other.rhs())
|
||||
&& "aliasing detected during tranposition, please evaluate your expression");
|
||||
return lazyAssign(static_cast<const MatrixBase<CwiseBinaryOp<ei_scalar_sum_op<Scalar>,DerivedA,Transpose<DerivedB> > >& >(other));
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived> Derived&
|
||||
MatrixBase<Derived>::
|
||||
lazyAssign(const CwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, Eigen::Transpose<OtherDerived> >& other)
|
||||
{
|
||||
ei_assert(ei_extract_data(other) != ei_extract_data(derived())
|
||||
&& "aliasing detected during tranposition, please use adjointInPlace()");
|
||||
return lazyAssign(static_cast<const MatrixBase<CwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, Eigen::Transpose<OtherDerived> > >& >(other));
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
template<typename DerivedA, typename DerivedB>
|
||||
Derived& MatrixBase<Derived>::
|
||||
lazyAssign(const CwiseBinaryOp<ei_scalar_sum_op<Scalar>,CwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, Eigen::Transpose<DerivedA> >,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<const MatrixBase<CwiseBinaryOp<ei_scalar_sum_op<Scalar>,CwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, Eigen::Transpose<DerivedA> >,DerivedB> >& >(other));
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
template<typename DerivedA, typename DerivedB>
|
||||
Derived& MatrixBase<Derived>::
|
||||
lazyAssign(const CwiseBinaryOp<ei_scalar_sum_op<Scalar>,DerivedA,CwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, Eigen::Transpose<DerivedB> > >& other)
|
||||
{
|
||||
ei_assert(ei_extract_data(derived()) != ei_extract_data(other.rhs())
|
||||
&& "aliasing detected during tranposition, please evaluate your expression");
|
||||
return lazyAssign(static_cast<const MatrixBase<CwiseBinaryOp<ei_scalar_sum_op<Scalar>,DerivedA,CwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, Eigen::Transpose<DerivedB> > > >& >(other));
|
||||
ei_assert((!ei_check_transpose_aliasing_selector<Scalar,ei_blas_traits<Derived>::IsTransposed,OtherDerived>::run(ei_extract_data(derived()), other))
|
||||
&& "aliasing detected during tranposition, use transposeInPlace() or evaluate the rhs into a temporary using .eval()");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -58,8 +58,8 @@ template<> struct ei_packet_traits<float> : 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
|
||||
|
@ -160,6 +160,7 @@ template<typename XprType> struct ei_blas_traits
|
||||
typedef XprType _ExtractType;
|
||||
enum {
|
||||
IsComplex = NumTraits<Scalar>::IsComplex,
|
||||
IsTransposed = false,
|
||||
NeedToConjugate = false,
|
||||
ActualAccess = int(ei_traits<XprType>::Flags)&DirectAccessBit ? HasDirectAccess : NoDirectAccess
|
||||
};
|
||||
@ -227,6 +228,9 @@ struct ei_blas_traits<Transpose<NestedXpr> >
|
||||
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()); }
|
||||
};
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user