add overloads of lazyAssign to detect common aliasing issue with

transpose and adjoint
This commit is contained in:
Gael Guennebaud
2009-08-15 22:19:29 +02:00
parent a3e6047c25
commit 239ada95b7
5 changed files with 122 additions and 3 deletions

View File

@@ -85,6 +85,8 @@ class CwiseBinaryOp : ei_no_assignment_operator,
EIGEN_GENERIC_PUBLIC_INTERFACE(CwiseBinaryOp)
typedef typename ei_traits<CwiseBinaryOp>::LhsNested LhsNested;
typedef typename ei_traits<CwiseBinaryOp>::RhsNested RhsNested;
typedef typename ei_traits<CwiseBinaryOp>::_LhsNested _LhsNested;
typedef typename ei_traits<CwiseBinaryOp>::_RhsNested _RhsNested;
EIGEN_STRONG_INLINE CwiseBinaryOp(const Lhs& lhs, const Rhs& rhs, const BinaryOp& func = BinaryOp())
: m_lhs(lhs), m_rhs(rhs), m_functor(func)
@@ -130,6 +132,10 @@ class CwiseBinaryOp : ei_no_assignment_operator,
return m_functor.packetOp(m_lhs.template packet<LoadMode>(index), m_rhs.template packet<LoadMode>(index));
}
const _LhsNested& lhs() const { return m_lhs; }
const _RhsNested& rhs() const { return m_rhs; }
const BinaryOp& functor() const { return m_functor; }
protected:
const LhsNested m_lhs;
const RhsNested m_rhs;

View File

@@ -457,6 +457,21 @@ template<typename Derived> class MatrixBase
void transposeInPlace();
const AdjointReturnType adjoint() const;
void adjointInPlace();
#ifndef EIGEN_NO_DEBUG
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>, NestByValue<Eigen::Transpose<OtherDerived> > >& other);
template<typename DerivedA, typename DerivedB>
Derived& lazyAssign(const CwiseBinaryOp<ei_scalar_sum_op<Scalar>,CwiseUnaryOp<ei_scalar_conjugate_op<Scalar>, NestByValue<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>, NestByValue<Eigen::Transpose<DerivedB> > > >& other);
#endif
RowXpr row(int i);
const RowXpr row(int i) const;

View File

@@ -267,4 +267,92 @@ inline void MatrixBase<Derived>::adjointInPlace()
derived() = adjoint().eval();
}
#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()
template<typename T, int Access=ei_blas_traits<T>::ActualAccess>
struct ei_extract_data_selector {
static typename T::Scalar* run(const T& m)
{
return &ei_blas_traits<T>::extract(m).const_cast_derived().coeffRef(0,0);
}
};
template<typename T>
struct ei_extract_data_selector<T,NoDirectAccess> {
static typename T::Scalar* run(const T&) { return 0; }
};
template<typename T> typename T::Scalar* ei_extract_data(const T& m)
{
return ei_extract_data_selector<T>::run(m);
}
template<typename Derived>
template<typename OtherDerived>
Derived& MatrixBase<Derived>::lazyAssign(const Transpose<OtherDerived>& other)
{
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>, NestByValue<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>, NestByValue<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>, NestByValue<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>, NestByValue<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>, NestByValue<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>, NestByValue<Eigen::Transpose<DerivedB> > > > >& >(other));
}
#endif
#endif // EIGEN_TRANSPOSE_H