diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h index dad2af802afe600dbfba377adf1851bfe433aeff..8ddbaf6d6a2e25e5d8f490f58a020083f8f16237 100644 --- a/Eigen/src/Core/Block.h +++ b/Eigen/src/Core/Block.h @@ -16,9 +16,10 @@ namespace Eigen { namespace internal { -template -struct traits > : traits +template +struct traits > : traits { + typedef XprType_ XprType; typedef typename traits::Scalar Scalar; typedef typename traits::StorageKind StorageKind; typedef typename traits::XprKind XprKind; @@ -52,12 +53,13 @@ struct traits > : traits::value ? LvalueBit : 0, FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0, - Flags = (traits::Flags & (DirectAccessBit | (InnerPanel?CompressedAccessBit:0))) | FlagsLvalueBit | FlagsRowMajorBit, + Flags = (traits::Flags & (DirectAccessBit | (InnerPanel_?CompressedAccessBit:0))) | FlagsLvalueBit | FlagsRowMajorBit, // FIXME DirectAccessBit should not be handled by expressions // // Alignment is needed by MapBase's assertions // We can sefely set it to false here. Internal alignment errors will be detected by an eigen_internal_assert in the respective evaluator - Alignment = 0 + Alignment = 0, + InnerPanel = InnerPanel_ ? 1 : 0 }; }; @@ -106,6 +108,7 @@ template class : public BlockImpl::StorageKind> { typedef BlockImpl::StorageKind> Impl; + using BlockHelper = internal::block_xpr_helper; public: //typedef typename Impl::Base Base; typedef Impl Base; @@ -148,6 +151,20 @@ template class eigen_assert(startRow >= 0 && blockRows >= 0 && startRow <= xpr.rows() - blockRows && startCol >= 0 && blockCols >= 0 && startCol <= xpr.cols() - blockCols); } + + using ConstUnwindReturnType = Block; + using UnwindReturnType = Block; + + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ConstUnwindReturnType unwind() const { + return ConstUnwindReturnType(BlockHelper::base(*this), BlockHelper::row(*this, 0), BlockHelper::col(*this, 0), + this->rows(), this->cols()); + } + + template ::value>> + EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE UnwindReturnType unwind() { + return UnwindReturnType(BlockHelper::base(*this), BlockHelper::row(*this, 0), BlockHelper::col(*this, 0), + this->rows(), this->cols()); + } }; // The generic default implementation for dense block simplu forward to the internal::BlockImpl_dense diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h index d8ac1b3406960cfafe65de2811326bc548cae03c..13ccae8ff907ece06c1dd01ee594ebae7bc0e3c8 100644 --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -808,6 +808,67 @@ std::string demangle_flags(int f) } #endif +template +struct is_block_xpr : std::false_type {}; + +template +struct is_block_xpr> : std::true_type {}; + +template +struct is_block_xpr> : std::true_type {}; + +// Helper utility for constructing non-recursive block expressions. +template +struct block_xpr_helper { + using BaseType = XprType; + + // For regular block expressions, simply forward along the InnerPanel argument, + // which is set when calling row/column expressions. + static constexpr bool is_inner_panel(bool inner_panel) { return inner_panel; }; + + // Only enable non-const base function if XprType is not const (otherwise we get a duplicate definition). + template::value>> + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BaseType& base(XprType& xpr) { return xpr; } + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE const BaseType& base(const XprType& xpr) { return xpr; } + static constexpr EIGEN_ALWAYS_INLINE Index row(const XprType& /*xpr*/, Index r) { return r; } + static constexpr EIGEN_ALWAYS_INLINE Index col(const XprType& /*xpr*/, Index c) { return c; } +}; + +template +struct block_xpr_helper> { + using BlockXprType = Block; + // Recursive helper in case of explicit block-of-block expression. + using NestedXprHelper = block_xpr_helper; + using BaseType = typename NestedXprHelper::BaseType; + + // For block-of-block expressions, we need to combine the InnerPannel trait + // with that of the block subexpression. + static constexpr bool is_inner_panel(bool inner_panel) { return InnerPanel && inner_panel; } + + // Only enable non-const base function if XprType is not const (otherwise we get a duplicates definition). + template::value>> + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE BaseType& base(BlockXprType& xpr) { return NestedXprHelper::base(xpr.nestedExpression()); } + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE const BaseType& base(const BlockXprType& xpr) { return NestedXprHelper::base(xpr.nestedExpression()); } + static constexpr EIGEN_ALWAYS_INLINE Index row(const BlockXprType& xpr, Index r) { return xpr.startRow() + NestedXprHelper::row(xpr.nestedExpression(), r); } + static constexpr EIGEN_ALWAYS_INLINE Index col(const BlockXprType& xpr, Index c) { return xpr.startCol() + NestedXprHelper::col(xpr.nestedExpression(), c); } +}; + +template +struct block_xpr_helper> { + using BlockXprType = const Block; + // Recursive helper in case of explicit block-of-block expression. + using NestedXprHelper = block_xpr_helper; + using BaseType = typename NestedXprHelper::BaseType; + + // For block-of-block expressions, we need to combine the InnerPannel trait + // with that of the block subexpression. + static constexpr bool is_inner_panel(bool inner_panel) { return InnerPanel && inner_panel; } + + static EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE const BaseType& base(const BlockXprType& xpr) { return NestedXprHelper::base(xpr.nestedExpression()); } + static constexpr EIGEN_ALWAYS_INLINE Index row(const BlockXprType& xpr, Index r) { return xpr.startRow() + NestedXprHelper::row(xpr.nestedExpression(), r); } + static constexpr EIGEN_ALWAYS_INLINE Index col(const BlockXprType& xpr, Index c) { return xpr.startCol() + NestedXprHelper::col(xpr.nestedExpression(), c); } +}; + } // end namespace internal diff --git a/Eigen/src/Geometry/Quaternion.h b/Eigen/src/Geometry/Quaternion.h index 3413a5197337e5d15b77e8c1212039c34f9ba8c9..6bd46e7c7fff168db5a5cc3bc63cd74038d5461a 100644 --- a/Eigen/src/Geometry/Quaternion.h +++ b/Eigen/src/Geometry/Quaternion.h @@ -48,6 +48,8 @@ class QuaternionBase : public RotationBase typedef typename Coefficients::CoeffReturnType CoeffReturnType; typedef std::conditional_t::Flags&LvalueBit), Scalar&, CoeffReturnType> NonConstCoeffReturnType; + typedef typename Coefficients::template FixedSegmentReturnType<3>::Type CoefficientsVec; + typedef typename Coefficients::template ConstFixedSegmentReturnType<3>::Type ConstCoefficientsVec; enum { @@ -83,16 +85,16 @@ class QuaternionBase : public RotationBase EIGEN_DEVICE_FUNC inline NonConstCoeffReturnType w() { return this->derived().coeffs().w(); } /** \returns a read-only vector expression of the imaginary part (x,y,z) */ - EIGEN_DEVICE_FUNC inline const VectorBlock vec() const { return coeffs().template head<3>(); } + EIGEN_DEVICE_FUNC inline ConstCoefficientsVec vec() const { return coeffs().template head<3>(); } /** \returns a vector expression of the imaginary part (x,y,z) */ - EIGEN_DEVICE_FUNC inline VectorBlock vec() { return coeffs().template head<3>(); } + EIGEN_DEVICE_FUNC inline CoefficientsVec vec() { return coeffs().template head<3>(); } /** \returns a read-only vector expression of the coefficients (x,y,z,w) */ - EIGEN_DEVICE_FUNC inline const typename internal::traits::Coefficients& coeffs() const { return derived().coeffs(); } + EIGEN_DEVICE_FUNC inline const Coefficients& coeffs() const { return derived().coeffs(); } /** \returns a vector expression of the coefficients (x,y,z,w) */ - EIGEN_DEVICE_FUNC inline typename internal::traits::Coefficients& coeffs() { return derived().coeffs(); } + EIGEN_DEVICE_FUNC inline Coefficients& coeffs() { return derived().coeffs(); } EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE QuaternionBase& operator=(const QuaternionBase& other); template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Derived& operator=(const QuaternionBase& other); diff --git a/Eigen/src/Geometry/Transform.h b/Eigen/src/Geometry/Transform.h index fd0ae7e6c1dab3d04a304eb1338f0640ba251f6b..ddf7c2a931f216fa9c89ed9348bc0fe01b81caff 100644 --- a/Eigen/src/Geometry/Transform.h +++ b/Eigen/src/Geometry/Transform.h @@ -225,23 +225,23 @@ public: /** type of the matrix used to represent the linear part of the transformation */ typedef Matrix LinearMatrixType; /** type of read/write reference to the linear part of the transformation */ - typedef Block LinearPart; + typedef typename MatrixType::template FixedBlockXpr::Type LinearPart; /** type of read reference to the linear part of the transformation */ - typedef const Block ConstLinearPart; + typedef typename MatrixType::template ConstFixedBlockXpr::Type ConstLinearPart; /** type of read/write reference to the affine part of the transformation */ typedef std::conditional_t > AffinePart; + typename MatrixType::template FixedBlockXpr::Type > AffinePart; /** type of read reference to the affine part of the transformation */ typedef std::conditional_t > ConstAffinePart; + typename MatrixType::template ConstFixedBlockXpr::Type > ConstAffinePart; /** type of a vector */ typedef Matrix VectorType; /** type of a read/write reference to the translation part of the rotation */ - typedef Block::Flags & RowMajorBit)> TranslationPart; + typedef typename MatrixType::template FixedBlockXpr::Flags & RowMajorBit)>::Type TranslationPart; /** type of a read reference to the translation part of the rotation */ - typedef const Block::Flags & RowMajorBit)> ConstTranslationPart; + typedef typename MatrixType::template ConstFixedBlockXpr::Flags & RowMajorBit)>::Type ConstTranslationPart; /** corresponding translation type */ typedef Translation TranslationType; @@ -658,26 +658,26 @@ public: * \returns the Dim x Dim linear part if the transformation is affine, * and the HDim x Dim part for projective transformations. */ - EIGEN_DEVICE_FUNC inline Block linearExt() + EIGEN_DEVICE_FUNC inline typename MatrixType::template FixedBlockXpr::Type linearExt() { return m_matrix.template block(0,0); } /** \internal * \returns the Dim x Dim linear part if the transformation is affine, * and the HDim x Dim part for projective transformations. */ - EIGEN_DEVICE_FUNC inline const Block linearExt() const + EIGEN_DEVICE_FUNC inline typename MatrixType::template ConstFixedBlockXpr::Type linearExt() const { return m_matrix.template block(0,0); } /** \internal * \returns the translation part if the transformation is affine, * and the last column for projective transformations. */ - EIGEN_DEVICE_FUNC inline Block translationExt() + EIGEN_DEVICE_FUNC inline typename MatrixType::template FixedBlockXpr::Type translationExt() { return m_matrix.template block(0,Dim); } /** \internal * \returns the translation part if the transformation is affine, * and the last column for projective transformations. */ - EIGEN_DEVICE_FUNC inline const Block translationExt() const + EIGEN_DEVICE_FUNC inline typename MatrixType::template ConstFixedBlockXpr::Type translationExt() const { return m_matrix.template block(0,Dim); } @@ -1362,7 +1362,7 @@ struct transform_right_product_impl< TransformType, MatrixType, 1, RhsCols> { EIGEN_STATIC_ASSERT(OtherRows==HDim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES); - typedef Block TopLeftLhs; + typedef typename ResultType::template FixedBlockXpr::Type TopLeftLhs; ResultType res(other.rows(),other.cols()); TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() = T.affine() * other; @@ -1388,7 +1388,7 @@ struct transform_right_product_impl< TransformType, MatrixType, 2, RhsCols> { EIGEN_STATIC_ASSERT(OtherRows==Dim, YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES); - typedef Block TopLeftLhs; + typedef typename ResultType::template FixedBlockXpr::Type TopLeftLhs; ResultType res(Replicate(T.translation(),1,other.cols())); TopLeftLhs(res, 0, 0, Dim, other.cols()).noalias() += T.linear() * other; diff --git a/Eigen/src/Householder/HouseholderSequence.h b/Eigen/src/Householder/HouseholderSequence.h index 41fef641d5b541b1c00c6b9a5091fb41be14c81f..4cdc1c11fb7a620d18a272a7e66bd9aae7fe6552 100644 --- a/Eigen/src/Householder/HouseholderSequence.h +++ b/Eigen/src/Householder/HouseholderSequence.h @@ -87,24 +87,24 @@ struct evaluator_traits > template struct hseq_side_dependent_impl { - typedef Block EssentialVectorType; + typedef typename VectorsType::template ConstFixedBlockXpr::Type EssentialVectorType; typedef HouseholderSequence HouseholderSequenceType; static EIGEN_DEVICE_FUNC inline const EssentialVectorType essentialVector(const HouseholderSequenceType& h, Index k) { Index start = k+1+h.m_shift; - return Block(h.m_vectors, start, k, h.rows()-start, 1); + return h.m_vectors.template block(start, k, h.rows()-start, 1); } }; template struct hseq_side_dependent_impl { - typedef Transpose > EssentialVectorType; + typedef Transpose::Type > EssentialVectorType; typedef HouseholderSequence HouseholderSequenceType; static inline const EssentialVectorType essentialVector(const HouseholderSequenceType& h, Index k) { Index start = k+1+h.m_shift; - return Block(h.m_vectors, k, start, 1, h.rows()-start).transpose(); + return h.m_vectors.template block<1, Dynamic>(k, start, 1, h.rows()-start).transpose(); } }; @@ -384,18 +384,19 @@ template class HouseholderS Index bs = end-k; Index start = k + m_shift; - typedef Block,Dynamic,Dynamic> SubVectorsType; - SubVectorsType sub_vecs1(m_vectors.const_cast_derived(), Side==OnTheRight ? k : start, - Side==OnTheRight ? start : k, - Side==OnTheRight ? bs : m_vectors.rows()-start, - Side==OnTheRight ? m_vectors.cols()-start : bs); + typedef typename internal::remove_all_t::BlockXpr SubVectorsType; + SubVectorsType sub_vecs1 = m_vectors.const_cast_derived().block( + Side==OnTheRight ? k : start, + Side==OnTheRight ? start : k, + Side==OnTheRight ? bs : m_vectors.rows()-start, + Side==OnTheRight ? m_vectors.cols()-start : bs); std::conditional_t, SubVectorsType&> sub_vecs(sub_vecs1); Index dstRows = rows()-m_shift-k; if (inputIsIdentity) { - Block sub_dst = dst.bottomRightCorner(dstRows, dstRows); + auto sub_dst = dst.bottomRightCorner(dstRows, dstRows); apply_block_householder_on_the_left(sub_dst, sub_vecs, m_coeffs.segment(k, bs), !m_reverse); } else @@ -415,7 +416,7 @@ template class HouseholderS if (inputIsIdentity) { - Block sub_dst = dst.bottomRightCorner(dstRows, dstRows); + auto sub_dst = dst.bottomRightCorner(dstRows, dstRows); sub_dst.applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), workspace.data()); } else diff --git a/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h b/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h index 49829d018fae14fef540a564e8bb76acf70fc4f8..81c176c4e8030ed7662f310301d3d73c49468592 100644 --- a/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h +++ b/Eigen/src/IterativeLinearSolvers/IterativeSolverBase.h @@ -379,8 +379,8 @@ public: ComputationInfo global_info = Success; for(Index k=0; k; +using BlockXprBase = typename BlockXprHelper::BaseType; + /// \internal expression type of a column */ -typedef Block::RowsAtCompileTime, 1, !IsRowMajor> ColXpr; -typedef const Block::RowsAtCompileTime, 1, !IsRowMajor> ConstColXpr; +typedef Block::RowsAtCompileTime, 1, BlockXprHelper::is_inner_panel(!IsRowMajor)> ColXpr; +typedef const Block::RowsAtCompileTime, 1, BlockXprHelper::is_inner_panel(!IsRowMajor)> ConstColXpr; /// \internal expression type of a row */ -typedef Block::ColsAtCompileTime, IsRowMajor> RowXpr; -typedef const Block::ColsAtCompileTime, IsRowMajor> ConstRowXpr; +typedef Block::ColsAtCompileTime, BlockXprHelper::is_inner_panel(IsRowMajor)> RowXpr; +typedef const Block::ColsAtCompileTime, BlockXprHelper::is_inner_panel(IsRowMajor)> ConstRowXpr; /// \internal expression type of a block of whole columns */ -typedef Block::RowsAtCompileTime, Dynamic, !IsRowMajor> ColsBlockXpr; -typedef const Block::RowsAtCompileTime, Dynamic, !IsRowMajor> ConstColsBlockXpr; +typedef Block::RowsAtCompileTime, Dynamic, BlockXprHelper::is_inner_panel(!IsRowMajor)> ColsBlockXpr; +typedef const Block::RowsAtCompileTime, Dynamic, BlockXprHelper::is_inner_panel(!IsRowMajor)> ConstColsBlockXpr; /// \internal expression type of a block of whole rows */ -typedef Block::ColsAtCompileTime, IsRowMajor> RowsBlockXpr; -typedef const Block::ColsAtCompileTime, IsRowMajor> ConstRowsBlockXpr; +typedef Block::ColsAtCompileTime, BlockXprHelper::is_inner_panel(IsRowMajor)> RowsBlockXpr; +typedef const Block::ColsAtCompileTime, BlockXprHelper::is_inner_panel(IsRowMajor)> ConstRowsBlockXpr; /// \internal expression type of a block of whole columns */ -template struct NColsBlockXpr { typedef Block::RowsAtCompileTime, N, !IsRowMajor> Type; }; -template struct ConstNColsBlockXpr { typedef const Block::RowsAtCompileTime, N, !IsRowMajor> Type; }; +template struct NColsBlockXpr { typedef Block::RowsAtCompileTime, N, BlockXprHelper::is_inner_panel(!IsRowMajor)> Type; }; +template struct ConstNColsBlockXpr { typedef const Block::RowsAtCompileTime, N, BlockXprHelper::is_inner_panel(!IsRowMajor)> Type; }; /// \internal expression type of a block of whole rows */ -template struct NRowsBlockXpr { typedef Block::ColsAtCompileTime, IsRowMajor> Type; }; -template struct ConstNRowsBlockXpr { typedef const Block::ColsAtCompileTime, IsRowMajor> Type; }; +template struct NRowsBlockXpr { typedef Block::ColsAtCompileTime, BlockXprHelper::is_inner_panel(IsRowMajor)> Type; }; +template struct ConstNRowsBlockXpr { typedef const Block::ColsAtCompileTime, BlockXprHelper::is_inner_panel(IsRowMajor)> Type; }; /// \internal expression of a block */ -typedef Block BlockXpr; -typedef const Block ConstBlockXpr; +typedef Block BlockXpr; +typedef const Block ConstBlockXpr; /// \internal expression of a block of fixed sizes */ -template struct FixedBlockXpr { typedef Block Type; }; -template struct ConstFixedBlockXpr { typedef Block Type; }; - -typedef VectorBlock SegmentReturnType; -typedef const VectorBlock ConstSegmentReturnType; -template struct FixedSegmentReturnType { typedef VectorBlock Type; }; -template struct ConstFixedSegmentReturnType { typedef const VectorBlock Type; }; +template +struct FixedBlockXpr { + typedef Block::Flags & RowMajorBit) + ? Cols != Dynamic && Cols == internal::traits::ColsAtCompileTime + : Rows != Dynamic && Rows == internal::traits::RowsAtCompileTime > Type; +}; +template +struct ConstFixedBlockXpr { + typedef const Block::Flags & RowMajorBit) + ? Cols != Dynamic && Cols == internal::traits::ColsAtCompileTime + : Rows != Dynamic && Rows == internal::traits::RowsAtCompileTime > Type; +}; + +template struct FixedSegmentReturnType { + typedef Block Type; +}; +template struct ConstFixedSegmentReturnType { + typedef const Block Type; +}; +using SegmentReturnType = typename FixedSegmentReturnType::Type; +using ConstSegmentReturnType = typename ConstFixedSegmentReturnType::Type; /// \internal inner-vector -typedef Block InnerVectorReturnType; -typedef Block ConstInnerVectorReturnType; +typedef Block InnerVectorReturnType; +typedef Block ConstInnerVectorReturnType; /// \internal set of inner-vectors -typedef Block InnerVectorsReturnType; -typedef Block ConstInnerVectorsReturnType; +typedef Block InnerVectorsReturnType; +typedef Block ConstInnerVectorsReturnType; #endif // not EIGEN_PARSED_BY_DOXYGEN @@ -96,7 +117,7 @@ typename FixedBlockXpr<...,...>::Type block(Index startRow, Index startCol, NRowsType blockRows, NColsType blockCols) { return typename FixedBlockXpr::value,internal::get_fixed_value::value>::Type( - derived(), startRow, startCol, internal::get_runtime_value(blockRows), internal::get_runtime_value(blockCols)); + BlockXprHelper::base(derived()), BlockXprHelper::row(derived(), startRow), BlockXprHelper::col(derived(), startCol), internal::get_runtime_value(blockRows), internal::get_runtime_value(blockCols)); } /// This is the const version of block(Index,Index,NRowsType,NColsType) @@ -110,10 +131,95 @@ const typename ConstFixedBlockXpr<...,...>::Type block(Index startRow, Index startCol, NRowsType blockRows, NColsType blockCols) const { return typename ConstFixedBlockXpr::value,internal::get_fixed_value::value>::Type( - derived(), startRow, startCol, internal::get_runtime_value(blockRows), internal::get_runtime_value(blockCols)); + BlockXprHelper::base(derived()), BlockXprHelper::row(derived(), startRow), BlockXprHelper::col(derived(), startCol), internal::get_runtime_value(blockRows), internal::get_runtime_value(blockCols)); } +/// \returns a fixed-size expression of a block of \c *this. +/// +/// The template parameters \a NRows and \a NCols are the number of +/// rows and columns in the block. +/// +/// \param startRow the first row in the block +/// \param startCol the first column in the block +/// +/// Example: \include MatrixBase_block_int_int.cpp +/// Output: \verbinclude MatrixBase_block_int_int.out +/// +/// \note The usage of of this overload is discouraged from %Eigen 3.4, better used the generic +/// block(Index,Index,NRowsType,NColsType), here is the one-to-one equivalence: +/// \code +/// mat.template block(i,j) <--> mat.block(i,j,fix,fix) +/// \endcode +/// +/// \note since block is a templated member, the keyword template has to be used +/// if the matrix type is also a template parameter: \code m.template block<3,3>(1,1); \endcode +/// +EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL +/// +/// \sa block(Index,Index,NRowsType,NColsType), class Block +/// +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +typename FixedBlockXpr::Type block(Index startRow, Index startCol) +{ + return typename FixedBlockXpr::Type(BlockXprHelper::base(derived()), BlockXprHelper::row(derived(), startRow), BlockXprHelper::col(derived(), startCol)); +} + +/// This is the const version of block<>(Index, Index). */ +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +const typename ConstFixedBlockXpr::Type block(Index startRow, Index startCol) const +{ + return typename ConstFixedBlockXpr::Type(BlockXprHelper::base(derived()), BlockXprHelper::row(derived(), startRow), BlockXprHelper::col(derived(), startCol)); +} + +/// \returns an expression of a block of \c *this. +/// +/// \tparam NRows number of rows in block as specified at compile-time +/// \tparam NCols number of columns in block as specified at compile-time +/// \param startRow the first row in the block +/// \param startCol the first column in the block +/// \param blockRows number of rows in block as specified at run-time +/// \param blockCols number of columns in block as specified at run-time +/// +/// This function is mainly useful for blocks where the number of rows is specified at compile-time +/// and the number of columns is specified at run-time, or vice versa. The compile-time and run-time +/// information should not contradict. In other words, \a blockRows should equal \a NRows unless +/// \a NRows is \a Dynamic, and the same for the number of columns. +/// +/// Example: \include MatrixBase_template_int_int_block_int_int_int_int.cpp +/// Output: \verbinclude MatrixBase_template_int_int_block_int_int_int_int.out +/// +/// \note The usage of of this overload is discouraged from %Eigen 3.4, better used the generic +/// block(Index,Index,NRowsType,NColsType), here is the one-to-one complete equivalence: +/// \code +/// mat.template block(i,j,rows,cols) <--> mat.block(i,j,fix(rows),fix(cols)) +/// \endcode +/// If we known that, e.g., NRows==Dynamic and NCols!=Dynamic, then the equivalence becomes: +/// \code +/// mat.template block(i,j,rows,NCols) <--> mat.block(i,j,rows,fix) +/// \endcode +/// +EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL +/// +/// \sa block(Index,Index,NRowsType,NColsType), class Block +/// +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +typename FixedBlockXpr::Type block(Index startRow, Index startCol, + Index blockRows, Index blockCols) +{ + return typename FixedBlockXpr::Type(BlockXprHelper::base(derived()), BlockXprHelper::row(derived(), startRow), BlockXprHelper::col(derived(), startCol), blockRows, blockCols); +} +/// This is the const version of block<>(Index, Index, Index, Index). +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE +const typename ConstFixedBlockXpr::Type block(Index startRow, Index startCol, + Index blockRows, Index blockCols) const +{ + return typename ConstFixedBlockXpr::Type(BlockXprHelper::base(derived()), BlockXprHelper::row(derived(), startRow), BlockXprHelper::col(derived(), startCol), blockRows, blockCols); +} /// \returns a expression of a top-right corner of \c *this with either dynamic or fixed sizes. /// @@ -141,8 +247,7 @@ typename FixedBlockXpr<...,...>::Type #endif topRightCorner(NRowsType cRows, NColsType cCols) { - return typename FixedBlockXpr::value,internal::get_fixed_value::value>::Type - (derived(), 0, cols() - internal::get_runtime_value(cCols), internal::get_runtime_value(cRows), internal::get_runtime_value(cCols)); + return block(0, cols() - internal::get_runtime_value(cCols), cRows, cCols); } /// This is the const version of topRightCorner(NRowsType, NColsType). @@ -155,8 +260,7 @@ const typename ConstFixedBlockXpr<...,...>::Type #endif topRightCorner(NRowsType cRows, NColsType cCols) const { - return typename ConstFixedBlockXpr::value,internal::get_fixed_value::value>::Type - (derived(), 0, cols() - internal::get_runtime_value(cCols), internal::get_runtime_value(cRows), internal::get_runtime_value(cCols)); + return block(0, cols() - internal::get_runtime_value(cCols), cRows, cCols); } /// \returns an expression of a fixed-size top-right corner of \c *this. @@ -175,7 +279,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename FixedBlockXpr::Type topRightCorner() { - return typename FixedBlockXpr::Type(derived(), 0, cols() - CCols); + return block(0, cols() - CCols); } /// This is the const version of topRightCorner(). @@ -183,7 +287,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename ConstFixedBlockXpr::Type topRightCorner() const { - return typename ConstFixedBlockXpr::Type(derived(), 0, cols() - CCols); + return block(0, cols() - CCols); } /// \returns an expression of a top-right corner of \c *this. @@ -209,7 +313,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename FixedBlockXpr::Type topRightCorner(Index cRows, Index cCols) { - return typename FixedBlockXpr::Type(derived(), 0, cols() - cCols, cRows, cCols); + return block(0, cols() - cCols, cRows, cCols); } /// This is the const version of topRightCorner(Index, Index). @@ -217,7 +321,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename ConstFixedBlockXpr::Type topRightCorner(Index cRows, Index cCols) const { - return typename ConstFixedBlockXpr::Type(derived(), 0, cols() - cCols, cRows, cCols); + return block(0, cols() - cCols, cRows, cCols); } @@ -248,8 +352,7 @@ typename FixedBlockXpr<...,...>::Type #endif topLeftCorner(NRowsType cRows, NColsType cCols) { - return typename FixedBlockXpr::value,internal::get_fixed_value::value>::Type - (derived(), 0, 0, internal::get_runtime_value(cRows), internal::get_runtime_value(cCols)); + return block(0, 0, cRows, cCols); } /// This is the const version of topLeftCorner(Index, Index). @@ -262,8 +365,7 @@ const typename ConstFixedBlockXpr<...,...>::Type #endif topLeftCorner(NRowsType cRows, NColsType cCols) const { - return typename ConstFixedBlockXpr::value,internal::get_fixed_value::value>::Type - (derived(), 0, 0, internal::get_runtime_value(cRows), internal::get_runtime_value(cCols)); + return block(0, 0, cRows, cCols); } /// \returns an expression of a fixed-size top-left corner of \c *this. @@ -281,7 +383,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename FixedBlockXpr::Type topLeftCorner() { - return typename FixedBlockXpr::Type(derived(), 0, 0); + return block(0, 0); } /// This is the const version of topLeftCorner(). @@ -289,7 +391,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename ConstFixedBlockXpr::Type topLeftCorner() const { - return typename ConstFixedBlockXpr::Type(derived(), 0, 0); + return block(0, 0); } /// \returns an expression of a top-left corner of \c *this. @@ -315,7 +417,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename FixedBlockXpr::Type topLeftCorner(Index cRows, Index cCols) { - return typename FixedBlockXpr::Type(derived(), 0, 0, cRows, cCols); + return block(0, 0, cRows, cCols); } /// This is the const version of topLeftCorner(Index, Index). @@ -323,7 +425,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename ConstFixedBlockXpr::Type topLeftCorner(Index cRows, Index cCols) const { - return typename ConstFixedBlockXpr::Type(derived(), 0, 0, cRows, cCols); + return block(0, 0, cRows, cCols); } @@ -354,9 +456,9 @@ typename FixedBlockXpr<...,...>::Type #endif bottomRightCorner(NRowsType cRows, NColsType cCols) { - return typename FixedBlockXpr::value,internal::get_fixed_value::value>::Type - (derived(), rows() - internal::get_runtime_value(cRows), cols() - internal::get_runtime_value(cCols), - internal::get_runtime_value(cRows), internal::get_runtime_value(cCols)); + return block(rows() - internal::get_runtime_value(cRows), + cols() - internal::get_runtime_value(cCols), + cRows, cCols); } /// This is the const version of bottomRightCorner(NRowsType, NColsType). @@ -369,9 +471,9 @@ const typename ConstFixedBlockXpr<...,...>::Type #endif bottomRightCorner(NRowsType cRows, NColsType cCols) const { - return typename ConstFixedBlockXpr::value,internal::get_fixed_value::value>::Type - (derived(), rows() - internal::get_runtime_value(cRows), cols() - internal::get_runtime_value(cCols), - internal::get_runtime_value(cRows), internal::get_runtime_value(cCols)); + return block(rows() - internal::get_runtime_value(cRows), + cols() - internal::get_runtime_value(cCols), + cRows, cCols); } /// \returns an expression of a fixed-size bottom-right corner of \c *this. @@ -389,7 +491,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename FixedBlockXpr::Type bottomRightCorner() { - return typename FixedBlockXpr::Type(derived(), rows() - CRows, cols() - CCols); + return block(rows() - CRows, cols() - CCols); } /// This is the const version of bottomRightCorner(). @@ -397,7 +499,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename ConstFixedBlockXpr::Type bottomRightCorner() const { - return typename ConstFixedBlockXpr::Type(derived(), rows() - CRows, cols() - CCols); + return block(rows() - CRows, cols() - CCols); } /// \returns an expression of a bottom-right corner of \c *this. @@ -423,7 +525,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename FixedBlockXpr::Type bottomRightCorner(Index cRows, Index cCols) { - return typename FixedBlockXpr::Type(derived(), rows() - cRows, cols() - cCols, cRows, cCols); + return block(rows() - cRows, cols() - cCols, cRows, cCols); } /// This is the const version of bottomRightCorner(Index, Index). @@ -431,7 +533,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename ConstFixedBlockXpr::Type bottomRightCorner(Index cRows, Index cCols) const { - return typename ConstFixedBlockXpr::Type(derived(), rows() - cRows, cols() - cCols, cRows, cCols); + return block(rows() - cRows, cols() - cCols, cRows, cCols); } @@ -462,9 +564,7 @@ typename FixedBlockXpr<...,...>::Type #endif bottomLeftCorner(NRowsType cRows, NColsType cCols) { - return typename FixedBlockXpr::value,internal::get_fixed_value::value>::Type - (derived(), rows() - internal::get_runtime_value(cRows), 0, - internal::get_runtime_value(cRows), internal::get_runtime_value(cCols)); + return block(rows() - internal::get_runtime_value(cRows), 0, cRows, cCols); } /// This is the const version of bottomLeftCorner(NRowsType, NColsType). @@ -477,9 +577,7 @@ typename ConstFixedBlockXpr<...,...>::Type #endif bottomLeftCorner(NRowsType cRows, NColsType cCols) const { - return typename ConstFixedBlockXpr::value,internal::get_fixed_value::value>::Type - (derived(), rows() - internal::get_runtime_value(cRows), 0, - internal::get_runtime_value(cRows), internal::get_runtime_value(cCols)); + return block(rows() - internal::get_runtime_value(cRows), 0, cRows, cCols); } /// \returns an expression of a fixed-size bottom-left corner of \c *this. @@ -497,7 +595,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename FixedBlockXpr::Type bottomLeftCorner() { - return typename FixedBlockXpr::Type(derived(), rows() - CRows, 0); + return block(rows() - CRows, 0); } /// This is the const version of bottomLeftCorner(). @@ -505,7 +603,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const typename ConstFixedBlockXpr::Type bottomLeftCorner() const { - return typename ConstFixedBlockXpr::Type(derived(), rows() - CRows, 0); + return block(rows() - CRows, 0); } /// \returns an expression of a bottom-left corner of \c *this. @@ -531,7 +629,7 @@ template EIGEN_STRONG_INLINE typename FixedBlockXpr::Type bottomLeftCorner(Index cRows, Index cCols) { - return typename FixedBlockXpr::Type(derived(), rows() - cRows, 0, cRows, cCols); + return block(rows() - cRows, 0, cRows, cCols); } /// This is the const version of bottomLeftCorner(Index, Index). @@ -539,18 +637,17 @@ template EIGEN_STRONG_INLINE const typename ConstFixedBlockXpr::Type bottomLeftCorner(Index cRows, Index cCols) const { - return typename ConstFixedBlockXpr::Type(derived(), rows() - cRows, 0, cRows, cCols); + return block(rows() - cRows, 0, cRows, cCols); } - - -/// \returns a block consisting of the top rows of \c *this. +/// \returns a block consisting of a range of rows of \c *this. /// +/// \param startRow the index of the first row in the block /// \param n the number of rows in the block /// \tparam NRowsType the type of the value handling the number of rows in the block, typically Index. /// -/// Example: \include MatrixBase_topRows_int.cpp -/// Output: \verbinclude MatrixBase_topRows_int.out +/// Example: \include DenseBase_middleRows_int.cpp +/// Output: \verbinclude DenseBase_middleRows_int.out /// /// The number of rows \a n can also be specified at compile-time by passing Eigen::fix, /// or Eigen::fix(n) as arguments. @@ -567,13 +664,15 @@ typename NRowsBlockXpr::value>::Type #else typename NRowsBlockXpr<...>::Type #endif -topRows(NRowsType n) +middleRows(Index startRow, NRowsType n) { return typename NRowsBlockXpr::value>::Type - (derived(), 0, 0, internal::get_runtime_value(n), cols()); + (BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), startRow), BlockXprHelper::col(derived(), 0), + internal::get_runtime_value(n), cols()); } -/// This is the const version of topRows(NRowsType). +/// This is the const version of middleRows(Index,NRowsType). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE #ifndef EIGEN_PARSED_BY_DOXYGEN @@ -581,22 +680,25 @@ const typename ConstNRowsBlockXpr::value>:: #else const typename ConstNRowsBlockXpr<...>::Type #endif -topRows(NRowsType n) const +middleRows(Index startRow, NRowsType n) const { return typename ConstNRowsBlockXpr::value>::Type - (derived(), 0, 0, internal::get_runtime_value(n), cols()); + (BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), startRow), BlockXprHelper::col(derived(), 0), + internal::get_runtime_value(n), cols()); } -/// \returns a block consisting of the top rows of \c *this. +/// \returns a block consisting of a range of rows of \c *this. /// /// \tparam N the number of rows in the block as specified at compile-time +/// \param startRow the index of the first row in the block /// \param n the number of rows in the block as specified at run-time /// /// The compile-time and run-time information should not contradict. In other words, /// \a n should equal \a N unless \a N is \a Dynamic. /// -/// Example: \include MatrixBase_template_int_topRows.cpp -/// Output: \verbinclude MatrixBase_template_int_topRows.out +/// Example: \include DenseBase_template_int_middleRows.cpp +/// Output: \verbinclude DenseBase_template_int_middleRows.out /// EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(row-major) /// @@ -604,28 +706,33 @@ EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(row-major) /// template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename NRowsBlockXpr::Type topRows(Index n = N) +typename NRowsBlockXpr::Type middleRows(Index startRow, Index n = N) { - return typename NRowsBlockXpr::Type(derived(), 0, 0, n, cols()); + return typename NRowsBlockXpr::Type + (BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), startRow), BlockXprHelper::col(derived(), 0), + n, cols()); } -/// This is the const version of topRows(). +/// This is the const version of middleRows(). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename ConstNRowsBlockXpr::Type topRows(Index n = N) const +typename ConstNRowsBlockXpr::Type middleRows(Index startRow, Index n = N) const { - return typename ConstNRowsBlockXpr::Type(derived(), 0, 0, n, cols()); + return typename ConstNRowsBlockXpr::Type + (BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), startRow), BlockXprHelper::col(derived(), 0), + n, cols()); } - -/// \returns a block consisting of the bottom rows of \c *this. +/// \returns a block consisting of the top rows of \c *this. /// /// \param n the number of rows in the block /// \tparam NRowsType the type of the value handling the number of rows in the block, typically Index. /// -/// Example: \include MatrixBase_bottomRows_int.cpp -/// Output: \verbinclude MatrixBase_bottomRows_int.out +/// Example: \include MatrixBase_topRows_int.cpp +/// Output: \verbinclude MatrixBase_topRows_int.out /// /// The number of rows \a n can also be specified at compile-time by passing Eigen::fix, /// or Eigen::fix(n) as arguments. @@ -642,13 +749,12 @@ typename NRowsBlockXpr::value>::Type #else typename NRowsBlockXpr<...>::Type #endif -bottomRows(NRowsType n) +topRows(NRowsType n) { - return typename NRowsBlockXpr::value>::Type - (derived(), rows() - internal::get_runtime_value(n), 0, internal::get_runtime_value(n), cols()); + return middleRows(0, n); } -/// This is the const version of bottomRows(NRowsType). +/// This is the const version of topRows(NRowsType). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE #ifndef EIGEN_PARSED_BY_DOXYGEN @@ -656,13 +762,12 @@ const typename ConstNRowsBlockXpr::value>:: #else const typename ConstNRowsBlockXpr<...>::Type #endif -bottomRows(NRowsType n) const +topRows(NRowsType n) const { - return typename ConstNRowsBlockXpr::value>::Type - (derived(), rows() - internal::get_runtime_value(n), 0, internal::get_runtime_value(n), cols()); + return middleRows(0, n); } -/// \returns a block consisting of the bottom rows of \c *this. +/// \returns a block consisting of the top rows of \c *this. /// /// \tparam N the number of rows in the block as specified at compile-time /// \param n the number of rows in the block as specified at run-time @@ -670,8 +775,8 @@ bottomRows(NRowsType n) const /// The compile-time and run-time information should not contradict. In other words, /// \a n should equal \a N unless \a N is \a Dynamic. /// -/// Example: \include MatrixBase_template_int_bottomRows.cpp -/// Output: \verbinclude MatrixBase_template_int_bottomRows.out +/// Example: \include MatrixBase_template_int_topRows.cpp +/// Output: \verbinclude MatrixBase_template_int_topRows.out /// EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(row-major) /// @@ -679,29 +784,28 @@ EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(row-major) /// template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename NRowsBlockXpr::Type bottomRows(Index n = N) +typename NRowsBlockXpr::Type topRows(Index n = N) { - return typename NRowsBlockXpr::Type(derived(), rows() - n, 0, n, cols()); + return middleRows(0, n); } -/// This is the const version of bottomRows(). +/// This is the const version of topRows(). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename ConstNRowsBlockXpr::Type bottomRows(Index n = N) const +typename ConstNRowsBlockXpr::Type topRows(Index n = N) const { - return typename ConstNRowsBlockXpr::Type(derived(), rows() - n, 0, n, cols()); + return middleRows(0, n); } -/// \returns a block consisting of a range of rows of \c *this. +/// \returns a block consisting of the bottom rows of \c *this. /// -/// \param startRow the index of the first row in the block /// \param n the number of rows in the block /// \tparam NRowsType the type of the value handling the number of rows in the block, typically Index. /// -/// Example: \include DenseBase_middleRows_int.cpp -/// Output: \verbinclude DenseBase_middleRows_int.out +/// Example: \include MatrixBase_bottomRows_int.cpp +/// Output: \verbinclude MatrixBase_bottomRows_int.out /// /// The number of rows \a n can also be specified at compile-time by passing Eigen::fix, /// or Eigen::fix(n) as arguments. @@ -718,13 +822,12 @@ typename NRowsBlockXpr::value>::Type #else typename NRowsBlockXpr<...>::Type #endif -middleRows(Index startRow, NRowsType n) +bottomRows(NRowsType n) { - return typename NRowsBlockXpr::value>::Type - (derived(), startRow, 0, internal::get_runtime_value(n), cols()); + return middleRows(rows() - internal::get_runtime_value(n), n); } -/// This is the const version of middleRows(Index,NRowsType). +/// This is the const version of bottomRows(NRowsType). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE #ifndef EIGEN_PARSED_BY_DOXYGEN @@ -732,23 +835,21 @@ const typename ConstNRowsBlockXpr::value>:: #else const typename ConstNRowsBlockXpr<...>::Type #endif -middleRows(Index startRow, NRowsType n) const +bottomRows(NRowsType n) const { - return typename ConstNRowsBlockXpr::value>::Type - (derived(), startRow, 0, internal::get_runtime_value(n), cols()); + return middleRows(rows() - internal::get_runtime_value(n), n); } -/// \returns a block consisting of a range of rows of \c *this. +/// \returns a block consisting of the bottom rows of \c *this. /// /// \tparam N the number of rows in the block as specified at compile-time -/// \param startRow the index of the first row in the block /// \param n the number of rows in the block as specified at run-time /// /// The compile-time and run-time information should not contradict. In other words, /// \a n should equal \a N unless \a N is \a Dynamic. /// -/// Example: \include DenseBase_template_int_middleRows.cpp -/// Output: \verbinclude DenseBase_template_int_middleRows.out +/// Example: \include MatrixBase_template_int_bottomRows.cpp +/// Output: \verbinclude MatrixBase_template_int_bottomRows.out /// EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(row-major) /// @@ -756,28 +857,27 @@ EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(row-major) /// template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename NRowsBlockXpr::Type middleRows(Index startRow, Index n = N) +typename NRowsBlockXpr::Type bottomRows(Index n = N) { - return typename NRowsBlockXpr::Type(derived(), startRow, 0, n, cols()); + return middleRows(rows() - n, n); } -/// This is the const version of middleRows(). +/// This is the const version of bottomRows(). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename ConstNRowsBlockXpr::Type middleRows(Index startRow, Index n = N) const +typename ConstNRowsBlockXpr::Type bottomRows(Index n = N) const { - return typename ConstNRowsBlockXpr::Type(derived(), startRow, 0, n, cols()); + return middleRows(rows() - n, n); } - - -/// \returns a block consisting of the left columns of \c *this. +/// \returns a block consisting of a range of columns of \c *this. /// -/// \param n the number of columns in the block +/// \param startCol the index of the first column in the block +/// \param numCols the number of columns in the block /// \tparam NColsType the type of the value handling the number of columns in the block, typically Index. /// -/// Example: \include MatrixBase_leftCols_int.cpp -/// Output: \verbinclude MatrixBase_leftCols_int.out +/// Example: \include DenseBase_middleCols_int.cpp +/// Output: \verbinclude DenseBase_middleCols_int.out /// /// The number of columns \a n can also be specified at compile-time by passing Eigen::fix, /// or Eigen::fix(n) as arguments. @@ -794,13 +894,15 @@ typename NColsBlockXpr::value>::Type #else typename NColsBlockXpr<...>::Type #endif -leftCols(NColsType n) +middleCols(Index startCol, NColsType numCols) { return typename NColsBlockXpr::value>::Type - (derived(), 0, 0, rows(), internal::get_runtime_value(n)); + (BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), 0), BlockXprHelper::col(derived(), startCol), + rows(), internal::get_runtime_value(numCols)); } -/// This is the const version of leftCols(NColsType). +/// This is the const version of middleCols(Index,NColsType). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE #ifndef EIGEN_PARSED_BY_DOXYGEN @@ -808,22 +910,25 @@ const typename ConstNColsBlockXpr::value>:: #else const typename ConstNColsBlockXpr<...>::Type #endif -leftCols(NColsType n) const +middleCols(Index startCol, NColsType numCols) const { return typename ConstNColsBlockXpr::value>::Type - (derived(), 0, 0, rows(), internal::get_runtime_value(n)); + (BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), 0), BlockXprHelper::col(derived(), startCol), + rows(), internal::get_runtime_value(numCols)); } -/// \returns a block consisting of the left columns of \c *this. +/// \returns a block consisting of a range of columns of \c *this. /// /// \tparam N the number of columns in the block as specified at compile-time +/// \param startCol the index of the first column in the block /// \param n the number of columns in the block as specified at run-time /// /// The compile-time and run-time information should not contradict. In other words, /// \a n should equal \a N unless \a N is \a Dynamic. /// -/// Example: \include MatrixBase_template_int_leftCols.cpp -/// Output: \verbinclude MatrixBase_template_int_leftCols.out +/// Example: \include DenseBase_template_int_middleCols.cpp +/// Output: \verbinclude DenseBase_template_int_middleCols.out /// EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(column-major) /// @@ -831,28 +936,32 @@ EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(column-major) /// template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename NColsBlockXpr::Type leftCols(Index n = N) +typename NColsBlockXpr::Type middleCols(Index startCol, Index n = N) { - return typename NColsBlockXpr::Type(derived(), 0, 0, rows(), n); + return typename NColsBlockXpr::Type + (BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), 0), BlockXprHelper::col(derived(), startCol), + rows(), n); } -/// This is the const version of leftCols(). +/// This is the const version of middleCols(). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename ConstNColsBlockXpr::Type leftCols(Index n = N) const +typename ConstNColsBlockXpr::Type middleCols(Index startCol, Index n = N) const { - return typename ConstNColsBlockXpr::Type(derived(), 0, 0, rows(), n); + return typename ConstNColsBlockXpr::Type + (BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), 0), BlockXprHelper::col(derived(), startCol), + rows(), n); } - - -/// \returns a block consisting of the right columns of \c *this. +/// \returns a block consisting of the left columns of \c *this. /// /// \param n the number of columns in the block /// \tparam NColsType the type of the value handling the number of columns in the block, typically Index. /// -/// Example: \include MatrixBase_rightCols_int.cpp -/// Output: \verbinclude MatrixBase_rightCols_int.out +/// Example: \include MatrixBase_leftCols_int.cpp +/// Output: \verbinclude MatrixBase_leftCols_int.out /// /// The number of columns \a n can also be specified at compile-time by passing Eigen::fix, /// or Eigen::fix(n) as arguments. @@ -869,13 +978,12 @@ typename NColsBlockXpr::value>::Type #else typename NColsBlockXpr<...>::Type #endif -rightCols(NColsType n) +leftCols(NColsType n) { - return typename NColsBlockXpr::value>::Type - (derived(), 0, cols() - internal::get_runtime_value(n), rows(), internal::get_runtime_value(n)); + return middleCols(0, n); } -/// This is the const version of rightCols(NColsType). +/// This is the const version of leftCols(NColsType). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE #ifndef EIGEN_PARSED_BY_DOXYGEN @@ -883,13 +991,12 @@ const typename ConstNColsBlockXpr::value>:: #else const typename ConstNColsBlockXpr<...>::Type #endif -rightCols(NColsType n) const +leftCols(NColsType n) const { - return typename ConstNColsBlockXpr::value>::Type - (derived(), 0, cols() - internal::get_runtime_value(n), rows(), internal::get_runtime_value(n)); + return middleCols(0, n); } -/// \returns a block consisting of the right columns of \c *this. +/// \returns a block consisting of the left columns of \c *this. /// /// \tparam N the number of columns in the block as specified at compile-time /// \param n the number of columns in the block as specified at run-time @@ -897,8 +1004,8 @@ rightCols(NColsType n) const /// The compile-time and run-time information should not contradict. In other words, /// \a n should equal \a N unless \a N is \a Dynamic. /// -/// Example: \include MatrixBase_template_int_rightCols.cpp -/// Output: \verbinclude MatrixBase_template_int_rightCols.out +/// Example: \include MatrixBase_template_int_leftCols.cpp +/// Output: \verbinclude MatrixBase_template_int_leftCols.out /// EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(column-major) /// @@ -906,29 +1013,28 @@ EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(column-major) /// template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename NColsBlockXpr::Type rightCols(Index n = N) +typename NColsBlockXpr::Type leftCols(Index n = N) { - return typename NColsBlockXpr::Type(derived(), 0, cols() - n, rows(), n); + return middleCols(0, n); } -/// This is the const version of rightCols(). +/// This is the const version of leftCols(). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename ConstNColsBlockXpr::Type rightCols(Index n = N) const +typename ConstNColsBlockXpr::Type leftCols(Index n = N) const { - return typename ConstNColsBlockXpr::Type(derived(), 0, cols() - n, rows(), n); + return middleCols(0, n); } -/// \returns a block consisting of a range of columns of \c *this. +/// \returns a block consisting of the right columns of \c *this. /// -/// \param startCol the index of the first column in the block -/// \param numCols the number of columns in the block +/// \param n the number of columns in the block /// \tparam NColsType the type of the value handling the number of columns in the block, typically Index. /// -/// Example: \include DenseBase_middleCols_int.cpp -/// Output: \verbinclude DenseBase_middleCols_int.out +/// Example: \include MatrixBase_rightCols_int.cpp +/// Output: \verbinclude MatrixBase_rightCols_int.out /// /// The number of columns \a n can also be specified at compile-time by passing Eigen::fix, /// or Eigen::fix(n) as arguments. @@ -945,13 +1051,12 @@ typename NColsBlockXpr::value>::Type #else typename NColsBlockXpr<...>::Type #endif -middleCols(Index startCol, NColsType numCols) +rightCols(NColsType n) { - return typename NColsBlockXpr::value>::Type - (derived(), 0, startCol, rows(), internal::get_runtime_value(numCols)); + return middleCols(cols() - internal::get_runtime_value(n), n); } -/// This is the const version of middleCols(Index,NColsType). +/// This is the const version of rightCols(NColsType). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE #ifndef EIGEN_PARSED_BY_DOXYGEN @@ -959,23 +1064,21 @@ const typename ConstNColsBlockXpr::value>:: #else const typename ConstNColsBlockXpr<...>::Type #endif -middleCols(Index startCol, NColsType numCols) const +rightCols(NColsType n) const { - return typename ConstNColsBlockXpr::value>::Type - (derived(), 0, startCol, rows(), internal::get_runtime_value(numCols)); + return middleCols(cols() - internal::get_runtime_value(n), n); } -/// \returns a block consisting of a range of columns of \c *this. +/// \returns a block consisting of the right columns of \c *this. /// /// \tparam N the number of columns in the block as specified at compile-time -/// \param startCol the index of the first column in the block /// \param n the number of columns in the block as specified at run-time /// /// The compile-time and run-time information should not contradict. In other words, /// \a n should equal \a N unless \a N is \a Dynamic. /// -/// Example: \include DenseBase_template_int_middleCols.cpp -/// Output: \verbinclude DenseBase_template_int_middleCols.out +/// Example: \include MatrixBase_template_int_rightCols.cpp +/// Output: \verbinclude MatrixBase_template_int_rightCols.out /// EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(column-major) /// @@ -983,106 +1086,17 @@ EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(column-major) /// template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename NColsBlockXpr::Type middleCols(Index startCol, Index n = N) +typename NColsBlockXpr::Type rightCols(Index n = N) { - return typename NColsBlockXpr::Type(derived(), 0, startCol, rows(), n); + return middleCols(cols() - n, n); } -/// This is the const version of middleCols(). +/// This is the const version of rightCols(). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename ConstNColsBlockXpr::Type middleCols(Index startCol, Index n = N) const -{ - return typename ConstNColsBlockXpr::Type(derived(), 0, startCol, rows(), n); -} - - - -/// \returns a fixed-size expression of a block of \c *this. -/// -/// The template parameters \a NRows and \a NCols are the number of -/// rows and columns in the block. -/// -/// \param startRow the first row in the block -/// \param startCol the first column in the block -/// -/// Example: \include MatrixBase_block_int_int.cpp -/// Output: \verbinclude MatrixBase_block_int_int.out -/// -/// \note The usage of of this overload is discouraged from %Eigen 3.4, better used the generic -/// block(Index,Index,NRowsType,NColsType), here is the one-to-one equivalence: -/// \code -/// mat.template block(i,j) <--> mat.block(i,j,fix,fix) -/// \endcode -/// -/// \note since block is a templated member, the keyword template has to be used -/// if the matrix type is also a template parameter: \code m.template block<3,3>(1,1); \endcode -/// -EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL -/// -/// \sa block(Index,Index,NRowsType,NColsType), class Block -/// -template -EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename FixedBlockXpr::Type block(Index startRow, Index startCol) -{ - return typename FixedBlockXpr::Type(derived(), startRow, startCol); -} - -/// This is the const version of block<>(Index, Index). */ -template -EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -const typename ConstFixedBlockXpr::Type block(Index startRow, Index startCol) const -{ - return typename ConstFixedBlockXpr::Type(derived(), startRow, startCol); -} - -/// \returns an expression of a block of \c *this. -/// -/// \tparam NRows number of rows in block as specified at compile-time -/// \tparam NCols number of columns in block as specified at compile-time -/// \param startRow the first row in the block -/// \param startCol the first column in the block -/// \param blockRows number of rows in block as specified at run-time -/// \param blockCols number of columns in block as specified at run-time -/// -/// This function is mainly useful for blocks where the number of rows is specified at compile-time -/// and the number of columns is specified at run-time, or vice versa. The compile-time and run-time -/// information should not contradict. In other words, \a blockRows should equal \a NRows unless -/// \a NRows is \a Dynamic, and the same for the number of columns. -/// -/// Example: \include MatrixBase_template_int_int_block_int_int_int_int.cpp -/// Output: \verbinclude MatrixBase_template_int_int_block_int_int_int_int.out -/// -/// \note The usage of of this overload is discouraged from %Eigen 3.4, better used the generic -/// block(Index,Index,NRowsType,NColsType), here is the one-to-one complete equivalence: -/// \code -/// mat.template block(i,j,rows,cols) <--> mat.block(i,j,fix(rows),fix(cols)) -/// \endcode -/// If we known that, e.g., NRows==Dynamic and NCols!=Dynamic, then the equivalence becomes: -/// \code -/// mat.template block(i,j,rows,NCols) <--> mat.block(i,j,rows,fix) -/// \endcode -/// -EIGEN_DOC_BLOCK_ADDONS_NOT_INNER_PANEL -/// -/// \sa block(Index,Index,NRowsType,NColsType), class Block -/// -template -EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename FixedBlockXpr::Type block(Index startRow, Index startCol, - Index blockRows, Index blockCols) -{ - return typename FixedBlockXpr::Type(derived(), startRow, startCol, blockRows, blockCols); -} - -/// This is the const version of block<>(Index, Index, Index, Index). -template -EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -const typename ConstFixedBlockXpr::Type block(Index startRow, Index startCol, - Index blockRows, Index blockCols) const +typename ConstNColsBlockXpr::Type rightCols(Index n = N) const { - return typename ConstFixedBlockXpr::Type(derived(), startRow, startCol, blockRows, blockCols); + return middleCols(cols() - n, n); } /// \returns an expression of the \a i-th column of \c *this. Note that the numbering starts at 0. @@ -1096,14 +1110,18 @@ EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(column-major) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ColXpr col(Index i) { - return ColXpr(derived(), i); + return ColXpr(BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), 0), BlockXprHelper::col(derived(), i), + rows(), 1); } /// This is the const version of col(). EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ConstColXpr col(Index i) const { - return ConstColXpr(derived(), i); + return ConstColXpr(BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), 0), BlockXprHelper::col(derived(), i), + rows(), 1); } /// \returns an expression of the \a i-th row of \c *this. Note that the numbering starts at 0. @@ -1117,14 +1135,18 @@ EIGEN_DOC_BLOCK_ADDONS_INNER_PANEL_IF(row-major) EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE RowXpr row(Index i) { - return RowXpr(derived(), i); + return RowXpr(BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), i), BlockXprHelper::col(derived(), 0), + 1, cols()); } /// This is the const version of row(). */ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ConstRowXpr row(Index i) const { - return ConstRowXpr(derived(), i); + return ConstRowXpr(BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), i), BlockXprHelper::col(derived(), 0), + 1, cols()); } /// \returns an expression of a segment (i.e. a vector block) in \c *this with either dynamic or fixed sizes. @@ -1159,10 +1181,13 @@ segment(Index start, NType n) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return typename FixedSegmentReturnType::value>::Type - (derived(), start, internal::get_runtime_value(n)); + (BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), IsRowMajor ? 0 : start), + BlockXprHelper::col(derived(), IsRowMajor ? start : 0), + IsRowMajor ? 1 : internal::get_runtime_value(n), + IsRowMajor ? internal::get_runtime_value(n) : 1); } - /// This is the const version of segment(Index,NType). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE @@ -1175,67 +1200,65 @@ segment(Index start, NType n) const { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) return typename ConstFixedSegmentReturnType::value>::Type - (derived(), start, internal::get_runtime_value(n)); + (BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), IsRowMajor ? 0 : start), + BlockXprHelper::col(derived(), IsRowMajor ? start : 0), + IsRowMajor ? 1 : internal::get_runtime_value(n), + IsRowMajor ? internal::get_runtime_value(n) : 1); } -/// \returns an expression of the first coefficients of \c *this with either dynamic or fixed sizes. +/// \returns a fixed-size expression of a segment (i.e. a vector block) in \c *this /// /// \only_for_vectors /// -/// \param n the number of coefficients in the segment -/// \tparam NType the type of the value handling the number of coefficients in the segment, typically Index. -/// -/// Example: \include MatrixBase_start_int.cpp -/// Output: \verbinclude MatrixBase_start_int.out +/// \tparam N the number of coefficients in the segment as specified at compile-time +/// \param start the index of the first element in the segment +/// \param n the number of coefficients in the segment as specified at compile-time /// -/// The number of coefficients \a n can also be specified at compile-time by passing Eigen::fix, -/// or Eigen::fix(n) as arguments. -/// See \link block(Index,Index,NRowsType,NColsType) block() \endlink for the details. +/// The compile-time and run-time information should not contradict. In other words, +/// \a n should equal \a N unless \a N is \a Dynamic. /// -/// \note Even in the case that the returned expression has dynamic size, in the case -/// when it is applied to a fixed-size vector, it inherits a fixed maximal size, -/// which means that evaluating it does not cause a dynamic memory allocation. +/// Example: \include MatrixBase_template_int_segment.cpp +/// Output: \verbinclude MatrixBase_template_int_segment.out /// -/// \sa class Block, block(Index,Index) +/// \sa segment(Index,NType), class Block /// -template +template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -#ifndef EIGEN_PARSED_BY_DOXYGEN -typename FixedSegmentReturnType::value>::Type -#else -typename FixedSegmentReturnType<...>::Type -#endif -head(NType n) +typename FixedSegmentReturnType::Type segment(Index start, Index n = N) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return typename FixedSegmentReturnType::value>::Type - (derived(), 0, internal::get_runtime_value(n)); + return typename FixedSegmentReturnType::Type + (BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), IsRowMajor ? 0 : start), + BlockXprHelper::col(derived(), IsRowMajor ? start : 0), + IsRowMajor ? 1 : n, + IsRowMajor ? n : 1); } -/// This is the const version of head(NType). -template +/// This is the const version of segment(Index). +template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -#ifndef EIGEN_PARSED_BY_DOXYGEN -const typename ConstFixedSegmentReturnType::value>::Type -#else -const typename ConstFixedSegmentReturnType<...>::Type -#endif -head(NType n) const +typename ConstFixedSegmentReturnType::Type segment(Index start, Index n = N) const { EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return typename ConstFixedSegmentReturnType::value>::Type - (derived(), 0, internal::get_runtime_value(n)); + return typename ConstFixedSegmentReturnType::Type + (BlockXprHelper::base(derived()), + BlockXprHelper::row(derived(), IsRowMajor ? 0 : start), + BlockXprHelper::col(derived(), IsRowMajor ? start : 0), + IsRowMajor ? 1 : n, + IsRowMajor ? n : 1); } -/// \returns an expression of a last coefficients of \c *this with either dynamic or fixed sizes. +/// \returns an expression of the first coefficients of \c *this with either dynamic or fixed sizes. /// /// \only_for_vectors /// /// \param n the number of coefficients in the segment /// \tparam NType the type of the value handling the number of coefficients in the segment, typically Index. /// -/// Example: \include MatrixBase_end_int.cpp -/// Output: \verbinclude MatrixBase_end_int.out +/// Example: \include MatrixBase_start_int.cpp +/// Output: \verbinclude MatrixBase_start_int.out /// /// The number of coefficients \a n can also be specified at compile-time by passing Eigen::fix, /// or Eigen::fix(n) as arguments. @@ -1254,14 +1277,12 @@ typename FixedSegmentReturnType::value>::Type #else typename FixedSegmentReturnType<...>::Type #endif -tail(NType n) +head(NType n) { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return typename FixedSegmentReturnType::value>::Type - (derived(), this->size() - internal::get_runtime_value(n), internal::get_runtime_value(n)); + return segment(0, n); } -/// This is the const version of tail(Index). +/// This is the const version of head(NType). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE #ifndef EIGEN_PARSED_BY_DOXYGEN @@ -1269,76 +1290,84 @@ const typename ConstFixedSegmentReturnType::val #else const typename ConstFixedSegmentReturnType<...>::Type #endif -tail(NType n) const +head(NType n) const { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return typename ConstFixedSegmentReturnType::value>::Type - (derived(), this->size() - internal::get_runtime_value(n), internal::get_runtime_value(n)); + return segment(0, n); } -/// \returns a fixed-size expression of a segment (i.e. a vector block) in \c *this +/// \returns a fixed-size expression of the first coefficients of \c *this. /// /// \only_for_vectors /// /// \tparam N the number of coefficients in the segment as specified at compile-time -/// \param start the index of the first element in the segment -/// \param n the number of coefficients in the segment as specified at compile-time +/// \param n the number of coefficients in the segment as specified at run-time /// /// The compile-time and run-time information should not contradict. In other words, /// \a n should equal \a N unless \a N is \a Dynamic. /// -/// Example: \include MatrixBase_template_int_segment.cpp -/// Output: \verbinclude MatrixBase_template_int_segment.out +/// Example: \include MatrixBase_template_int_start.cpp +/// Output: \verbinclude MatrixBase_template_int_start.out /// -/// \sa segment(Index,NType), class Block +/// \sa head(NType), class Block /// template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename FixedSegmentReturnType::Type segment(Index start, Index n = N) +typename FixedSegmentReturnType::Type head(Index n = N) { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return typename FixedSegmentReturnType::Type(derived(), start, n); + return segment(0, n); } -/// This is the const version of segment(Index). +/// This is the const version of head(). template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename ConstFixedSegmentReturnType::Type segment(Index start, Index n = N) const +typename ConstFixedSegmentReturnType::Type head(Index n = N) const { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return typename ConstFixedSegmentReturnType::Type(derived(), start, n); + return segment(0, n); } -/// \returns a fixed-size expression of the first coefficients of \c *this. +/// \returns an expression of a last coefficients of \c *this with either dynamic or fixed sizes. /// /// \only_for_vectors /// -/// \tparam N the number of coefficients in the segment as specified at compile-time -/// \param n the number of coefficients in the segment as specified at run-time +/// \param n the number of coefficients in the segment +/// \tparam NType the type of the value handling the number of coefficients in the segment, typically Index. /// -/// The compile-time and run-time information should not contradict. In other words, -/// \a n should equal \a N unless \a N is \a Dynamic. +/// Example: \include MatrixBase_end_int.cpp +/// Output: \verbinclude MatrixBase_end_int.out /// -/// Example: \include MatrixBase_template_int_start.cpp -/// Output: \verbinclude MatrixBase_template_int_start.out +/// The number of coefficients \a n can also be specified at compile-time by passing Eigen::fix, +/// or Eigen::fix(n) as arguments. +/// See \link block(Index,Index,NRowsType,NColsType) block() \endlink for the details. /// -/// \sa head(NType), class Block +/// \note Even in the case that the returned expression has dynamic size, in the case +/// when it is applied to a fixed-size vector, it inherits a fixed maximal size, +/// which means that evaluating it does not cause a dynamic memory allocation. /// -template +/// \sa class Block, block(Index,Index) +/// +template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename FixedSegmentReturnType::Type head(Index n = N) +#ifndef EIGEN_PARSED_BY_DOXYGEN +typename FixedSegmentReturnType::value>::Type +#else +typename FixedSegmentReturnType<...>::Type +#endif +tail(NType n) { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return typename FixedSegmentReturnType::Type(derived(), 0, n); + return segment(this->size() - internal::get_runtime_value(n), n); } -/// This is the const version of head(). -template +/// This is the const version of tail(Index). +template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -typename ConstFixedSegmentReturnType::Type head(Index n = N) const +#ifndef EIGEN_PARSED_BY_DOXYGEN +const typename ConstFixedSegmentReturnType::value>::Type +#else +const typename ConstFixedSegmentReturnType<...>::Type +#endif +tail(NType n) const { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return typename ConstFixedSegmentReturnType::Type(derived(), 0, n); + return segment(this->size() - internal::get_runtime_value(n), n); } /// \returns a fixed-size expression of the last coefficients of \c *this. @@ -1360,8 +1389,7 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename FixedSegmentReturnType::Type tail(Index n = N) { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return typename FixedSegmentReturnType::Type(derived(), size() - n); + return segment(size() - n, n); } /// This is the const version of tail. @@ -1369,34 +1397,42 @@ template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename ConstFixedSegmentReturnType::Type tail(Index n = N) const { - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return typename ConstFixedSegmentReturnType::Type(derived(), size() - n); + return segment(size() - n, n); } /// \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this /// is col-major (resp. row-major). /// EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -InnerVectorReturnType innerVector(Index outer) -{ return InnerVectorReturnType(derived(), outer); } +InnerVectorReturnType innerVector(Index outer) { + return InnerVectorReturnType( + BlockXprHelper::base(derived()), + IsRowMajor ? outer : 0, IsRowMajor ? 0 : outer, + IsRowMajor ? 1 : rows(), IsRowMajor ? cols() : 1); +} /// \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this /// is col-major (resp. row-major). Read-only. /// EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE -const ConstInnerVectorReturnType innerVector(Index outer) const -{ return ConstInnerVectorReturnType(derived(), outer); } +const ConstInnerVectorReturnType innerVector(Index outer) const { + return ConstInnerVectorReturnType( + BlockXprHelper::base(derived()), + IsRowMajor ? outer : 0, IsRowMajor ? 0 : outer, + IsRowMajor ? 1 : rows(), IsRowMajor ? cols() : 1); +} /// \returns the \a outer -th column (resp. row) of the matrix \c *this if \c *this /// is col-major (resp. row-major). /// EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE InnerVectorsReturnType -innerVectors(Index outerStart, Index outerSize) -{ - return Block(derived(), - IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart, - IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize); +innerVectors(Index outerStart, Index outerSize) { + return InnerVectorsReturnType( + BlockXprHelper::base(derived()), + IsRowMajor ? BlockXprHelper::row(derived(), outerStart) : BlockXprHelper::col(derived(), 0), + IsRowMajor ? BlockXprHelper::row(derived(), 0) : BlockXprHelper::col(derived(), outerStart), + IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize); } @@ -1405,12 +1441,12 @@ innerVectors(Index outerStart, Index outerSize) /// EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const ConstInnerVectorsReturnType -innerVectors(Index outerStart, Index outerSize) const -{ - return Block(derived(), - IsRowMajor ? outerStart : 0, IsRowMajor ? 0 : outerStart, - IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize); - +innerVectors(Index outerStart, Index outerSize) const { + return ConstInnerVectorsReturnType( + BlockXprHelper::base(derived()), + IsRowMajor ? BlockXprHelper::row(derived(), outerStart) : BlockXprHelper::col(derived(), 0), + IsRowMajor ? BlockXprHelper::row(derived(), 0) : BlockXprHelper::col(derived(), outerStart), + IsRowMajor ? outerSize : rows(), IsRowMajor ? cols() : outerSize); } /** \returns the i-th subvector (column or vector) according to the \c Direction @@ -1421,7 +1457,12 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::conditional_t subVector(Index i) { - return std::conditional_t(derived(),i); + return std::conditional_t( + BlockXprHelper::base(derived()), + Direction==Vertical ? 0 : BlockXprHelper::col(derived(), i), + Direction==Vertical ? BlockXprHelper::row(derived(), i) : 0, + Direction==Vertical ? rows() : 1, + Direction==Vertical ? 1 : cols()); } /** This is the const version of subVector(Index) */ @@ -1430,7 +1471,12 @@ EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::conditional_t subVector(Index i) const { - return std::conditional_t(derived(),i); + return std::conditional_t( + BlockXprHelper::base(derived()), + Direction==Vertical ? 0 : BlockXprHelper::col(derived(), i), + Direction==Vertical ? BlockXprHelper::row(derived(), i) : 0, + Direction==Vertical ? rows() : 1, + Direction==Vertical ? 1 : cols()); } /** \returns the number of subvectors (rows or columns) in the direction \c Direction @@ -1439,4 +1485,4 @@ subVector(Index i) const template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE EIGEN_CONSTEXPR Index subVectors() const -{ return (Direction==Vertical)?cols():rows(); } +{ return (Direction==Vertical) ? cols() : rows(); } diff --git a/Eigen/src/plugins/IndexedViewMethods.h b/Eigen/src/plugins/IndexedViewMethods.h index e5432eacce7435fde2b251abab17858489a8ba6f..ef43a0db598c8cb4a46bcc857786e3af48c41572 100644 --- a/Eigen/src/plugins/IndexedViewMethods.h +++ b/Eigen/src/plugins/IndexedViewMethods.h @@ -148,17 +148,37 @@ struct VectorIndexedViewSelector { // Block template struct VectorIndexedViewSelector { - - using ReturnType = VectorBlock::value>; - using ConstReturnType = VectorBlock::value>; + using BlockXprHelper = internal::block_xpr_helper; + using BlockXprBase = typename BlockXprHelper::BaseType; + template struct FixedSegmentReturnType { + typedef Block Type; + }; + template struct ConstFixedSegmentReturnType { + typedef const Block Type; + }; + + using ReturnType = typename FixedSegmentReturnType::value>::Type; + using ConstReturnType = typename ConstFixedSegmentReturnType::value>::Type; static inline ReturnType run(Derived& derived, const Indices& indices) { IvcType actualIndices = derived.ivcSize(indices); - return ReturnType(derived, internal::first(actualIndices), internal::index_list_size(actualIndices)); + auto start = internal::first(actualIndices); + auto n = internal::get_runtime_value(internal::index_list_size(actualIndices)); + return ReturnType(BlockXprHelper::base(derived), + BlockXprHelper::row(derived, IsRowMajor ? 0 : start), + BlockXprHelper::col(derived, IsRowMajor ? start : 0), + IsRowMajor ? 1 : n, + IsRowMajor ? n : 1); } static inline ConstReturnType run(const Derived& derived, const Indices& indices) { IvcType actualIndices = derived.ivcSize(indices); - return ConstReturnType(derived, internal::first(actualIndices), internal::index_list_size(actualIndices)); + auto start = internal::first(actualIndices); + auto n = internal::get_runtime_value(internal::index_list_size(actualIndices)); + return ConstReturnType(BlockXprHelper::base(derived), + BlockXprHelper::row(derived, IsRowMajor ? 0 : start), + BlockXprHelper::col(derived, IsRowMajor ? start : 0), + IsRowMajor ? 1 : n, + IsRowMajor ? n : 1); } }; @@ -344,7 +364,7 @@ operator()(const RowIndices& rowIndices, const ColIndices& colIndices); * \only_for_vectors */ template -IndexedView_or_VectorBlock +IndexedView_or_Block operator()(const Indices& indices); #endif // EIGEN_PARSED_BY_DOXYGEN diff --git a/test/block.cpp b/test/block.cpp index aba089629dc66b1db909c54b79b6f6a4081d1343..b7bbfadffd094552fc64966396c121da6542596e 100644 --- a/test/block.cpp +++ b/test/block.cpp @@ -306,6 +306,51 @@ void data_and_stride(const MatrixType& m) compare_using_data_and_stride(m1.col(c1).transpose()); } +template +void recursive_block_check(const Xpr& xpr) { + // Recursively reduce rows/cols until the result is 1x1. This is just + // to ensure we don't introduce infinite compile-time recursion. + if (xpr.rows() > 1) { + recursive_block_check(xpr.block(0, 0, (xpr.rows() + 1) / 2, xpr.cols())); + } + if (xpr.cols() > 1) { + recursive_block_check(xpr.block(0, 0, xpr.rows(), (xpr.cols() + 1)/2)); + } +} + +template +struct unwind_test_impl { + static void run(Xpr& xpr) { + Index startRow = xpr.rows() / 5; + Index startCol = xpr.cols() / 6; + Index rows = xpr.rows() / 3; + Index cols = xpr.cols() / 2; + // test equivalence of const expressions + const Block constNestedBlock(xpr, startRow, startCol, rows, cols); + const Block constUnwoundBlock = constNestedBlock.unwind(); + VERIFY_IS_CWISE_EQUAL(constNestedBlock, constUnwoundBlock); + // modify a random element and test equivalence of non-const expressions + Block nestedBlock(xpr, startRow, startCol, rows, cols); + Block unwoundBlock = nestedBlock.unwind(); + Index r = internal::random(0, rows - 1); + Index c = internal::random(0, cols - 1); + nestedBlock.coeffRef(r, c) = internal::random::Scalar>(); + VERIFY_IS_CWISE_EQUAL(nestedBlock, unwoundBlock); + unwind_test_impl, Depth + 1>::run(nestedBlock); + } +}; + +template +struct unwind_test_impl { + static void run(const Xpr&) {} +}; + +template +void unwind_test(const BaseXpr&) { + BaseXpr xpr = BaseXpr::Random(100, 100); + unwind_test_impl::run(xpr); +} + EIGEN_DECLARE_TEST(block) { for(int i = 0; i < g_repeat; i++) { @@ -320,6 +365,8 @@ EIGEN_DECLARE_TEST(block) CALL_SUBTEST_7( block(Matrix(internal::random(2,50), internal::random(2,50))) ); CALL_SUBTEST_8( block(Matrix(3, 4)) ); + CALL_SUBTEST_9( recursive_block_check(Matrix(3, 4)) ); + CALL_SUBTEST_10( unwind_test(MatrixXf())); #ifndef EIGEN_DEFAULT_TO_ROW_MAJOR CALL_SUBTEST_6( data_and_stride(MatrixXf(internal::random(5,50), internal::random(5,50))) );