mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-08-12 03:39:01 +08:00
Deal with automatic transposition in call_assignment, fix a few shortcomings
This commit is contained in:
parent
bffa15142c
commit
d595fd31f5
@ -531,6 +531,23 @@ EIGEN_STRONG_INLINE Derived& DenseBase<Derived>
|
||||
|
||||
namespace internal {
|
||||
|
||||
#ifdef EIGEN_TEST_EVALUATORS
|
||||
|
||||
// TODO remove this class which is now useless
|
||||
|
||||
template<typename Derived, typename OtherDerived>
|
||||
struct assign_selector {
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) {
|
||||
call_assignment(dst, other.derived(), internal::assign_op<typename OtherDerived::Scalar>());
|
||||
return dst;
|
||||
}
|
||||
template<typename ActualDerived, typename ActualOtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE Derived& evalTo(ActualDerived& dst, const ActualOtherDerived& other) { other.evalTo(dst); return dst; }
|
||||
};
|
||||
|
||||
#else // EIGEN_TEST_EVALUATORS
|
||||
template<typename Derived, typename OtherDerived,
|
||||
bool EvalBeforeAssigning = (int(internal::traits<OtherDerived>::Flags) & EvalBeforeAssigningBit) != 0,
|
||||
bool NeedToTranspose = ((int(Derived::RowsAtCompileTime) == 1 && int(OtherDerived::ColsAtCompileTime) == 1)
|
||||
@ -566,7 +583,7 @@ struct assign_selector<Derived,OtherDerived,true,true> {
|
||||
EIGEN_DEVICE_FUNC
|
||||
static EIGEN_STRONG_INLINE Derived& run(Derived& dst, const OtherDerived& other) { return dst.lazyAssign(other.transpose().eval()); }
|
||||
};
|
||||
|
||||
#endif // EIGEN_TEST_EVALUATORS
|
||||
} // end namespace internal
|
||||
|
||||
template<typename Derived>
|
||||
@ -604,7 +621,11 @@ template <typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const EigenBase<OtherDerived>& other)
|
||||
{
|
||||
#ifdef EIGEN_TEST_EVALUATORS
|
||||
return internal::assign_selector<Derived,OtherDerived>::evalTo(derived(), other.derived());
|
||||
#else
|
||||
return internal::assign_selector<Derived,OtherDerived,false>::evalTo(derived(), other.derived());
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
@ -612,7 +633,11 @@ template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Derived& MatrixBase<Derived>::operator=(const ReturnByValue<OtherDerived>& other)
|
||||
{
|
||||
#ifdef EIGEN_TEST_EVALUATORS
|
||||
return internal::assign_selector<Derived,OtherDerived>::evalTo(derived(), other.derived());
|
||||
#else
|
||||
return internal::assign_selector<Derived,OtherDerived,false>::evalTo(derived(), other.derived());
|
||||
#endif
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
@ -656,28 +656,75 @@ template< typename DstXprType, typename SrcXprType, typename Functor,
|
||||
struct Assignment;
|
||||
|
||||
|
||||
// The only purpose of this call_assignment() function is to deal with noalias() / AssumeAliasing.
|
||||
// The only purpose of this call_assignment() function is to deal with noalias() / AssumeAliasing and automatic transposition.
|
||||
// Indeed, I (Gael) think that this concept of AssumeAliasing was a mistake, and it makes thing quite complicated.
|
||||
// So this intermediate function removes everything related to AssumeAliasing such that Assignment
|
||||
// does not has to bother about these annoying details.
|
||||
|
||||
template<typename Dst, typename Src, typename Func>
|
||||
void call_assignment(Dst& dst, const Src& src, const Func& func)
|
||||
template<typename Dst, typename Src> struct transpose_to_match
|
||||
{
|
||||
typedef typename internal::conditional<evaluator_traits<Src>::AssumeAliasing==1, EvalToTemp<Src>, Src>::type ActualSrc;
|
||||
Assignment<Dst,ActualSrc,Func>::run(dst, src, func);
|
||||
enum {
|
||||
NeedToTranspose = ( (int(Dst::RowsAtCompileTime) == 1 && int(Src::ColsAtCompileTime) == 1)
|
||||
| // FIXME | instead of || to please GCC 4.4.0 stupid warning "suggest parentheses around &&".
|
||||
// revert to || as soon as not needed anymore.
|
||||
(int(Dst::ColsAtCompileTime) == 1 && int(Src::RowsAtCompileTime) == 1))
|
||||
&& int(Dst::SizeAtCompileTime) != 1
|
||||
};
|
||||
|
||||
typedef typename internal::conditional<NeedToTranspose, Transpose<Dst>, Dst>::type type;
|
||||
};
|
||||
|
||||
template<typename Dst, typename Src>
|
||||
void call_assignment(Dst& dst, const Src& src)
|
||||
{
|
||||
call_assignment(dst, src, internal::assign_op<typename Dst::Scalar>());
|
||||
}
|
||||
template<typename Dst, typename Src>
|
||||
void call_assignment(const Dst& dst, const Src& src)
|
||||
{
|
||||
call_assignment(dst, src, internal::assign_op<typename Dst::Scalar>());
|
||||
}
|
||||
|
||||
// Deal with AssumeAliasing
|
||||
template<typename Dst, typename Src, typename Func>
|
||||
void call_assignment(Dst& dst, const Src& src, const Func& func, typename enable_if<evaluator_traits<Src>::AssumeAliasing==1, void*>::type = 0)
|
||||
{
|
||||
// The following initial implementation through an EvalToTemp object does not permit to
|
||||
// perform deferred resizing as in 'A = A * B' when the size of 'A' as to be changed
|
||||
// typedef typename internal::conditional<evaluator_traits<Src>::AssumeAliasing==1, EvalToTemp<Src>, Src>::type ActualSrc;
|
||||
// Assignment<Dst,ActualSrc,Func>::run(dst, src, func);
|
||||
|
||||
// TODO we should simply do tmp(src);
|
||||
#ifdef EIGEN_TEST_EVALUATORS
|
||||
typename Src::PlainObject tmp(src);
|
||||
#else
|
||||
typename Src::PlainObject tmp(src.rows(), src.cols());
|
||||
call_assignment(tmp.noalias(), src);
|
||||
#endif
|
||||
|
||||
// resizing
|
||||
dst.resize(tmp.rows(), tmp.cols());
|
||||
call_assignment(dst.noalias(), tmp, func);
|
||||
TRACK;
|
||||
}
|
||||
|
||||
template<typename Dst, typename Src, typename Func>
|
||||
void call_assignment(Dst& dst, const Src& src, const Func& func, typename enable_if<evaluator_traits<Src>::AssumeAliasing==0, void*>::type = 0)
|
||||
{
|
||||
Assignment<typename transpose_to_match<Dst,Src>::type,Src,Func>::run(dst, src, func);
|
||||
}
|
||||
|
||||
// by-pass AssumeAliasing
|
||||
// FIXME the const version should probably not be needed
|
||||
template<typename Dst, template <typename> class StorageBase, typename Src, typename Func>
|
||||
void call_assignment(const NoAlias<Dst,StorageBase>& dst, const Src& src, const Func& func)
|
||||
{
|
||||
Assignment<Dst,Src,Func>::run(dst.expression(), src, func);
|
||||
Assignment<typename transpose_to_match<Dst,Src>::type,Src,Func>::run(dst.expression(), src, func);
|
||||
}
|
||||
template<typename Dst, template <typename> class StorageBase, typename Src, typename Func>
|
||||
void call_assignment(NoAlias<Dst,StorageBase>& dst, const Src& src, const Func& func)
|
||||
{
|
||||
Assignment<Dst,Src,Func>::run(dst.expression(), src, func);
|
||||
Assignment<typename transpose_to_match<Dst,Src>::type,Src,Func>::run(dst.expression(), src, func);
|
||||
}
|
||||
|
||||
// Generic Dense to Dense assignment
|
||||
|
@ -639,6 +639,18 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
*
|
||||
* \internal
|
||||
*/
|
||||
#ifdef EIGEN_TEST_EVALUATORS
|
||||
// aliasing is dealt once in internall::call_assignment
|
||||
// so at this stage we have to assume aliasing... and resising has to be done later.
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other)
|
||||
{
|
||||
internal::call_assignment(this->derived(), other.derived());
|
||||
return this->derived();
|
||||
return this->derived();
|
||||
}
|
||||
#else
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE Derived& _set(const DenseBase<OtherDerived>& other)
|
||||
@ -654,7 +666,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
template<typename OtherDerived>
|
||||
EIGEN_DEVICE_FUNC
|
||||
EIGEN_STRONG_INLINE void _set_selector(const OtherDerived& other, const internal::false_type&) { _set_noalias(other); }
|
||||
|
||||
#endif
|
||||
/** \internal Like _set() but additionally makes the assumption that no aliasing effect can happen (which
|
||||
* is the case when creating a new matrix) so one can enforce lazy evaluation.
|
||||
*
|
||||
@ -669,7 +681,12 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
|
||||
//_resize_to_match(other);
|
||||
// the 'false' below means to enforce lazy evaluation. We don't use lazyAssign() because
|
||||
// it wouldn't allow to copy a row-vector into a column-vector.
|
||||
#ifdef EIGEN_TEST_EVALUATORS
|
||||
internal::call_assignment(this->noalias(), other.derived());
|
||||
return this->derived();
|
||||
#else
|
||||
return internal::assign_selector<Derived,OtherDerived,false>::run(this->derived(), other.derived());
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T0, typename T1>
|
||||
|
@ -1235,6 +1235,7 @@ struct triangular_assignment_loop<Kernel, Mode, Dynamic, SetOpposite>
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
#ifdef EIGEN_TEST_EVALUATORS
|
||||
/** Assigns a triangular or selfadjoint matrix to a dense matrix.
|
||||
* If the matrix is triangular, the opposite part is set to zero. */
|
||||
template<typename Derived>
|
||||
@ -1244,6 +1245,7 @@ void TriangularBase<Derived>::evalToLazy(MatrixBase<DenseDerived> &other) const
|
||||
other.derived().resize(this->rows(), this->cols());
|
||||
internal::call_triangular_assignment_loop<Derived::Mode,(Derived::Mode&SelfAdjoint)==0 /* SetOpposite */>(other.derived(), derived().nestedExpression());
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // EIGEN_ENABLE_EVALUATORS
|
||||
|
||||
|
@ -47,8 +47,8 @@ struct traits<CoeffBasedProduct<LhsNested,RhsNested,NestingFlags> >
|
||||
typename traits<_RhsNested>::Index>::type Index;
|
||||
|
||||
enum {
|
||||
LhsCoeffReadCost = _LhsNested::CoeffReadCost,
|
||||
RhsCoeffReadCost = _RhsNested::CoeffReadCost,
|
||||
LhsCoeffReadCost = traits<_LhsNested>::CoeffReadCost,
|
||||
RhsCoeffReadCost = traits<_RhsNested>::CoeffReadCost,
|
||||
LhsFlags = traits<_LhsNested>::Flags,
|
||||
RhsFlags = traits<_RhsNested>::Flags,
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user