Re: [eigen] Feature suggestion: interior row and column ranges [patch attached]

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]




On Saturday 26 June 2010 05:32:31 pm FMDSPAM wrote:
>   Am 26.06.2010 22:58, schrieb Manoj Rajagopalan:
> > Hi,
> >
> >    I've noticed leftCols(), rightCols(), topRows() and bottomRows() in
> > the DenseBase API. I have, on occasion felt the need to access a
> > contiguous range of rows/columns that start and end in the interior - the
> > above functions allow access only to the extremes. Could DenseBase member
> > functions, possibly named colRange(Index start, Index size) and
> > rowRange(Index start, Index size), be supported sometime in the future?
> >
> > Thanks,
> > Manoj
>
> It's already in upcomming eigen 3.0:
> Use dynamic sized block: mat1.block(i,j,rows,cols)
> or fixed sized block: mat1.block<rows,cols>(i,j)
> to have Read-write access to sub-matrices.
>
> see devel-doc:Tutorial Matrix Blocks 
> <http://eigen.tuxfamily.org/dox-devel/TutorialCore.html#TutorialCoreMatrixB
>locks>
>
> cheers
> Frank



Attaching a patch implementing my suggestion for the consideration of the 
developers/maintainers.

@Frank: I wished the API would let me choose, say 3 columns starting with the 
4th, in a 10x10 matrix. This should be a 10x3 submatrix starting at column #3 
(0-base-indexing). With leftCols() (or rightCols()), the starting (or ending) 
column is fixed to an extreme and there is currently no API method to extract 
a few contiguous columns or rows purely in the interior.

DenseBase::block() is the master method that allows the access of any 
contiguous 2D sub-region and is used to implement leftCol() and rightCol() 
but the latter are much more readable functions. So I present 
DenseBase::rowRange() and DenseBase::colRange() which use DenseBase::block() 
to extract contiguous interior rows and columns respectively.

Example of rowRange usage:

        int const N = 10;
        MatrixXi A(N,N);
        A.setRandom();
        cout << "A =\n" << A << '\n' << endl;
        cout << "A(3..5,:) =\n" << A.rowRange(3,3) << endl;
        // alternatively, since #cols is known at compile time
        cout << "A(3..5,:) =\n" << A.rowRange<3>(3) << endl;

Output:

A =
  7   0 -10   0   1   1  -5   1   4  10
 -2   3  -5   7   6  -9  10 -10  -7   2
  6  -3  -8   2  -2  -6   8  -1  -1   3
  6   0   6  -4   8   3   7   9   8   8
  9   9  -7   3  -5   8  -5   9   7  -1
 -6   9  -2   1  -3  -3   1   5  -4   9
 -3   3  -8   0   6  -9  -3  -5  -6  -2
  6   5  -8  10   9 -10   5   5   8   7
 -5  -8  10  -4  -9  -1   0   3  -3   4
  1   2  -6   6   9  -9   4  -3   4   9

A(3..5,:) =
  0   1   1
  7   6  -9
  2  -2  -6
 -4   8   3
  3  -5   8
  1  -3  -3
  0   6  -9
 10   9 -10
 -4  -9  -1
  6   9  -9


I have written small test programs like the above and have tested static and 
dynamic versions of rowRange() and colRange().

Thanks,
Manoj
# HG changeset patch
# User Manoj Rajagopalan <rmanoj@xxxxxxxxx>
# Date 1277588237 14400
# Node ID 005e59ee039e8edbf6056361b057022fbdacb40a
# Parent  687dca0e53d43b123e64e8640a08827de3fa0429
Included definitions for rowRange() and colRange() member functions of DenseBase

diff -r 687dca0e53d4 -r 005e59ee039e Eigen/src/Core/Block.h
--- a/Eigen/src/Core/Block.h	Sat Jun 26 23:15:06 2010 +0200
+++ b/Eigen/src/Core/Block.h	Sat Jun 26 17:37:17 2010 -0400
@@ -678,9 +678,62 @@ DenseBase<Derived>::bottomRows() const
 
 
 
+/** \returns a block consisting of a range of rows of *this.
+  *
+  * \param startRow the index of the first row in the block
+  * \param numRows the number of rows in the block
+  *
+  * Example: \include MatrixBase_rowRange_int.cpp
+  * Output: \verbinclude MatrixBase_rowRange_int.out
+  *
+  * \sa class Block, block(Index,Index,Index,Index)
+  */
+template<typename Derived>
+inline typename DenseBase<Derived>::RowsBlockXpr DenseBase<Derived>
+  ::rowRange(Index startRow, Index numRows)
+{
+  return RowsBlockXpr(derived(), startRow, 0, numRows, cols());
+}
 
+/** This is the const version of rowRange(Index,Index).*/
+template<typename Derived>
+inline const typename DenseBase<Derived>::RowsBlockXpr
+DenseBase<Derived>::rowRange(Index startRow, Index numRows) const
+{
+  return RowsBlockXpr(derived(), startRow, 0, numRows, cols());
+}
 
-/** \returns a block consisting of the top columns of *this.
+/** \returns a block consisting of a range of rows of *this.
+  *
+  * \param N the number of rows in the block
+  * \param startRow the index of the first row in the block
+  *
+  * Example: \include MatrixBase_template_int_rowRange.cpp
+  * Output: \verbinclude MatrixBase_template_int_rowRange.out
+  *
+  * \sa class Block, block(Index,Index,Index,Index)
+  */
+template<typename Derived>
+template<int N>
+inline typename DenseBase<Derived>::template NRowsBlockXpr<N>::Type
+DenseBase<Derived>::rowRange(Index startRow)
+{
+  return typename DenseBase<Derived>::template NRowsBlockXpr<N>::Type(derived(), startRow, 0, N, cols());
+}
+
+/** This is the const version of rowRange<int>().*/
+template<typename Derived>
+template<int N>
+inline const typename DenseBase<Derived>::template NRowsBlockXpr<N>::Type
+DenseBase<Derived>::rowRange(Index startRow) const
+{
+  return typename DenseBase<Derived>::template NRowsBlockXpr<N>::Type(derived(), startRow, 0, N, cols());
+}
+
+
+
+
+/** \returns a block consisting of the left columns of *this.
   *
   * \param n the number of columns in the block
   *
@@ -782,6 +835,61 @@ DenseBase<Derived>::rightCols() const
 DenseBase<Derived>::rightCols() const
 {
   return typename DenseBase<Derived>::template NColsBlockXpr<N>::Type(derived(), 0, cols() - N, rows(), N);
+}
+
+
+
+
+/** \returns a block consisting of a range of columns of *this.
+  *
+  * \param startCol the index of the first column in the block
+  * \param numCols the number of columns in the block
+  *
+  * Example: \include MatrixBase_colRange_int.cpp
+  * Output: \verbinclude MatrixBase_colRange_int.out
+  *
+  * \sa class Block, block(Index,Index,Index,Index)
+  */
+template<typename Derived>
+inline typename DenseBase<Derived>::ColsBlockXpr DenseBase<Derived>
+  ::colRange(Index startCol, Index numCols)
+{
+  return ColsBlockXpr(derived(), 0, startCol, rows(), numCols);
+}
+
+/** This is the const version of colRange(Index,Index).*/
+template<typename Derived>
+inline const typename DenseBase<Derived>::ColsBlockXpr
+DenseBase<Derived>::colRange(Index startCol, Index numCols) const
+{
+  return ColsBlockXpr(derived(), 0, startCol, rows(), numCols);
+}
+
+/** \returns a block consisting of a range of columns of *this.
+  *
+  * \param N the number of columns in the block
+  * \param startCol the index of the first column in the block
+  *
+  * Example: \include MatrixBase_template_int_colRange.cpp
+  * Output: \verbinclude MatrixBase_template_int_colRange.out
+  *
+  * \sa class Block, block(Index,Index,Index,Index)
+  */
+template<typename Derived>
+template<int N>
+inline typename DenseBase<Derived>::template NColsBlockXpr<N>::Type
+DenseBase<Derived>::colRange(Index startCol)
+{
+  return typename NColsBlockXpr<N>::Type(derived(), 0, startCol, rows(), N);
+}
+
+/** This is the const version of colRange<int>().*/
+template<typename Derived>
+template<int N>
+inline const typename DenseBase<Derived>::template NColsBlockXpr<N>::Type
+DenseBase<Derived>::colRange(Index startCol) const
+{
+  return typename NColsBlockXpr<N>::Type(derived(), 0, startCol, rows(), N);
 }
 
 
diff -r 687dca0e53d4 -r 005e59ee039e Eigen/src/Core/DenseBase.h
--- a/Eigen/src/Core/DenseBase.h	Sat Jun 26 23:15:06 2010 +0200
+++ b/Eigen/src/Core/DenseBase.h	Sat Jun 26 17:37:17 2010 -0400
@@ -326,10 +326,14 @@ template<typename Derived> class DenseBa
     const RowsBlockXpr topRows(Index n) const;
     RowsBlockXpr       bottomRows(Index n);
     const RowsBlockXpr bottomRows(Index n) const;
+	RowsBlockXpr       rowRange(Index startRow, Index numRows);
+	const RowsBlockXpr rowRange(Index startRow, Index numRows) const;
     ColsBlockXpr       leftCols(Index n);
     const ColsBlockXpr leftCols(Index n) const;
     ColsBlockXpr       rightCols(Index n);
     const ColsBlockXpr rightCols(Index n) const;
+	ColsBlockXpr       colRange(Index startCol, Index numCols);
+	const ColsBlockXpr colRange(Index startCol, Index numCols) const;
 
     template<int CRows, int CCols> Block<Derived, CRows, CCols>       topLeftCorner();
     template<int CRows, int CCols> const Block<Derived, CRows, CCols> topLeftCorner() const;
@@ -344,10 +348,14 @@ template<typename Derived> class DenseBa
     template<int NRows> const typename NRowsBlockXpr<NRows>::Type topRows() const;
     template<int NRows> typename NRowsBlockXpr<NRows>::Type       bottomRows();
     template<int NRows> const typename NRowsBlockXpr<NRows>::Type bottomRows() const;
+	template<int NRows> typename NRowsBlockXpr<NRows>::Type       rowRange(Index startRow);
+	template<int NRows> const typename NRowsBlockXpr<NRows>::Type rowRange(Index startRow) const;
     template<int NCols> typename NColsBlockXpr<NCols>::Type       leftCols();
     template<int NCols> const typename NColsBlockXpr<NCols>::Type leftCols() const;
     template<int NCols> typename NColsBlockXpr<NCols>::Type       rightCols();
     template<int NCols> const typename NColsBlockXpr<NCols>::Type rightCols() const;
+	template<int NCols> typename NColsBlockXpr<NCols>::Type       colRange(Index startCol);
+	template<int NCols> const typename NColsBlockXpr<NCols>::Type colRange(Index startCol) const;
 
     template<int BlockRows, int BlockCols>
     Block<Derived, BlockRows, BlockCols> block(Index startRow, Index startCol);


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/