diff options
author | 2014-02-17 16:11:55 +0100 | |
---|---|---|
committer | 2014-02-17 16:11:55 +0100 | |
commit | d595fd31f544009e62a55d6ffc26e0b62f3147d5 (patch) | |
tree | d65354f2693e90a686ba6f31a4a57a5dbec7b9c8 /Eigen/src/Core/AssignEvaluator.h | |
parent | bffa15142c4271313a70801e6bb7d01365a00bc9 (diff) |
Deal with automatic transposition in call_assignment, fix a few shortcomings
Diffstat (limited to 'Eigen/src/Core/AssignEvaluator.h')
-rw-r--r-- | Eigen/src/Core/AssignEvaluator.h | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/Eigen/src/Core/AssignEvaluator.h b/Eigen/src/Core/AssignEvaluator.h index fe6fbdb9a..0a3475d83 100644 --- a/Eigen/src/Core/AssignEvaluator.h +++ b/Eigen/src/Core/AssignEvaluator.h @@ -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> 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) +{ + 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) +void call_assignment(Dst& dst, const Src& src, const Func& func, typename enable_if<evaluator_traits<Src>::AssumeAliasing==0, void*>::type = 0) { - typedef typename internal::conditional<evaluator_traits<Src>::AssumeAliasing==1, EvalToTemp<Src>, Src>::type ActualSrc; - Assignment<Dst,ActualSrc,Func>::run(dst, src, func); + 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 |