diff --git a/Eigen/src/Core/ArithmeticSequence.h b/Eigen/src/Core/ArithmeticSequence.h index 2ad4c0906..0f9c72e2e 100644 --- a/Eigen/src/Core/ArithmeticSequence.h +++ b/Eigen/src/Core/ArithmeticSequence.h @@ -12,10 +12,69 @@ namespace Eigen { +namespace internal { + +#if !EIGEN_HAS_CXX11 +template struct aseq_negate {}; + +template<> struct aseq_negate { + typedef Index type; +}; + +template struct aseq_negate > { + typedef fix_t<-N> type; +}; + +// Compilation error in the following case: +template<> struct aseq_negate > {}; + +template::value, + bool SizeIsSymbolic =Symbolic::is_symbolic::value> +struct aseq_reverse_first_type { + typedef Index type; +}; + +template +struct aseq_reverse_first_type { + typedef Symbolic::AddExpr, + Symbolic::ValueExpr> + > type; +}; + +template +struct aseq_reverse_first_type { + typedef Symbolic::AddExpr type; +}; + +template +struct aseq_reverse_first_type { + typedef Symbolic::AddExpr,Symbolic::ValueExpr>, + Symbolic::ValueExpr> type; +}; +#endif + +// Helper to cleanup the type of the increment: +template struct cleanup_seq_incr { + typedef typename cleanup_index_type::type type; +}; + +} + //-------------------------------------------------------------------------------- // seq(first,last,incr) and seqN(first,size,incr) //-------------------------------------------------------------------------------- +template > +class ArithmeticSequence; + +template +ArithmeticSequence::type, + typename internal::cleanup_index_type::type, + typename internal::cleanup_seq_incr::type > +seqN(FirstType first, SizeType size, IncrType incr); + /** \class ArithmeticSequence * \ingroup Core_Module * @@ -35,10 +94,9 @@ namespace Eigen { * * \sa Eigen::seq, Eigen::seqN, DenseBase::operator()(const RowIndices&, const ColIndices&), class IndexedView */ -template > +template class ArithmeticSequence { - public: ArithmeticSequence(FirstType first, SizeType size) : m_first(first), m_size(size) {} ArithmeticSequence(FirstType first, SizeType size, IncrType incr) : m_first(first), m_size(size), m_incr(incr) {} @@ -65,17 +123,25 @@ protected: FirstType m_first; SizeType m_size; IncrType m_incr; + +public: + +#if EIGEN_HAS_CXX11 + auto reverse() const -> decltype(Eigen::seqN(m_first+(m_size-1)*Index(m_incr),m_size,-m_incr)) { + return seqN(m_first+(m_size-1)*Index(m_incr),m_size,-m_incr); + } +#else +protected: + typedef typename internal::aseq_negate::type ReverseIncrType; + typedef typename internal::aseq_reverse_first_type::type ReverseFirstType; +public: + ArithmeticSequence + reverse() const { + return seqN(m_first+(m_size-1)*Index(m_incr),m_size,-m_incr); + } +#endif }; -namespace internal { - -// Helper to cleanup the type of the increment: -template struct cleanup_seq_incr { - typedef typename cleanup_index_type::type type; -}; - -} - /** \returns an ArithmeticSequence starting at \a first, of length \a size, and increment \a incr * * \sa seqN(FirstType,SizeType), seq(FirstType,LastType,IncrType) */ diff --git a/Eigen/src/Core/util/IntegralConstant.h b/Eigen/src/Core/util/IntegralConstant.h index 2402baeec..354aa8c4c 100644 --- a/Eigen/src/Core/util/IntegralConstant.h +++ b/Eigen/src/Core/util/IntegralConstant.h @@ -27,6 +27,8 @@ template struct fix_t { eigen_internal_assert(int(other)==N); } + fix_t<-N> operator-() const { return fix_t<-N>(); } + #if EIGEN_HAS_CXX14 // Needed in C++14 to allow fix(): fix_t operator() () const { return *this; } diff --git a/test/indexed_view.cpp b/test/indexed_view.cpp index 47c454976..f8b3838a4 100644 --- a/test/indexed_view.cpp +++ b/test/indexed_view.cpp @@ -58,7 +58,13 @@ template typename internal::enable_if::value,bool>::type is_same_seq_type(const T1& a, const T2& b) { - return a.size() == b.size() && a.first()==b.first() && Index(a.incrObject())==Index(b.incrObject()); + bool ok = a.first()==b.first() && a.size() == b.size() && Index(a.incrObject())==Index(b.incrObject());; + if(!ok) + { + std::cerr << "seqN(" << a.first() << ", " << a.size() << ", " << Index(a.incrObject()) << ") != "; + std::cerr << "seqN(" << b.first() << ", " << b.size() << ", " << Index(b.incrObject()) << ")\n"; + } + return ok; } #define VERIFY_EQ_INT(A,B) VERIFY_IS_APPROX(int(A),int(B)) @@ -187,7 +193,6 @@ 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( (A(seqN(2,fix<5>), 5)).RowsAtCompileTime == 5); VERIFY( (A(4, all)).ColsAtCompileTime == Dynamic); VERIFY( (A(4, all)).RowsAtCompileTime == 1); @@ -201,6 +206,8 @@ void check_indexed_view() VERIFY_EQ_INT( (A(eii, eii)).InnerStrideAtCompileTime, 0); VERIFY_EQ_INT( (A(eii, eii)).OuterStrideAtCompileTime, 0); + VERIFY_IS_APPROX( A(seq(n-1,2,-2), seqN(n-1-6,3,-1)), A(seq(last,2,fix<-2>), seqN(last-6,3,fix<-1>)) ); + VERIFY_IS_APPROX( A(seq(n-1,2,-2), seqN(n-1-6,4)), A(seq(last,2,-2), seqN(last-6,4)) ); VERIFY_IS_APPROX( A(seq(n-1-6,n-1-2), seqN(n-1-6,4)), A(seq(last-6,last-2), seqN(6+last-6-6,4)) ); VERIFY_IS_APPROX( A(seq((n-1)/2,(n)/2+3), seqN(2,4)), A(seq(last/2,(last+1)/2+3), seqN(last+2-last,4)) ); @@ -218,7 +225,6 @@ void check_indexed_view() VERIFY_IS_APPROX( a(a.size()-2), a(last-1) ); VERIFY_IS_APPROX( a(a.size()/2), a((last+1)/2) ); - // Check fall-back to Block { VERIFY( is_same_eq(A.col(0), A(all,0)) ); @@ -251,6 +257,16 @@ void check_indexed_view() A1(seq(6,3,-1),range25) = A2; VERIFY_IS_APPROX( A1.block(3,2,4,4), A2 ); + // check reverse + { + VERIFY( is_same_seq_type( seq(3,7).reverse(), seqN(7,5,fix<-1>) ) ); + VERIFY( is_same_seq_type( seq(7,3,fix<-2>).reverse(), seqN(3,3,fix<2>) ) ); + VERIFY_IS_APPROX( a(seqN(2,last/2).reverse()), a(seqN(2+(last/2-1)*1,last/2,fix<-1>)) ); + VERIFY_IS_APPROX( a(seqN(last/2,fix<4>).reverse()),a(seqN(last/2,fix<4>)).reverse() ); + VERIFY_IS_APPROX( A(seq(last-5,last-1,2).reverse(), seqN(last-3,3,fix<-2>).reverse()), + A(seq(last-5,last-1,2), seqN(last-3,3,fix<-2>)).reverse() ); + } + #if EIGEN_HAS_CXX11 VERIFY( (A(all, std::array{{1,3,2,4}})).ColsAtCompileTime == 4);