aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen/src/Core
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2014-02-18 10:53:14 +0100
committerGravatar Gael Guennebaud <g.gael@free.fr>2014-02-18 10:53:14 +0100
commit573c587e3d66c8151f6523433d853664e1fa7667 (patch)
tree6f3c23696dd901b32eccc51e2034953ea3fb3396 /Eigen/src/Core
parent551bf5c66a3f29c8ac1f24f8439a6b85d0da79ac (diff)
New design for handling automatic transposition
Diffstat (limited to 'Eigen/src/Core')
-rw-r--r--Eigen/src/Core/AssignEvaluator.h61
-rw-r--r--Eigen/src/Core/PlainObjectBase.h2
2 files changed, 36 insertions, 27 deletions
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<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
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<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());