From e37ff98bbb21f2ee44c6d912002ddf2cdf05ccda Mon Sep 17 00:00:00 2001 From: Jitse Niesen Date: Tue, 18 Jun 2013 14:29:15 +0100 Subject: [PATCH] Implement mixed static/dynamic-size .block() (bug #579) --- Eigen/src/plugins/BlockMethods.h | 158 +++++++++++++++++- doc/LinearLeastSquares.dox | 27 +++ ...template_int_int_block_int_int_int_int.cpp | 5 + ...plate_int_int_bottomLeftCorner_int_int.cpp | 6 + ...late_int_int_bottomRightCorner_int_int.cpp | 6 + ...template_int_int_topLeftCorner_int_int.cpp | 6 + ...emplate_int_int_topRightCorner_int_int.cpp | 6 + test/block.cpp | 6 + test/corners.cpp | 20 +++ 9 files changed, 238 insertions(+), 2 deletions(-) create mode 100644 doc/LinearLeastSquares.dox create mode 100644 doc/snippets/MatrixBase_template_int_int_block_int_int_int_int.cpp create mode 100644 doc/snippets/MatrixBase_template_int_int_bottomLeftCorner_int_int.cpp create mode 100644 doc/snippets/MatrixBase_template_int_int_bottomRightCorner_int_int.cpp create mode 100644 doc/snippets/MatrixBase_template_int_int_topLeftCorner_int_int.cpp create mode 100644 doc/snippets/MatrixBase_template_int_int_topRightCorner_int_int.cpp diff --git a/Eigen/src/plugins/BlockMethods.h b/Eigen/src/plugins/BlockMethods.h index 19a491cf7..6911bedef 100644 --- a/Eigen/src/plugins/BlockMethods.h +++ b/Eigen/src/plugins/BlockMethods.h @@ -90,12 +90,13 @@ inline const Block topRightCorner(Index cRows, Index cCols) const /** \returns an expression of a fixed-size top-right corner of *this. * - * The template parameters CRows and CCols are the number of rows and columns in the corner. + * \tparam CRows the number of rows in the corner + * \tparam CCols the number of columns in the corner * * Example: \include MatrixBase_template_int_int_topRightCorner.cpp * Output: \verbinclude MatrixBase_template_int_int_topRightCorner.out * - * \sa class Block, block(Index,Index,Index,Index) + * \sa class Block, block(Index,Index) */ template inline Block topRightCorner() @@ -110,6 +111,35 @@ inline const Block topRightCorner() const return Block(derived(), 0, cols() - CCols); } +/** \returns an expression of a top-right corner of *this. + * + * \tparam CRows number of rows in corner as specified at compile time + * \tparam CCols number of columns in corner as specified at compile time + * \param cRows number of rows in corner as specified at run time + * \param cCols number of columns in corner as specified at run time + * + * This function is mainly useful for corners 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 cRows should equal \a CRows unless + * \a CRows is \a Dynamic, and the same for the number of columns. + * + * Example: \include MatrixBase_template_int_int_topRightCorner_int_int.cpp + * Output: \verbinclude MatrixBase_template_int_int_topRightCorner_int_int.out + * + * \sa class Block + */ +template +inline Block topRightCorner(Index cRows, Index cCols) +{ + return Block(derived(), 0, cols() - cCols, cRows, cCols); +} + +/** This is the const version of topRightCorner(Index, Index).*/ +template +inline const Block topRightCorner(Index cRows, Index cCols) const +{ + return Block(derived(), 0, cols() - cCols, cRows, cCols); +} @@ -156,6 +186,36 @@ inline const Block topLeftCorner() const return Block(derived(), 0, 0); } +/** \returns an expression of a top-left corner of *this. + * + * \tparam CRows number of rows in corner as specified at compile time + * \tparam CCols number of columns in corner as specified at compile time + * \param cRows number of rows in corner as specified at run time + * \param cCols number of columns in corner as specified at run time + * + * This function is mainly useful for corners 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 cRows should equal \a CRows unless + * \a CRows is \a Dynamic, and the same for the number of columns. + * + * Example: \include MatrixBase_template_int_int_topLeftCorner_int_int.cpp + * Output: \verbinclude MatrixBase_template_int_int_topLeftCorner_int_int.out + * + * \sa class Block + */ +template +inline Block topLeftCorner(Index cRows, Index cCols) +{ + return Block(derived(), 0, 0, cRows, cCols); +} + +/** This is the const version of topLeftCorner(Index, Index).*/ +template +inline const Block topLeftCorner(Index cRows, Index cCols) const +{ + return Block(derived(), 0, 0, cRows, cCols); +} + /** \returns a dynamic-size expression of a bottom-right corner of *this. @@ -201,6 +261,36 @@ inline const Block bottomRightCorner() const return Block(derived(), rows() - CRows, cols() - CCols); } +/** \returns an expression of a bottom-right corner of *this. + * + * \tparam CRows number of rows in corner as specified at compile time + * \tparam CCols number of columns in corner as specified at compile time + * \param cRows number of rows in corner as specified at run time + * \param cCols number of columns in corner as specified at run time + * + * This function is mainly useful for corners 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 cRows should equal \a CRows unless + * \a CRows is \a Dynamic, and the same for the number of columns. + * + * Example: \include MatrixBase_template_int_int_bottomRightCorner_int_int.cpp + * Output: \verbinclude MatrixBase_template_int_int_bottomRightCorner_int_int.out + * + * \sa class Block + */ +template +inline Block bottomRightCorner(Index cRows, Index cCols) +{ + return Block(derived(), rows() - cRows, cols() - cCols, cRows, cCols); +} + +/** This is the const version of bottomRightCorner(Index, Index).*/ +template +inline const Block bottomRightCorner(Index cRows, Index cCols) const +{ + return Block(derived(), rows() - cRows, cols() - cCols, cRows, cCols); +} + /** \returns a dynamic-size expression of a bottom-left corner of *this. @@ -246,6 +336,36 @@ inline const Block bottomLeftCorner() const return Block(derived(), rows() - CRows, 0); } +/** \returns an expression of a bottom-left corner of *this. + * + * \tparam CRows number of rows in corner as specified at compile time + * \tparam CCols number of columns in corner as specified at compile time + * \param cRows number of rows in corner as specified at run time + * \param cCols number of columns in corner as specified at run time + * + * This function is mainly useful for corners 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 cRows should equal \a CRows unless + * \a CRows is \a Dynamic, and the same for the number of columns. + * + * Example: \include MatrixBase_template_int_int_bottomLeftCorner_int_int.cpp + * Output: \verbinclude MatrixBase_template_int_int_bottomLeftCorner_int_int.out + * + * \sa class Block + */ +template +inline Block bottomLeftCorner(Index cRows, Index cCols) +{ + return Block(derived(), rows() - cRows, 0, cRows, cCols); +} + +/** This is the const version of bottomLeftCorner(Index, Index).*/ +template +inline const Block bottomLeftCorner(Index cRows, Index cCols) const +{ + return Block(derived(), rows() - cRows, 0, cRows, cCols); +} + /** \returns a block consisting of the top rows of *this. @@ -545,6 +665,40 @@ inline const Block block(Index startRow, In return Block(derived(), startRow, startCol); } +/** \returns an expression of a block in *this. + * + * \tparam BlockRows number of rows in block as specified at compile time + * \tparam BlockCols 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 BlockRows unless + * \a BlockRows 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.cpp + * + * \sa class Block, block(Index,Index,Index,Index) + */ +template +inline Block block(Index startRow, Index startCol, + Index blockRows, Index blockCols) +{ + return Block(derived(), startRow, startCol, blockRows, blockCols); +} + +/** This is the const version of block<>(Index, Index, Index, Index). */ +template +inline const Block block(Index startRow, Index startCol, + Index blockRows, Index blockCols) const +{ + return Block(derived(), startRow, startCol, blockRows, blockCols); +} + /** \returns an expression of the \a i-th column of *this. Note that the numbering starts at 0. * * Example: \include MatrixBase_col.cpp diff --git a/doc/LinearLeastSquares.dox b/doc/LinearLeastSquares.dox new file mode 100644 index 000000000..ab21a87ae --- /dev/null +++ b/doc/LinearLeastSquares.dox @@ -0,0 +1,27 @@ +namespace Eigen { + +/** \eigenManualPage LinearLeastSquares Solving linear least squares problems + +lede + +\eigenAutoToc + +\section LinearLeastSquaresCopied Copied + +The best way to do least squares solving is with a SVD decomposition. Eigen provides one as the JacobiSVD class, and its solve() +is doing least-squares solving. + +Here is an example: + + + + + + +
Example:Output:
\include TutorialLinAlgSVDSolve.cpp \verbinclude TutorialLinAlgSVDSolve.out
+ +For more information, including faster but less reliable methods, read our page concentrating on \ref LinearLeastSquares "linear least squares problems". + +*/ + +} diff --git a/doc/snippets/MatrixBase_template_int_int_block_int_int_int_int.cpp b/doc/snippets/MatrixBase_template_int_int_block_int_int_int_int.cpp new file mode 100644 index 000000000..4dced03ba --- /dev/null +++ b/doc/snippets/MatrixBase_template_int_int_block_int_int_int_int.cpp @@ -0,0 +1,5 @@ +Matrix4i m = Matrix4i::Random(); +cout << "Here is the matrix m:" << endl << m << endl; +cout << "Here is the block:" << endl << m.block<2, Dynamic>(1, 1, 2, 3) << endl; +m.block<2, Dynamic>(1, 1, 2, 3).setZero(); +cout << "Now the matrix m is:" << endl << m << endl; diff --git a/doc/snippets/MatrixBase_template_int_int_bottomLeftCorner_int_int.cpp b/doc/snippets/MatrixBase_template_int_int_bottomLeftCorner_int_int.cpp new file mode 100644 index 000000000..a1edcc808 --- /dev/null +++ b/doc/snippets/MatrixBase_template_int_int_bottomLeftCorner_int_int.cpp @@ -0,0 +1,6 @@ +Matrix4i m = Matrix4i::Random(); +cout << "Here is the matrix m:" << endl << m << endl; +cout << "Here is m.bottomLeftCorner<2,Dynamic>(2,2):" << endl; +cout << m.bottomLeftCorner<2,Dynamic>(2,2) << endl; +m.bottomLeftCorner<2,Dynamic>(2,2).setZero(); +cout << "Now the matrix m is:" << endl << m << endl; diff --git a/doc/snippets/MatrixBase_template_int_int_bottomRightCorner_int_int.cpp b/doc/snippets/MatrixBase_template_int_int_bottomRightCorner_int_int.cpp new file mode 100644 index 000000000..a65508fd8 --- /dev/null +++ b/doc/snippets/MatrixBase_template_int_int_bottomRightCorner_int_int.cpp @@ -0,0 +1,6 @@ +Matrix4i m = Matrix4i::Random(); +cout << "Here is the matrix m:" << endl << m << endl; +cout << "Here is m.bottomRightCorner<2,Dynamic>(2,2):" << endl; +cout << m.bottomRightCorner<2,Dynamic>(2,2) << endl; +m.bottomRightCorner<2,Dynamic>(2,2).setZero(); +cout << "Now the matrix m is:" << endl << m << endl; diff --git a/doc/snippets/MatrixBase_template_int_int_topLeftCorner_int_int.cpp b/doc/snippets/MatrixBase_template_int_int_topLeftCorner_int_int.cpp new file mode 100644 index 000000000..fac761f63 --- /dev/null +++ b/doc/snippets/MatrixBase_template_int_int_topLeftCorner_int_int.cpp @@ -0,0 +1,6 @@ +Matrix4i m = Matrix4i::Random(); +cout << "Here is the matrix m:" << endl << m << endl; +cout << "Here is m.topLeftCorner<2,Dynamic>(2,2):" << endl; +cout << m.topLeftCorner<2,Dynamic>(2,2) << endl; +m.topLeftCorner<2,Dynamic>(2,2).setZero(); +cout << "Now the matrix m is:" << endl << m << endl; diff --git a/doc/snippets/MatrixBase_template_int_int_topRightCorner_int_int.cpp b/doc/snippets/MatrixBase_template_int_int_topRightCorner_int_int.cpp new file mode 100644 index 000000000..a17acc004 --- /dev/null +++ b/doc/snippets/MatrixBase_template_int_int_topRightCorner_int_int.cpp @@ -0,0 +1,6 @@ +Matrix4i m = Matrix4i::Random(); +cout << "Here is the matrix m:" << endl << m << endl; +cout << "Here is m.topRightCorner<2,Dynamic>(2,2):" << endl; +cout << m.topRightCorner<2,Dynamic>(2,2) << endl; +m.topRightCorner<2,Dynamic>(2,2).setZero(); +cout << "Now the matrix m is:" << endl << m << endl; diff --git a/test/block.cpp b/test/block.cpp index a3246f411..189fa5aba 100644 --- a/test/block.cpp +++ b/test/block.cpp @@ -77,6 +77,12 @@ template void block(const MatrixType& m) // check that fixed block() and block() agree Matrix b = m1.template block(3,3); VERIFY_IS_EQUAL(b, m1.block(3,3,BlockRows,BlockCols)); + + // same tests with mixed fixed/dynamic size + m1.template block(1,1,BlockRows,BlockCols) *= s1; + m1.template block(1,1,BlockRows,BlockCols)(0,3) = m1.template block<2,5>(1,1)(1,2); + Matrix b2 = m1.template block(3,3,2,5); + VERIFY_IS_EQUAL(b2, m1.block(3,3,BlockRows,BlockCols)); } if (rows>2) diff --git a/test/corners.cpp b/test/corners.cpp index 4705c5f05..3c64c32a1 100644 --- a/test/corners.cpp +++ b/test/corners.cpp @@ -62,6 +62,16 @@ template void c VERIFY_IS_EQUAL((matrix.template bottomLeftCorner()), (matrix.template block(rows-r,0))); VERIFY_IS_EQUAL((matrix.template bottomRightCorner()), (matrix.template block(rows-r,cols-c))); + VERIFY_IS_EQUAL((matrix.template topLeftCorner()), (matrix.template topLeftCorner(r,c))); + VERIFY_IS_EQUAL((matrix.template topRightCorner()), (matrix.template topRightCorner(r,c))); + VERIFY_IS_EQUAL((matrix.template bottomLeftCorner()), (matrix.template bottomLeftCorner(r,c))); + VERIFY_IS_EQUAL((matrix.template bottomRightCorner()), (matrix.template bottomRightCorner(r,c))); + + VERIFY_IS_EQUAL((matrix.template topLeftCorner()), (matrix.template topLeftCorner(r,c))); + VERIFY_IS_EQUAL((matrix.template topRightCorner()), (matrix.template topRightCorner(r,c))); + VERIFY_IS_EQUAL((matrix.template bottomLeftCorner()), (matrix.template bottomLeftCorner(r,c))); + VERIFY_IS_EQUAL((matrix.template bottomRightCorner()), (matrix.template bottomRightCorner(r,c))); + VERIFY_IS_EQUAL((matrix.template topRows()), (matrix.template block(0,0))); VERIFY_IS_EQUAL((matrix.template middleRows(sr)), (matrix.template block(sr,0))); VERIFY_IS_EQUAL((matrix.template bottomRows()), (matrix.template block(rows-r,0))); @@ -74,6 +84,16 @@ template void c VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner()), (const_matrix.template block(rows-r,0))); VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner()), (const_matrix.template block(rows-r,cols-c))); + VERIFY_IS_EQUAL((const_matrix.template topLeftCorner()), (const_matrix.template topLeftCorner(r,c))); + VERIFY_IS_EQUAL((const_matrix.template topRightCorner()), (const_matrix.template topRightCorner(r,c))); + VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner()), (const_matrix.template bottomLeftCorner(r,c))); + VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner()), (const_matrix.template bottomRightCorner(r,c))); + + VERIFY_IS_EQUAL((const_matrix.template topLeftCorner()), (const_matrix.template topLeftCorner(r,c))); + VERIFY_IS_EQUAL((const_matrix.template topRightCorner()), (const_matrix.template topRightCorner(r,c))); + VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner()), (const_matrix.template bottomLeftCorner(r,c))); + VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner()), (const_matrix.template bottomRightCorner(r,c))); + VERIFY_IS_EQUAL((const_matrix.template topRows()), (const_matrix.template block(0,0))); VERIFY_IS_EQUAL((const_matrix.template middleRows(sr)), (const_matrix.template block(sr,0))); VERIFY_IS_EQUAL((const_matrix.template bottomRows()), (const_matrix.template block(rows-r,0)));