diff options
author | Jitse Niesen <jitse@maths.leeds.ac.uk> | 2012-06-29 13:54:09 +0100 |
---|---|---|
committer | Jitse Niesen <jitse@maths.leeds.ac.uk> | 2012-06-29 13:54:09 +0100 |
commit | 746378868a6d19656c09ad8288a7b862d588253f (patch) | |
tree | 07d07a227026635b5bb3d168acc136053fb06bf5 | |
parent | d0b873822f52f5739868ba322dae5b3d0c399a4d (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.h | 30 | ||||
-rw-r--r-- | Eigen/src/Core/CoreEvaluators.h | 51 | ||||
-rw-r--r-- | Eigen/src/Core/ProductEvaluators.h | 4 |
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 // |