New design for handling automatic transposition

This commit is contained in:
Gael Guennebaud 2014-02-18 10:53:14 +01:00
parent 551bf5c66a
commit 573c587e3d
2 changed files with 36 additions and 27 deletions

View File

@ -661,34 +661,21 @@ struct Assignment;
// 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> struct transpose_to_match
{
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)
{
{TRACK;
call_assignment(dst, src, internal::assign_op<typename Dst::Scalar>());
}
template<typename Dst, typename Src>
void call_assignment(const Dst& dst, const Src& src)
{
{TRACK;
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)
{
{TRACK;
// 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;
@ -699,40 +686,62 @@ void call_assignment(Dst& dst, const Src& src, const Func& func, typename enable
typename Src::PlainObject tmp(src);
#else
typename Src::PlainObject tmp(src.rows(), src.cols());
call_assignment(tmp.noalias(), src);
call_assignment_no_alias(tmp, src, internal::assign_op<typename Dst::Scalar>());
#endif
// resizing
dst.resize(tmp.rows(), tmp.cols());
call_assignment(dst.noalias(), tmp, func);
TRACK;
call_assignment_no_alias(dst, tmp, func);
}
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);
{TRACK;
// There is no explicit no-aliasing, so we must resize here:
dst.resize(src.rows(), src.cols());
call_assignment_no_alias(dst, src, func);
}
// by-pass AssumeAliasing
// FIXME the const version should probably not be needed
// When there is no aliasing, we require that 'dst' has been properly resized
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<typename transpose_to_match<Dst,Src>::type,Src,Func>::run(dst.expression(), src, func);
{TRACK;
call_assignment_no_alias(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<typename transpose_to_match<Dst,Src>::type,Src,Func>::run(dst.expression(), src, func);
{TRACK;
call_assignment_no_alias(dst.expression(), src, func);
}
template<typename Dst, typename Src, typename Func>
void call_assignment_no_alias(Dst& dst, const Src& src, const Func& func)
{TRACK;
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 ActualDstTypeCleaned;
typedef typename internal::conditional<NeedToTranspose, Transpose<Dst>, Dst&>::type ActualDstType;
ActualDstType actualDst(dst);
Assignment<ActualDstTypeCleaned,Src,Func>::run(actualDst, src, func);
}
// Generic Dense to Dense assignment
template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar>
struct Assignment<DstXprType, SrcXprType, Functor, Dense2Dense, Scalar>
{
static void run(DstXprType &dst, const SrcXprType &src, const Functor &func)
{
{TRACK;
// TODO check whether this is the right place to perform these checks:
enum{
SameType = internal::is_same<typename DstXprType::Scalar,typename SrcXprType::Scalar>::value

View File

@ -682,7 +682,7 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type
// 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());
internal::call_assignment_no_alias(this->derived(), other.derived(), internal::assign_op<Scalar>());
return this->derived();
#else
return internal::assign_selector<Derived,OtherDerived,false>::run(this->derived(), other.derived());