From 94acccc126d430bf34587527d84ff9b389219c2f Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sun, 26 Jan 2014 15:35:44 +0100 Subject: [PATCH] Fix Random().normalized() by introducing a nested_eval helper (recall that the old nested<> class is deprecated) --- Eigen/src/Core/Dot.h | 7 ++++++- Eigen/src/Core/util/XprHelper.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Eigen/src/Core/Dot.h b/Eigen/src/Core/Dot.h index 718de5d1a..38f6fbf44 100644 --- a/Eigen/src/Core/Dot.h +++ b/Eigen/src/Core/Dot.h @@ -141,8 +141,13 @@ template inline const typename MatrixBase::PlainObject MatrixBase::normalized() const { - typedef typename internal::nested::type Nested; +#ifndef EIGEN_TEST_EVALUATORS + typedef typename internal::nested::type Nested; typedef typename internal::remove_reference::type _Nested; +#else + typedef typename internal::nested_eval::type _Nested; +// typedef typename internal::remove_reference::type _Nested; +#endif // EIGEN_TEST_EVALUATORS _Nested n(derived()); return n / n.norm(); } diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h index 189928c8f..f210344d3 100644 --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -296,11 +296,40 @@ struct transfer_constness #ifdef EIGEN_TEST_EVALUATORS // When using evaluators, we never evaluate when assembling the expression!! +// TODO: get rid of this nested class since it's just an alias for ref_selector. template::type> struct nested { typedef typename ref_selector::type type; }; +// However, we still need a mechanism to detect whether an expression which is evaluated multiple time +// has to be evaluated into a temporary. +// That's the purpose of this new nested_eval helper: +template::type> struct nested_eval +{ + enum { + // For the purpose of this test, to keep it reasonably simple, we arbitrarily choose a value of Dynamic values. + // the choice of 10000 makes it larger than any practical fixed value and even most dynamic values. + // in extreme cases where these assumptions would be wrong, we would still at worst suffer performance issues + // (poor choice of temporaries). + // It's important that this value can still be squared without integer overflowing. + DynamicAsInteger = 10000, + ScalarReadCost = NumTraits::Scalar>::ReadCost, + ScalarReadCostAsInteger = ScalarReadCost == Dynamic ? int(DynamicAsInteger) : int(ScalarReadCost), + CoeffReadCost = traits::CoeffReadCost, + CoeffReadCostAsInteger = CoeffReadCost == Dynamic ? int(DynamicAsInteger) : int(CoeffReadCost), + NAsInteger = n == Dynamic ? int(DynamicAsInteger) : n, + CostEvalAsInteger = (NAsInteger+1) * ScalarReadCostAsInteger + CoeffReadCostAsInteger, + CostNoEvalAsInteger = NAsInteger * CoeffReadCostAsInteger + }; + + typedef typename conditional< + int(CostEvalAsInteger) < int(CostNoEvalAsInteger), + PlainObject, + typename ref_selector::type + >::type type; +}; + #else /** \internal Determines how a given expression should be nested into another one. * For example, when you do a * (b+c), Eigen will determine how the expression b+c should be