aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Jitse Niesen <jitse@maths.leeds.ac.uk>2012-06-29 13:54:09 +0100
committerGravatar Jitse Niesen <jitse@maths.leeds.ac.uk>2012-06-29 13:54:09 +0100
commit746378868a6d19656c09ad8288a7b862d588253f (patch)
tree07d07a227026635b5bb3d168acc136053fb06bf5
parentd0b873822f52f5739868ba322dae5b3d0c399a4d (diff)
Implement A.noalias() = B * C without temporaries
* Wrap expression inside EvalToTemp in copy_using_evaluators() if we assume aliasing for that expression (that is, for products) * Remove temporary kludge of evaluating expression to temporary in AllAtOnce traversal * Implement EvalToTemp expression object
-rw-r--r--Eigen/src/Core/AssignEvaluator.h30
-rw-r--r--Eigen/src/Core/CoreEvaluators.h51
-rw-r--r--Eigen/src/Core/ProductEvaluators.h4
3 files changed, 77 insertions, 8 deletions
diff --git a/Eigen/src/Core/AssignEvaluator.h b/Eigen/src/Core/AssignEvaluator.h
index 9be00067d..9f5deb8e7 100644
--- a/Eigen/src/Core/AssignEvaluator.h
+++ b/Eigen/src/Core/AssignEvaluator.h
@@ -617,12 +617,8 @@ struct copy_using_evaluator_impl<DstXprType, SrcXprType, AllAtOnceTraversal, NoU
SrcEvaluatorType srcEvaluator(src);
// Evaluate rhs in temporary to prevent aliasing problems in a = a * a;
- // TODO: Be smarter about this
// TODO: Do not pass the xpr object to evalTo()
- typename DstXprType::PlainObject tmp;
- typename evaluator<typename DstXprType::PlainObject>::type tmpEvaluator(tmp);
- srcEvaluator.evalTo(tmpEvaluator, tmp);
- copy_using_evaluator(dst, tmp);
+ srcEvaluator.evalTo(dstEvaluator, dst);
}
};
@@ -640,11 +636,33 @@ const DstXprType& copy_using_evaluator(const NoAlias<DstXprType, StorageBase>& d
return noalias_copy_using_evaluator(dst.expression(), src.derived());
}
+template<typename XprType, int AssumeAliasing = evaluator_traits<XprType>::AssumeAliasing>
+struct AddEvalIfAssumingAliasing;
+
+template<typename XprType>
+struct AddEvalIfAssumingAliasing<XprType, 0>
+{
+ static const XprType& run(const XprType& xpr)
+ {
+ return xpr;
+ }
+};
+
+template<typename XprType>
+struct AddEvalIfAssumingAliasing<XprType, 1>
+{
+ static const EvalToTemp<XprType> run(const XprType& xpr)
+ {
+ return EvalToTemp<XprType>(xpr);
+ }
+};
+
template<typename DstXprType, typename SrcXprType>
EIGEN_STRONG_INLINE
const DstXprType& copy_using_evaluator(const EigenBase<DstXprType>& dst, const EigenBase<SrcXprType>& src)
{
- return noalias_copy_using_evaluator(dst.const_cast_derived(), src.derived());
+ return noalias_copy_using_evaluator(dst.const_cast_derived(),
+ AddEvalIfAssumingAliasing<SrcXprType>::run(src.derived()));
}
template<typename DstXprType, typename SrcXprType>
diff --git a/Eigen/src/Core/CoreEvaluators.h b/Eigen/src/Core/CoreEvaluators.h
index 808546ec1..906df2af7 100644
--- a/Eigen/src/Core/CoreEvaluators.h
+++ b/Eigen/src/Core/CoreEvaluators.h
@@ -40,6 +40,10 @@ struct evaluator_traits
// 1 if evaluator_impl<T>::evalTo() exists
// 0 if evaluator_impl<T> allows coefficient-based access
static const int HasEvalTo = 0;
+
+ // 1 if assignment A = B assumes aliasing when B is of type T and thus B needs to be evaluated into a
+ // temporary; 0 if not.
+ static const int AssumeAliasing = 0;
};
// expression class for evaluating nested expression to a temporary
@@ -246,16 +250,61 @@ struct evaluator_impl<Array<Scalar, Rows, Cols, Options, MaxRows, MaxCols> >
// -------------------- EvalToTemp --------------------
template<typename ArgType>
+struct traits<EvalToTemp<ArgType> >
+ : public traits<ArgType>
+{ };
+
+template<typename ArgType>
+class EvalToTemp
+ : public dense_xpr_base<EvalToTemp<ArgType> >::type
+{
+ public:
+
+ typedef typename dense_xpr_base<EvalToTemp>::type Base;
+ EIGEN_GENERIC_PUBLIC_INTERFACE(EvalToTemp)
+
+ EvalToTemp(const ArgType& arg)
+ : m_arg(arg)
+ { }
+
+ const ArgType& arg() const
+ {
+ return m_arg;
+ }
+
+ Index rows() const
+ {
+ return m_arg.rows();
+ }
+
+ Index cols() const
+ {
+ return m_arg.cols();
+ }
+
+ private:
+ const ArgType& m_arg;
+};
+
+template<typename ArgType>
struct evaluator_impl<EvalToTemp<ArgType> >
: evaluator_impl<typename ArgType::PlainObject>
{
+ typedef EvalToTemp<ArgType> XprType;
typedef typename ArgType::PlainObject PlainObject;
typedef evaluator_impl<PlainObject> BaseType;
+ evaluator_impl(const XprType& xpr)
+ : BaseType(m_result)
+ {
+ noalias_copy_using_evaluator(m_result, xpr.arg());
+ };
+
+ // this constructor is used when nesting an EvalTo evaluator in another evaluator
evaluator_impl(const ArgType& arg)
: BaseType(m_result)
{
- copy_using_evaluator(m_result, arg);
+ noalias_copy_using_evaluator(m_result, arg);
};
protected:
diff --git a/Eigen/src/Core/ProductEvaluators.h b/Eigen/src/Core/ProductEvaluators.h
index e814a4710..3804113f8 100644
--- a/Eigen/src/Core/ProductEvaluators.h
+++ b/Eigen/src/Core/ProductEvaluators.h
@@ -56,7 +56,9 @@ struct product_evaluator_traits_dispatcher;
template<typename Lhs, typename Rhs>
struct evaluator_traits<Product<Lhs, Rhs> >
: product_evaluator_traits_dispatcher<Product<Lhs, Rhs>, typename ProductReturnType<Lhs, Rhs>::Type>
-{ };
+{
+ static const int AssumeAliasing = 1;
+};
// Case 1: Evaluate all at once
//