From 4d302a080c775290acf23935f233cebbe19540f4 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Thu, 19 Jan 2017 20:34:18 +0100 Subject: [PATCH] Recover compile-time size from seq(A,B) when A and B are fixed values. (c++11 only) --- Eigen/src/Core/ArithmeticSequence.h | 27 ++++++++++++++++---------- Eigen/src/Core/util/IntegralConstant.h | 4 ++++ Eigen/src/Core/util/SymbolicIndex.h | 7 +++++++ test/indexed_view.cpp | 20 +++++++++++++++++-- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/Eigen/src/Core/ArithmeticSequence.h b/Eigen/src/Core/ArithmeticSequence.h index 1f3a9e583..646eb5770 100644 --- a/Eigen/src/Core/ArithmeticSequence.h +++ b/Eigen/src/Core/ArithmeticSequence.h @@ -191,18 +191,22 @@ auto seq(FirstType f, LastType l); #if EIGEN_HAS_CXX11 template -auto seq(FirstType f, LastType l) -> decltype(seqN(f,(l-f+fix<1>()))) +auto seq(FirstType f, LastType l) -> decltype(seqN(f,( typename internal::cleanup_index_type::type(l) + - typename internal::cleanup_index_type::type(f)+fix<1>()))) { - return seqN(f,(l-f+fix<1>())); + return seqN(f,(typename internal::cleanup_index_type::type(l) + -typename internal::cleanup_index_type::type(f)+fix<1>())); } template auto seq(FirstType f, LastType l, IncrType incr) - -> decltype(seqN(f, (l-f+typename internal::cleanup_seq_incr::type(incr)) + -> decltype(seqN(f, ( typename internal::cleanup_index_type::type(l) + - typename internal::cleanup_index_type::type(f)+typename internal::cleanup_seq_incr::type(incr)) / typename internal::cleanup_seq_incr::type(incr),typename internal::cleanup_seq_incr::type(incr))) { typedef typename internal::cleanup_seq_incr::type CleanedIncrType; - return seqN(f,(l-f+CleanedIncrType(incr))/CleanedIncrType(incr),CleanedIncrType(incr)); + return seqN(f,(typename internal::cleanup_index_type::type(l) + -typename internal::cleanup_index_type::type(f)+CleanedIncrType(incr)) / CleanedIncrType(incr),CleanedIncrType(incr)); } #else @@ -211,7 +215,8 @@ typename internal::enable_if::value || Symbol ArithmeticSequence::type,Index> >::type seq(FirstType f, LastType l) { - return seqN(f,(l-f+fix<1>())); + return seqN(typename internal::cleanup_index_type::type(f), + Index((typename internal::cleanup_index_type::type(l)-typename internal::cleanup_index_type::type(f)+fix<1>()))); } template @@ -220,7 +225,7 @@ typename internal::enable_if::value, Symbolic::ValueExpr > > > >::type seq(const Symbolic::BaseExpr &f, LastType l) { - return seqN(f.derived(),(l-f.derived()+fix<1>())); + return seqN(f.derived(),(typename internal::cleanup_index_type::type(l)-f.derived()+fix<1>())); } template @@ -230,7 +235,7 @@ typename internal::enable_if::value, Symbolic::ValueExpr > > > >::type seq(FirstType f, const Symbolic::BaseExpr &l) { - return seqN(f,(l.derived()-f+fix<1>())); + return seqN(typename internal::cleanup_index_type::type(f),(l.derived()-typename internal::cleanup_index_type::type(f)+fix<1>())); } template @@ -248,7 +253,8 @@ typename internal::enable_if::value || Symbol seq(FirstType f, LastType l, IncrType incr) { typedef typename internal::cleanup_seq_incr::type CleanedIncrType; - return seqN(f,(l-f+CleanedIncrType(incr))/CleanedIncrType(incr), incr); + return seqN(typename internal::cleanup_index_type::type(f), + Index((typename internal::cleanup_index_type::type(l)-typename internal::cleanup_index_type::type(f)+CleanedIncrType(incr))/CleanedIncrType(incr)), incr); } template @@ -262,7 +268,7 @@ typename internal::enable_if::value, seq(const Symbolic::BaseExpr &f, LastType l, IncrType incr) { typedef typename internal::cleanup_seq_incr::type CleanedIncrType; - return seqN(f.derived(),(l-f.derived()+CleanedIncrType(incr))/CleanedIncrType(incr), incr); + return seqN(f.derived(),(typename internal::cleanup_index_type::type(l)-f.derived()+CleanedIncrType(incr))/CleanedIncrType(incr), incr); } template @@ -275,7 +281,8 @@ typename internal::enable_if::value, seq(FirstType f, const Symbolic::BaseExpr &l, IncrType incr) { typedef typename internal::cleanup_seq_incr::type CleanedIncrType; - return seqN(f,(l.derived()-f+CleanedIncrType(incr))/CleanedIncrType(incr), incr); + return seqN(typename internal::cleanup_index_type::type(f), + (l.derived()-typename internal::cleanup_index_type::type(f)+CleanedIncrType(incr))/CleanedIncrType(incr), incr); } template diff --git a/Eigen/src/Core/util/IntegralConstant.h b/Eigen/src/Core/util/IntegralConstant.h index 354aa8c4c..178e4893c 100644 --- a/Eigen/src/Core/util/IntegralConstant.h +++ b/Eigen/src/Core/util/IntegralConstant.h @@ -28,6 +28,10 @@ template struct fix_t { } fix_t<-N> operator-() const { return fix_t<-N>(); } + template + fix_t operator+(fix_t) const { return fix_t(); } + template + fix_t operator-(fix_t) const { return fix_t(); } #if EIGEN_HAS_CXX14 // Needed in C++14 to allow fix(): diff --git a/Eigen/src/Core/util/SymbolicIndex.h b/Eigen/src/Core/util/SymbolicIndex.h index 5e9465db8..62058760b 100644 --- a/Eigen/src/Core/util/SymbolicIndex.h +++ b/Eigen/src/Core/util/SymbolicIndex.h @@ -163,6 +163,13 @@ struct is_symbolic { enum { value = internal::is_convertible >::value }; }; +// Specialization for functions, because is_convertible fails in this case. +// Useful in c++98/11 mode when testing is_symbolic)> +template +struct is_symbolic { + enum { value = false }; +}; + /** Represents the actual value of a symbol identified by its tag * * It is the return type of SymbolValue::operator=, and most of the time this is only way it is used. diff --git a/test/indexed_view.cpp b/test/indexed_view.cpp index 751f98344..e70a9c616 100644 --- a/test/indexed_view.cpp +++ b/test/indexed_view.cpp @@ -55,8 +55,7 @@ is_same_eq(const T1& a, const T2& b) } template -typename internal::enable_if::value,bool>::type -is_same_seq_type(const T1& a, const T2& b) +bool is_same_seq(const T1& a, const T2& b) { bool ok = a.first()==b.first() && a.size() == b.size() && Index(a.incrObject())==Index(b.incrObject());; if(!ok) @@ -67,6 +66,15 @@ is_same_seq_type(const T1& a, const T2& b) return ok; } +template +typename internal::enable_if::value,bool>::type +is_same_seq_type(const T1& a, const T2& b) +{ + return is_same_seq(a,b); +} + + + #define VERIFY_EQ_INT(A,B) VERIFY_IS_APPROX(int(A),int(B)) void check_indexed_view() @@ -193,6 +201,14 @@ void check_indexed_view() VERIFY( is_same_seq_type( seqN(2,fix(5),3), seqN(2,5,fix(3)) ) ); VERIFY( is_same_seq_type( seqN(2,fix<5>(5),fix<-2>), seqN(2,fix<5>,fix<-2>()) ) ); + VERIFY( is_same_seq_type( seq(2,fix<5>), seqN(2,4) ) ); +#if EIGEN_HAS_CXX11 + VERIFY( is_same_seq_type( seq(fix<2>,fix<5>), seqN(fix<2>,fix<4>) ) ); +#else + // sorry, no compile-time size recovery in c++98/03 + VERIFY( is_same_seq( seq(fix<2>,fix<5>), seqN(fix<2>,fix<4>) ) ); +#endif + VERIFY( (A(seqN(2,fix<5>), 5)).RowsAtCompileTime == 5); VERIFY( (A(4, all)).ColsAtCompileTime == Dynamic); VERIFY( (A(4, all)).RowsAtCompileTime == 1);