From 573c587e3d66c8151f6523433d853664e1fa7667 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Tue, 18 Feb 2014 10:53:14 +0100 Subject: New design for handling automatic transposition --- Eigen/src/Core/AssignEvaluator.h | 61 +++++++++++++++++++++++----------------- Eigen/src/Core/PlainObjectBase.h | 2 +- 2 files changed, 36 insertions(+), 27 deletions(-) (limited to 'Eigen/src/Core') diff --git a/Eigen/src/Core/AssignEvaluator.h b/Eigen/src/Core/AssignEvaluator.h index 0a3475d83..d5745f20c 100644 --- a/Eigen/src/Core/AssignEvaluator.h +++ b/Eigen/src/Core/AssignEvaluator.h @@ -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 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, Dst>::type type; -}; - template void call_assignment(Dst& dst, const Src& src) -{ +{TRACK; call_assignment(dst, src, internal::assign_op()); } template void call_assignment(const Dst& dst, const Src& src) -{ +{TRACK; call_assignment(dst, src, internal::assign_op()); } // Deal with AssumeAliasing template void call_assignment(Dst& dst, const Src& src, const Func& func, typename enable_if::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::AssumeAliasing==1, EvalToTemp, 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()); #endif // resizing dst.resize(tmp.rows(), tmp.cols()); - call_assignment(dst.noalias(), tmp, func); - TRACK; + call_assignment_no_alias(dst, tmp, func); } template void call_assignment(Dst& dst, const Src& src, const Func& func, typename enable_if::AssumeAliasing==0, void*>::type = 0) -{ - Assignment::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 class StorageBase, typename Src, typename Func> void call_assignment(const NoAlias& dst, const Src& src, const Func& func) -{ - Assignment::type,Src,Func>::run(dst.expression(), src, func); +{TRACK; + call_assignment_no_alias(dst.expression(), src, func); } template class StorageBase, typename Src, typename Func> void call_assignment(NoAlias& dst, const Src& src, const Func& func) -{ - Assignment::type,Src,Func>::run(dst.expression(), src, func); +{TRACK; + call_assignment_no_alias(dst.expression(), src, func); +} + + +template +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, Dst>::type ActualDstTypeCleaned; + typedef typename internal::conditional, Dst&>::type ActualDstType; + ActualDstType actualDst(dst); + + Assignment::run(actualDst, src, func); } + // Generic Dense to Dense assignment template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> struct Assignment { 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::value diff --git a/Eigen/src/Core/PlainObjectBase.h b/Eigen/src/Core/PlainObjectBase.h index 8eccbfbd0..4f456804c 100644 --- a/Eigen/src/Core/PlainObjectBase.h +++ b/Eigen/src/Core/PlainObjectBase.h @@ -682,7 +682,7 @@ class PlainObjectBase : public internal::dense_xpr_base::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()); return this->derived(); #else return internal::assign_selector::run(this->derived(), other.derived()); -- cgit v1.2.3