aboutsummaryrefslogtreecommitdiffhomepage
path: root/Eigen
diff options
context:
space:
mode:
authorGravatar Hauke Heibel <hauke.heibel@gmail.com>2009-11-30 18:56:56 +0100
committerGravatar Hauke Heibel <hauke.heibel@gmail.com>2009-11-30 18:56:56 +0100
commit1c2e476fa745d7323d77959d5fb88fd3587be187 (patch)
tree47a46b365f1bab31008a6595ac4607f1b239b05b /Eigen
parent66534b782c243f8a9a6c392674fa6e1706e7e822 (diff)
Initial commit for a modified ei_nested logic.
Diffstat (limited to 'Eigen')
-rw-r--r--Eigen/src/Core/util/XprHelper.h61
1 files changed, 54 insertions, 7 deletions
diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h
index be4266f85..7f58797d7 100644
--- a/Eigen/src/Core/util/XprHelper.h
+++ b/Eigen/src/Core/util/XprHelper.h
@@ -171,6 +171,46 @@ template<typename T> struct ei_plain_matrix_type_row_major
template<typename T> struct ei_must_nest_by_value { enum { ret = false }; };
template<typename T> struct ei_must_nest_by_value<NestByValue<T> > { enum { ret = true }; };
+/**
+* Just a sanity check in order to verify that NestByValue is never
+* used in combination with Matrix. Currently, I don't see a use case
+* for nesting matrices by value. When an expression requires a temporary
+* this should be handled through PlainMatrixType (i.e. arithmetic cost
+* check + eval before nesting check).
+* Note: If this were happening there were no harm but - if we are sure
+* this does not happen, we can actually get rid of NestByValue!
+**/
+template <typename T> struct ei_is_nested_matrix { typedef int ok; };
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+struct ei_is_nested_matrix< NestByValue< Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> > > {};
+
+/**
+* The reference selector for template expressions. The idea is that we don't
+* need to use references for expressions since they are light weight proxy
+* objects which should generate no copying overhead.
+**/
+template <typename T>
+struct ei_ref_selector
+{
+ typedef T type;
+};
+
+/**
+* Matrices on the other hand side should only be copied, when it is sure
+* we gain by copying (see arithmetic cost check and eval before nesting flag).
+* Note: This is an optimization measure that comprises potential (though little)
+* to create erroneous code. Any user, utilizing ei_nested outside of
+* Eigen needs to take care that no references to temporaries are
+* stored or that this potential danger is at least communicated
+* to the user.
+**/
+template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
+struct ei_ref_selector< Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> >
+{
+ typedef typename Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols> MatrixType;
+ typedef MatrixType const& type;
+};
+
/** \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
* nested into the bigger product expression. The choice is between nesting the expression b+c as-is, or
@@ -195,15 +235,22 @@ template<typename T, int n=1, typename PlainMatrixType = typename ei_eval<T>::ty
CostEval = (n+1) * int(NumTraits<typename ei_traits<T>::Scalar>::ReadCost),
CostNoEval = (n-1) * int(ei_traits<T>::CoeffReadCost)
};
+
+ typedef typename ei_is_nested_matrix<T>::ok is_ok;
+
typedef typename ei_meta_if<
ei_must_nest_by_value<T>::ret,
- T,
- typename ei_meta_if<
- (int(ei_traits<T>::Flags) & EvalBeforeNestingBit)
- || ( int(CostEval) <= int(CostNoEval) ),
- PlainMatrixType,
- const T&
- >::ret
+ T,
+ typename ei_meta_if<
+ ( int(ei_traits<T>::Flags) & EvalBeforeNestingBit ) ||
+ ( int(CostEval) <= int(CostNoEval) ),
+ PlainMatrixType,
+#ifdef EIGEN_OLD_NESTED
+ const T&
+#else
+ typename ei_ref_selector<T>::type
+#endif
+ >::ret
>::ret type;
};