From 34ca81b1bfe77b11effdd463099b30d12b6466c9 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Mon, 2 Dec 2013 16:37:58 +0100 Subject: [PATCH] Add direct assignment of products --- Eigen/src/Core/AssignEvaluator.h | 5 ++++ Eigen/src/Core/ProductEvaluators.h | 40 ++++++++++++++++++++++++++++-- test/evaluators.cpp | 15 +++++++++-- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/Eigen/src/Core/AssignEvaluator.h b/Eigen/src/Core/AssignEvaluator.h index 3babc16ba..6d3739407 100644 --- a/Eigen/src/Core/AssignEvaluator.h +++ b/Eigen/src/Core/AssignEvaluator.h @@ -679,6 +679,11 @@ void call_assignment(const NoAlias& dst, const Src& src, const { Assignment::run(dst.expression(), src, func); } +template class StorageBase, typename Src, typename Func> +void call_assignment(NoAlias& dst, const Src& src, const Func& func) +{ + Assignment::run(dst.expression(), src, func); +} // Generic Dense to Dense assignment template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> diff --git a/Eigen/src/Core/ProductEvaluators.h b/Eigen/src/Core/ProductEvaluators.h index 26145ceff..d0dba1644 100644 --- a/Eigen/src/Core/ProductEvaluators.h +++ b/Eigen/src/Core/ProductEvaluators.h @@ -45,6 +45,12 @@ struct evaluator > template::value> struct dense_product_impl; +template +struct evaluator_traits > + : evaluator_traits_base > +{ + enum { AssumeAliasing = 1 }; +}; // The evaluator for default dense products creates a temporary and call dense_product_impl template @@ -58,9 +64,7 @@ struct product_evaluator, ProductTag, DenseSha product_evaluator(const XprType& xpr) : m_result(xpr.rows(), xpr.cols()) { - ::new (static_cast(this)) Base(m_result); - dense_product_impl::evalTo(m_result, xpr.lhs(), xpr.rhs()); } @@ -68,6 +72,38 @@ protected: PlainObject m_result; }; +// Dense = Product +template< typename DstXprType, typename Lhs, typename Rhs, typename Scalar> +struct Assignment, internal::assign_op, Dense2Dense, Scalar> +{ + typedef Product SrcXprType; + static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &) + { + dense_product_impl::evalTo(dst, src.lhs(), src.rhs()); + } +}; + +// Dense += Product +template< typename DstXprType, typename Lhs, typename Rhs, typename Scalar> +struct Assignment, internal::add_assign_op, Dense2Dense, Scalar> +{ + typedef Product SrcXprType; + static void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op &) + { + dense_product_impl::addTo(dst, src.lhs(), src.rhs()); + } +}; + +// Dense -= Product +template< typename DstXprType, typename Lhs, typename Rhs, typename Scalar> +struct Assignment, internal::sub_assign_op, Dense2Dense, Scalar> +{ + typedef Product SrcXprType; + static void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op &) + { + dense_product_impl::subTo(dst, src.lhs(), src.rhs()); + } +}; template struct dense_product_impl diff --git a/test/evaluators.cpp b/test/evaluators.cpp index 7a20014dd..c07146260 100644 --- a/test/evaluators.cpp +++ b/test/evaluators.cpp @@ -47,14 +47,14 @@ namespace Eigen { void add_assign_using_evaluator(const DstXprType& dst, const SrcXprType& src) { typedef typename DstXprType::Scalar Scalar; - call_assignment(dst.const_cast_derived(), src.derived(), internal::add_assign_op()); + call_assignment(const_cast(dst), src.derived(), internal::add_assign_op()); } template void subtract_assign_using_evaluator(const DstXprType& dst, const SrcXprType& src) { typedef typename DstXprType::Scalar Scalar; - call_assignment(dst.const_cast_derived(), src.derived(), internal::sub_assign_op()); + call_assignment(const_cast(dst), src.derived(), internal::sub_assign_op()); } template @@ -151,6 +151,17 @@ void test_evaluators() c = a*a; copy_using_evaluator(a, prod(a,a)); VERIFY_IS_APPROX(a,c); + + // check compound assignment of products + d = c; + add_assign_using_evaluator(c.noalias(), prod(a,b)); + d.noalias() += a*b; + VERIFY_IS_APPROX(c, d); + + d = c; + subtract_assign_using_evaluator(c.noalias(), prod(a,b)); + d.noalias() -= a*b; + VERIFY_IS_APPROX(c, d); } {