aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2014-02-17 16:11:55 +0100
committerGravatar Gael Guennebaud <g.gael@free.fr>2014-02-17 16:11:55 +0100
commitd595fd31f544009e62a55d6ffc26e0b62f3147d5 (patch)
treed65354f2693e90a686ba6f31a4a57a5dbec7b9c8
parentbffa15142c4271313a70801e6bb7d01365a00bc9 (diff)
Deal with automatic transposition in call_assignment, fix a few shortcomings
-rw-r--r--Eigen/src/Core/Assign.h27
-rw-r--r--Eigen/src/Core/AssignEvaluator.h59
-rw-r--r--Eigen/src/Core/PlainObjectBase.h19
-rw-r--r--Eigen/src/Core/TriangularMatrix.h2
-rw-r--r--Eigen/src/Core/products/CoeffBasedProduct.h4
5 files changed, 101 insertions, 10 deletions
diff --git a/Eigen/src/Core/Assign.h b/Eigen/src/Core/Assign.h
index cefa6f3cc..6080a83f6 100644
--- a/Eigen/src/Core/Assign.h
+++ b/Eigen/src/Core/Assign.h
@@ -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
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
diff --git a/Eigen/src/Core/PlainObjectBase.h b/Eigen/src/Core/PlainObjectBase.h
index 0305066ba..8eccbfbd0 100644
--- a/Eigen/src/Core/PlainObjectBase.h
+++ b/Eigen/src/Core/PlainObjectBase.h
@@ -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>
diff --git a/Eigen/src/Core/TriangularMatrix.h b/Eigen/src/Core/TriangularMatrix.h
index d413ec2e9..2b1c236b9 100644
--- a/Eigen/src/Core/TriangularMatrix.h
+++ b/Eigen/src/Core/TriangularMatrix.h
@@ -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
diff --git a/Eigen/src/Core/products/CoeffBasedProduct.h b/Eigen/src/Core/products/CoeffBasedProduct.h
index 5f8182aa9..de06108da 100644
--- a/Eigen/src/Core/products/CoeffBasedProduct.h
+++ b/Eigen/src/Core/products/CoeffBasedProduct.h
@@ -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,