From a875167d99cffa76a662de5475627d60238f0f36 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Fri, 6 Jan 2017 15:54:55 +0100 Subject: [PATCH] Propagate compile-time increment and strides. Had to introduce a UndefinedIncr constant for non structured list of indices. --- Eigen/src/Core/ArithmeticSequence.h | 27 ++++++++++++++++++++-- Eigen/src/Core/IndexedView.h | 35 +++++++++++++---------------- Eigen/src/Core/util/Constants.h | 4 ++++ test/indexed_view.cpp | 27 +++++++++++++++++++++- 4 files changed, 71 insertions(+), 22 deletions(-) diff --git a/Eigen/src/Core/ArithmeticSequence.h b/Eigen/src/Core/ArithmeticSequence.h index 06b6b53eb..1585c1dbf 100644 --- a/Eigen/src/Core/ArithmeticSequence.h +++ b/Eigen/src/Core/ArithmeticSequence.h @@ -160,7 +160,7 @@ span(FirstType first, SizeType size) { namespace internal { template struct get_compile_time_size { - enum { value = -1 }; + enum { value = Dynamic }; }; template struct get_compile_time_size::type> { @@ -173,6 +173,21 @@ template struct get_compile_time_size struct get_compile_time_incr { + enum { value = UndefinedIncr }; +}; + +template +struct get_compile_time_incr > { + enum { value = get_compile_time::value }; +}; + +template +struct get_compile_time_incr > { + enum { value = get_compile_time::value }; +}; + + // MakeIndexing/make_indexing turn an arbitrary object of type T into something usable by MatrixSlice template struct MakeIndexing { @@ -180,7 +195,7 @@ struct MakeIndexing { }; template -const T& make_indexing(const T& x, Index size) { return x; } +const T& make_indexing(const T& x, Index /*size*/) { return x; } struct IntAsArray { enum { @@ -192,6 +207,10 @@ struct IntAsArray { Index m_value; }; +template<> struct get_compile_time_incr { + enum { value = 1 }; // 1 or 0 ?? +}; + // Turn a single index into something that looks like an array (i.e., that exposes a .size(), and operatro[](int) methods) template struct MakeIndexing::value>::type> { @@ -254,6 +273,10 @@ template struct get_compile_time_size { enum { value = XprSize }; }; +template<> struct get_compile_time_incr { + enum { value = 1 }; +}; + } // end namespace internal } // end namespace Eigen diff --git a/Eigen/src/Core/IndexedView.h b/Eigen/src/Core/IndexedView.h index bc1eff8f9..26c048584 100644 --- a/Eigen/src/Core/IndexedView.h +++ b/Eigen/src/Core/IndexedView.h @@ -29,12 +29,24 @@ struct traits > : (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0 : XprTypeIsRowMajor, + RowIncr = get_compile_time_incr::value, + ColIncr = get_compile_time_incr::value, + InnerIncr = IsRowMajor ? ColIncr : RowIncr, + OuterIncr = IsRowMajor ? RowIncr : ColIncr, + + HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor), + XprInnerStride = HasSameStorageOrderAsXprType ? int(inner_stride_at_compile_time::ret) : int(outer_stride_at_compile_time::ret), + XprOuterstride = HasSameStorageOrderAsXprType ? int(outer_stride_at_compile_time::ret) : int(inner_stride_at_compile_time::ret), + + InnerStrideAtCompileTime = InnerIncr<0 || InnerIncr==DynamicIndex || XprInnerStride==Dynamic ? Dynamic : XprInnerStride * InnerIncr, + OuterStrideAtCompileTime = OuterIncr<0 || OuterIncr==DynamicIndex || XprOuterstride==Dynamic ? Dynamic : XprOuterstride * OuterIncr, + + // FIXME we deal with compile-time strides if and only if we have DirectAccessBit flag, + // but this is too strict regarding negative strides... + DirectAccessMask = (InnerIncr!=UndefinedIncr && OuterIncr!=UndefinedIncr && InnerIncr>=0 && OuterIncr>=0) ? DirectAccessBit : 0, FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0, FlagsLvalueBit = is_lvalue::value ? LvalueBit : 0, - Flags = (traits::Flags & HereditaryBits) | FlagsLvalueBit | FlagsRowMajorBit, - //MatrixTypeInnerStride = inner_stride_at_compile_time::ret, - InnerStrideAtCompileTime = int(Dynamic), - OuterStrideAtCompileTime = int(Dynamic) + Flags = (traits::Flags & (HereditaryBits | DirectAccessMask)) | FlagsLvalueBit | FlagsRowMajorBit }; }; @@ -72,21 +84,6 @@ public: const RowIndices& rowIndices() const { return m_rowIndices; } const ColIndices& colIndices() const { return m_colIndices; } -// std::pair index(Index i, Index j) const { -// return std::pair(m_rowIndices[i], m_colIndices[j]); -// } -// -// void print() const { -// for(Index i=0; i k = index(i,j); -// std::cout << '(' << k.first << ',' << k.second << ") "; -// } -// std::cout << '\n'; -// } -// } protected: MatrixTypeNested m_xpr; RowIndices m_rowIndices; diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h index 7587d6842..5d37e5d04 100644 --- a/Eigen/src/Core/util/Constants.h +++ b/Eigen/src/Core/util/Constants.h @@ -25,6 +25,10 @@ const int Dynamic = -1; */ const int DynamicIndex = 0xffffff; +/** This value means that the increment to go from one value to another in a sequence is not constant for each step. + */ +const int UndefinedIncr = 0xfffffe; + /** This value means +Infinity; it is currently used only as the p parameter to MatrixBase::lpNorm(). * The value Infinity there means the L-infinity norm. */ diff --git a/test/indexed_view.cpp b/test/indexed_view.cpp index 5d8ce16ee..bc69adf13 100644 --- a/test/indexed_view.cpp +++ b/test/indexed_view.cpp @@ -27,7 +27,8 @@ IndexPair decode(Index ij) { template bool match(const T& xpr, std::string ref, std::string str_xpr = "") { - std::cout << str_xpr << "\n" << xpr << "\n\n"; + EIGEN_UNUSED_VARIABLE(str_xpr); + //std::cout << str_xpr << "\n" << xpr << "\n\n"; std::stringstream str; str << xpr; return str.str() == ref; @@ -102,8 +103,28 @@ void check_indexed_view() ); Array44i B; + B.setRandom(); VERIFY( (A(span(2,5), 5)).ColsAtCompileTime == 1); VERIFY( (A(span(2,5), 5)).RowsAtCompileTime == Dynamic); + VERIFY_IS_EQUAL( (A(span(2,5), 5)).InnerStrideAtCompileTime , A.InnerStrideAtCompileTime); + VERIFY_IS_EQUAL( (A(span(2,5), 5)).OuterStrideAtCompileTime , A.col(5).OuterStrideAtCompileTime); + + VERIFY_IS_EQUAL( (A(5,span(2,5))).InnerStrideAtCompileTime , A.row(5).InnerStrideAtCompileTime); + VERIFY_IS_EQUAL( (A(5,span(2,5))).OuterStrideAtCompileTime , A.row(5).OuterStrideAtCompileTime); + VERIFY_IS_EQUAL( (B(1,span(1,2))).InnerStrideAtCompileTime , B.row(1).InnerStrideAtCompileTime); + VERIFY_IS_EQUAL( (B(1,span(1,2))).OuterStrideAtCompileTime , B.row(1).OuterStrideAtCompileTime); + + VERIFY_IS_EQUAL( (A(span(2,5), range(1,3))).InnerStrideAtCompileTime , A.InnerStrideAtCompileTime); + VERIFY_IS_EQUAL( (A(span(2,5), range(1,3))).OuterStrideAtCompileTime , A.OuterStrideAtCompileTime); + VERIFY_IS_EQUAL( (B(span(1,2), range(1,3))).InnerStrideAtCompileTime , B.InnerStrideAtCompileTime); + VERIFY_IS_EQUAL( (B(span(1,2), range(1,3))).OuterStrideAtCompileTime , B.OuterStrideAtCompileTime); + VERIFY_IS_EQUAL( (A(span(2,5,2), range(1,3,2))).InnerStrideAtCompileTime , Dynamic); + VERIFY_IS_EQUAL( (A(span(2,5,2), range(1,3,2))).OuterStrideAtCompileTime , Dynamic); + VERIFY_IS_EQUAL( (A(span(2,5,fix<2>), range(1,3,fix<3>))).InnerStrideAtCompileTime , 2); + VERIFY_IS_EQUAL( (A(span(2,5,fix<2>), range(1,3,fix<3>))).OuterStrideAtCompileTime , Dynamic); + VERIFY_IS_EQUAL( (B(span(1,2,fix<2>), range(1,3,fix<3>))).InnerStrideAtCompileTime , 2); + VERIFY_IS_EQUAL( (B(span(1,2,fix<2>), range(1,3,fix<3>))).OuterStrideAtCompileTime , 3*4); + VERIFY( (A(span(2,fix<5>), 5)).RowsAtCompileTime == 5); VERIFY( (A(4, all)).ColsAtCompileTime == Dynamic); VERIFY( (A(4, all)).RowsAtCompileTime == 1); @@ -113,6 +134,10 @@ void check_indexed_view() VERIFY( (B(all,1)).RowsAtCompileTime == 4); VERIFY( (A(all, eii)).ColsAtCompileTime == eii.SizeAtCompileTime); + VERIFY_IS_EQUAL( (A(eii, eii)).Flags&DirectAccessBit, (unsigned int)(0)); + VERIFY_IS_EQUAL( (A(eii, eii)).InnerStrideAtCompileTime, 0); + VERIFY_IS_EQUAL( (A(eii, eii)).OuterStrideAtCompileTime, 0); + #if EIGEN_HAS_CXX11 VERIFY( (A(all, std::array{{1,3,2,4}})).ColsAtCompileTime == 4);