diff options
author | Benoit Jacob <jacob.benoit.1@gmail.com> | 2010-04-22 14:11:18 -0400 |
---|---|---|
committer | Benoit Jacob <jacob.benoit.1@gmail.com> | 2010-04-22 14:11:18 -0400 |
commit | 9962c59b56960569c8df332144190e62c1eb3b01 (patch) | |
tree | a3efa574460c6a08f4ed17a3896b497d5bfc374f | |
parent | 28dde19e40a3d758faa94f0fc228857f7b3192ea (diff) |
* implement the corner() API change: new methods topLeftCorner() etc
* get rid of BlockReturnType: it was not needed, and code was not always using it consistently anyway
* add topRows(), leftCols(), bottomRows(), rightCols()
* add corners unit-test covering all of that
* adapt docs, expand "porting from eigen 2 to 3"
* adapt Eigen2Support
37 files changed, 818 insertions, 348 deletions
diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h index d0e6d4ee8..32f4b0ab2 100644 --- a/Eigen/src/Core/Block.h +++ b/Eigen/src/Core/Block.h @@ -328,128 +328,456 @@ class Block<XprType,BlockRows,BlockCols,HasDirectAccess> * \sa class Block, block(int,int) */ template<typename Derived> -inline typename BlockReturnType<Derived>::Type DenseBase<Derived> +inline Block<Derived> DenseBase<Derived> ::block(int startRow, int startCol, int blockRows, int blockCols) { - return typename BlockReturnType<Derived>::Type(derived(), startRow, startCol, blockRows, blockCols); + return Block<Derived>(derived(), startRow, startCol, blockRows, blockCols); } /** This is the const version of block(int,int,int,int). */ template<typename Derived> -inline const typename BlockReturnType<Derived>::Type DenseBase<Derived> +inline const Block<Derived> DenseBase<Derived> ::block(int startRow, int startCol, int blockRows, int blockCols) const { - return typename BlockReturnType<Derived>::Type(derived(), startRow, startCol, blockRows, blockCols); + return Block<Derived>(derived(), startRow, startCol, blockRows, blockCols); } -/** \returns a dynamic-size expression of a corner of *this. + + + +/** \returns a dynamic-size expression of a top-right corner of *this. * - * \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight, - * \a Eigen::BottomLeft, \a Eigen::BottomRight. * \param cRows the number of rows in the corner * \param cCols the number of columns in the corner * - * Example: \include MatrixBase_corner_enum_int_int.cpp - * Output: \verbinclude MatrixBase_corner_enum_int_int.out + * Example: \include MatrixBase_topRightCorner_int_int.cpp + * Output: \verbinclude MatrixBase_topRightCorner_int_int.out * - * \note Even though the returned expression has dynamic size, in the case - * when it is applied to a fixed-size matrix, it inherits a fixed maximal size, - * which means that evaluating it does not cause a dynamic memory allocation. + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +inline Block<Derived> DenseBase<Derived> + ::topRightCorner(int cRows, int cCols) +{ + return Block<Derived>(derived(), 0, cols() - cCols, cRows, cCols); +} + +/** This is the const version of topRightCorner(int, int).*/ +template<typename Derived> +inline const Block<Derived> +DenseBase<Derived>::topRightCorner(int cRows, int cCols) const +{ + return Block<Derived>(derived(), 0, cols() - cCols, cRows, cCols); +} + +/** \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. + * + * Example: \include MatrixBase_template_int_int_topRightCorner.cpp + * Output: \verbinclude MatrixBase_template_int_int_topRightCorner.out * * \sa class Block, block(int,int,int,int) */ template<typename Derived> -inline typename BlockReturnType<Derived>::Type DenseBase<Derived> - ::corner(CornerType type, int cRows, int cCols) +template<int CRows, int CCols> +inline Block<Derived, CRows, CCols> +DenseBase<Derived>::topRightCorner() { - switch(type) - { - default: - ei_assert(false && "Bad corner type."); - case TopLeft: - return typename BlockReturnType<Derived>::Type(derived(), 0, 0, cRows, cCols); - case TopRight: - return typename BlockReturnType<Derived>::Type(derived(), 0, cols() - cCols, cRows, cCols); - case BottomLeft: - return typename BlockReturnType<Derived>::Type(derived(), rows() - cRows, 0, cRows, cCols); - case BottomRight: - return typename BlockReturnType<Derived>::Type(derived(), rows() - cRows, cols() - cCols, cRows, cCols); - } + return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols); } -/** This is the const version of corner(CornerType, int, int).*/ +/** This is the const version of topRightCorner<int, int>().*/ template<typename Derived> -inline const typename BlockReturnType<Derived>::Type -DenseBase<Derived>::corner(CornerType type, int cRows, int cCols) const +template<int CRows, int CCols> +inline const Block<Derived, CRows, CCols> +DenseBase<Derived>::topRightCorner() const { - switch(type) - { - default: - ei_assert(false && "Bad corner type."); - case TopLeft: - return typename BlockReturnType<Derived>::Type(derived(), 0, 0, cRows, cCols); - case TopRight: - return typename BlockReturnType<Derived>::Type(derived(), 0, cols() - cCols, cRows, cCols); - case BottomLeft: - return typename BlockReturnType<Derived>::Type(derived(), rows() - cRows, 0, cRows, cCols); - case BottomRight: - return typename BlockReturnType<Derived>::Type(derived(), rows() - cRows, cols() - cCols, cRows, cCols); - } + return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols); } -/** \returns a fixed-size expression of a corner of *this. + + + +/** \returns a dynamic-size expression of a top-left corner of *this. * - * \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight, - * \a Eigen::BottomLeft, \a Eigen::BottomRight. + * \param cRows the number of rows in the corner + * \param cCols the number of columns in the corner * - * The template parameters CRows and CCols arethe number of rows and columns in the corner. + * Example: \include MatrixBase_topLeftCorner_int_int.cpp + * Output: \verbinclude MatrixBase_topLeftCorner_int_int.out * - * Example: \include MatrixBase_template_int_int_corner_enum.cpp - * Output: \verbinclude MatrixBase_template_int_int_corner_enum.out + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +inline Block<Derived> DenseBase<Derived> + ::topLeftCorner(int cRows, int cCols) +{ + return Block<Derived>(derived(), 0, 0, cRows, cCols); +} + +/** This is the const version of topLeftCorner(int, int).*/ +template<typename Derived> +inline const Block<Derived> +DenseBase<Derived>::topLeftCorner(int cRows, int cCols) const +{ + return Block<Derived>(derived(), 0, 0, cRows, cCols); +} + +/** \returns an expression of a fixed-size top-left corner of *this. + * + * The template parameters CRows and CCols are the number of rows and columns in the corner. + * + * Example: \include MatrixBase_template_int_int_topLeftCorner.cpp + * Output: \verbinclude MatrixBase_template_int_int_topLeftCorner.out * * \sa class Block, block(int,int,int,int) */ template<typename Derived> template<int CRows, int CCols> -inline typename BlockReturnType<Derived, CRows, CCols>::Type -DenseBase<Derived>::corner(CornerType type) +inline Block<Derived, CRows, CCols> +DenseBase<Derived>::topLeftCorner() { - switch(type) - { - default: - ei_assert(false && "Bad corner type."); - case TopLeft: - return Block<Derived, CRows, CCols>(derived(), 0, 0); - case TopRight: - return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols); - case BottomLeft: - return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0); - case BottomRight: - return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols); - } + return Block<Derived, CRows, CCols>(derived(), 0, 0); } -/** This is the const version of corner<int, int>(CornerType).*/ +/** This is the const version of topLeftCorner<int, int>().*/ template<typename Derived> template<int CRows, int CCols> -inline const typename BlockReturnType<Derived, CRows, CCols>::Type -DenseBase<Derived>::corner(CornerType type) const +inline const Block<Derived, CRows, CCols> +DenseBase<Derived>::topLeftCorner() const { - switch(type) - { - default: - ei_assert(false && "Bad corner type."); - case TopLeft: - return Block<Derived, CRows, CCols>(derived(), 0, 0); - case TopRight: - return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols); - case BottomLeft: - return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0); - case BottomRight: - return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols); - } + return Block<Derived, CRows, CCols>(derived(), 0, 0); +} + + + + + + +/** \returns a dynamic-size expression of a bottom-right corner of *this. + * + * \param cRows the number of rows in the corner + * \param cCols the number of columns in the corner + * + * Example: \include MatrixBase_bottomRightCorner_int_int.cpp + * Output: \verbinclude MatrixBase_bottomRightCorner_int_int.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +inline Block<Derived> DenseBase<Derived> + ::bottomRightCorner(int cRows, int cCols) +{ + return Block<Derived>(derived(), rows() - cRows, cols() - cCols, cRows, cCols); +} + +/** This is the const version of bottomRightCorner(int, int).*/ +template<typename Derived> +inline const Block<Derived> +DenseBase<Derived>::bottomRightCorner(int cRows, int cCols) const +{ + return Block<Derived>(derived(), rows() - cRows, cols() - cCols, cRows, cCols); +} + +/** \returns an expression of a fixed-size bottom-right corner of *this. + * + * The template parameters CRows and CCols are the number of rows and columns in the corner. + * + * Example: \include MatrixBase_template_int_int_bottomRightCorner.cpp + * Output: \verbinclude MatrixBase_template_int_int_bottomRightCorner.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +template<int CRows, int CCols> +inline Block<Derived, CRows, CCols> +DenseBase<Derived>::bottomRightCorner() +{ + return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols); +} + +/** This is the const version of bottomRightCorner<int, int>().*/ +template<typename Derived> +template<int CRows, int CCols> +inline const Block<Derived, CRows, CCols> +DenseBase<Derived>::bottomRightCorner() const +{ + return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols); +} + + + + +/** \returns a dynamic-size expression of a bottom-left corner of *this. + * + * \param cRows the number of rows in the corner + * \param cCols the number of columns in the corner + * + * Example: \include MatrixBase_bottomLeftCorner_int_int.cpp + * Output: \verbinclude MatrixBase_bottomLeftCorner_int_int.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +inline Block<Derived> DenseBase<Derived> + ::bottomLeftCorner(int cRows, int cCols) +{ + return Block<Derived>(derived(), rows() - cRows, 0, cRows, cCols); +} + +/** This is the const version of bottomLeftCorner(int, int).*/ +template<typename Derived> +inline const Block<Derived> +DenseBase<Derived>::bottomLeftCorner(int cRows, int cCols) const +{ + return Block<Derived>(derived(), rows() - cRows, 0, cRows, cCols); +} + +/** \returns an expression of a fixed-size bottom-left corner of *this. + * + * The template parameters CRows and CCols are the number of rows and columns in the corner. + * + * Example: \include MatrixBase_template_int_int_bottomLeftCorner.cpp + * Output: \verbinclude MatrixBase_template_int_int_bottomLeftCorner.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +template<int CRows, int CCols> +inline Block<Derived, CRows, CCols> +DenseBase<Derived>::bottomLeftCorner() +{ + return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0); +} + +/** This is the const version of bottomLeftCorner<int, int>().*/ +template<typename Derived> +template<int CRows, int CCols> +inline const Block<Derived, CRows, CCols> +DenseBase<Derived>::bottomLeftCorner() const +{ + return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0); +} + + + +/** \returns a block consisting of the top rows of *this. + * + * \param n the number of rows in the block + * + * Example: \include MatrixBase_topRows_int.cpp + * Output: \verbinclude MatrixBase_topRows_int.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +inline typename DenseBase<Derived>::RowsBlockXpr DenseBase<Derived> + ::topRows(int n) +{ + return RowsBlockXpr(derived(), 0, 0, n, cols()); +} + +/** This is the const version of topRows(int).*/ +template<typename Derived> +inline const typename DenseBase<Derived>::RowsBlockXpr +DenseBase<Derived>::topRows(int n) const +{ + return RowsBlockXpr(derived(), 0, 0, n, cols()); +} + +/** \returns a block consisting of the top rows of *this. + * + * \param N the number of rows in the block + * + * Example: \include MatrixBase_template_int_topRows.cpp + * Output: \verbinclude MatrixBase_template_int_topRows.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +template<int N> +inline typename DenseBase<Derived>::template NRowsBlockXpr<N>::Type +DenseBase<Derived>::topRows() +{ + return typename DenseBase<Derived>::template NRowsBlockXpr<N>::Type(derived(), 0, 0, N, cols()); +} + +/** This is the const version of topRows<int>().*/ +template<typename Derived> +template<int N> +inline const typename DenseBase<Derived>::template NRowsBlockXpr<N>::Type +DenseBase<Derived>::topRows() const +{ + return typename DenseBase<Derived>::template NRowsBlockXpr<N>::Type(derived(), 0, 0, N, cols()); } + + + + +/** \returns a block consisting of the bottom rows of *this. + * + * \param n the number of rows in the block + * + * Example: \include MatrixBase_bottomRows_int.cpp + * Output: \verbinclude MatrixBase_bottomRows_int.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +inline typename DenseBase<Derived>::RowsBlockXpr DenseBase<Derived> + ::bottomRows(int n) +{ + return RowsBlockXpr(derived(), rows() - n, 0, n, cols()); +} + +/** This is the const version of bottomRows(int).*/ +template<typename Derived> +inline const typename DenseBase<Derived>::RowsBlockXpr +DenseBase<Derived>::bottomRows(int n) const +{ + return RowsBlockXpr(derived(), rows() - n, 0, n, cols()); +} + +/** \returns a block consisting of the bottom rows of *this. + * + * \param N the number of rows in the block + * + * Example: \include MatrixBase_template_int_bottomRows.cpp + * Output: \verbinclude MatrixBase_template_int_bottomRows.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +template<int N> +inline typename DenseBase<Derived>::template NRowsBlockXpr<N>::Type +DenseBase<Derived>::bottomRows() +{ + return typename NRowsBlockXpr<N>::Type(derived(), rows() - N, 0, N, cols()); +} + +/** This is the const version of bottomRows<int>().*/ +template<typename Derived> +template<int N> +inline const typename DenseBase<Derived>::template NRowsBlockXpr<N>::Type +DenseBase<Derived>::bottomRows() const +{ + return typename NRowsBlockXpr<N>::Type(derived(), rows() - N, 0, N, cols()); +} + + + + + +/** \returns a block consisting of the top columns of *this. + * + * \param n the number of columns in the block + * + * Example: \include MatrixBase_leftCols_int.cpp + * Output: \verbinclude MatrixBase_leftCols_int.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +inline typename DenseBase<Derived>::ColsBlockXpr DenseBase<Derived> + ::leftCols(int n) +{ + return ColsBlockXpr(derived(), 0, 0, rows(), n); +} + +/** This is the const version of leftCols(int).*/ +template<typename Derived> +inline const typename DenseBase<Derived>::ColsBlockXpr +DenseBase<Derived>::leftCols(int n) const +{ + return ColsBlockXpr(derived(), 0, 0, rows(), n); +} + +/** \returns a block consisting of the top columns of *this. + * + * \param N the number of columns in the block + * + * Example: \include MatrixBase_template_int_leftCols.cpp + * Output: \verbinclude MatrixBase_template_int_leftCols.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +template<int N> +inline typename DenseBase<Derived>::template NColsBlockXpr<N>::Type +DenseBase<Derived>::leftCols() +{ + return typename NColsBlockXpr<N>::Type(derived(), 0, 0, rows(), N); +} + +/** This is the const version of leftCols<int>().*/ +template<typename Derived> +template<int N> +inline const typename DenseBase<Derived>::template NColsBlockXpr<N>::Type +DenseBase<Derived>::leftCols() const +{ + return typename NColsBlockXpr<N>::Type(derived(), 0, 0, rows(), N); +} + + + + + +/** \returns a block consisting of the top columns of *this. + * + * \param n the number of columns in the block + * + * Example: \include MatrixBase_rightCols_int.cpp + * Output: \verbinclude MatrixBase_rightCols_int.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +inline typename DenseBase<Derived>::ColsBlockXpr DenseBase<Derived> + ::rightCols(int n) +{ + return ColsBlockXpr(derived(), 0, cols() - n, rows(), n); +} + +/** This is the const version of rightCols(int).*/ +template<typename Derived> +inline const typename DenseBase<Derived>::ColsBlockXpr +DenseBase<Derived>::rightCols(int n) const +{ + return ColsBlockXpr(derived(), 0, cols() - n, rows(), n); +} + +/** \returns a block consisting of the top columns of *this. + * + * \param N the number of columns in the block + * + * Example: \include MatrixBase_template_int_rightCols.cpp + * Output: \verbinclude MatrixBase_template_int_rightCols.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +template<int N> +inline typename DenseBase<Derived>::template NColsBlockXpr<N>::Type +DenseBase<Derived>::rightCols() +{ + return typename DenseBase<Derived>::template NColsBlockXpr<N>::Type(derived(), 0, cols() - N, rows(), N); +} + +/** This is the const version of rightCols<int>().*/ +template<typename Derived> +template<int N> +inline const typename DenseBase<Derived>::template NColsBlockXpr<N>::Type +DenseBase<Derived>::rightCols() const +{ + return typename DenseBase<Derived>::template NColsBlockXpr<N>::Type(derived(), 0, cols() - N, rows(), N); +} + + + + + /** \returns a fixed-size expression of a block in *this. * * The template parameters \a BlockRows and \a BlockCols are the number of @@ -468,7 +796,7 @@ DenseBase<Derived>::corner(CornerType type) const */ template<typename Derived> template<int BlockRows, int BlockCols> -inline typename BlockReturnType<Derived, BlockRows, BlockCols>::Type +inline Block<Derived, BlockRows, BlockCols> DenseBase<Derived>::block(int startRow, int startCol) { return Block<Derived, BlockRows, BlockCols>(derived(), startRow, startCol); @@ -477,7 +805,7 @@ DenseBase<Derived>::block(int startRow, int startCol) /** This is the const version of block<>(int, int). */ template<typename Derived> template<int BlockRows, int BlockCols> -inline const typename BlockReturnType<Derived, BlockRows, BlockCols>::Type +inline const Block<Derived, BlockRows, BlockCols> DenseBase<Derived>::block(int startRow, int startCol) const { return Block<Derived, BlockRows, BlockCols>(derived(), startRow, startCol); @@ -525,4 +853,116 @@ DenseBase<Derived>::row(int i) const return RowXpr(derived(), i); } +#ifdef EIGEN2_SUPPORT + +/** \returns a dynamic-size expression of a corner of *this. + * + * \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight, + * \a Eigen::BottomLeft, \a Eigen::BottomRight. + * \param cRows the number of rows in the corner + * \param cCols the number of columns in the corner + * + * Example: \include MatrixBase_corner_enum_int_int.cpp + * Output: \verbinclude MatrixBase_corner_enum_int_int.out + * + * \note Even though the returned expression has dynamic size, in the case + * when it is applied to a fixed-size matrix, it inherits a fixed maximal size, + * which means that evaluating it does not cause a dynamic memory allocation. + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +inline Block<Derived> DenseBase<Derived> + ::corner(CornerType type, int cRows, int cCols) +{ + switch(type) + { + default: + ei_assert(false && "Bad corner type."); + case TopLeft: + return Block<Derived>(derived(), 0, 0, cRows, cCols); + case TopRight: + return Block<Derived>(derived(), 0, cols() - cCols, cRows, cCols); + case BottomLeft: + return Block<Derived>(derived(), rows() - cRows, 0, cRows, cCols); + case BottomRight: + return Block<Derived>(derived(), rows() - cRows, cols() - cCols, cRows, cCols); + } +} + +/** This is the const version of corner(CornerType, int, int).*/ +template<typename Derived> +inline const Block<Derived> +DenseBase<Derived>::corner(CornerType type, int cRows, int cCols) const +{ + switch(type) + { + default: + ei_assert(false && "Bad corner type."); + case TopLeft: + return Block<Derived>(derived(), 0, 0, cRows, cCols); + case TopRight: + return Block<Derived>(derived(), 0, cols() - cCols, cRows, cCols); + case BottomLeft: + return Block<Derived>(derived(), rows() - cRows, 0, cRows, cCols); + case BottomRight: + return Block<Derived>(derived(), rows() - cRows, cols() - cCols, cRows, cCols); + } +} + +/** \returns a fixed-size expression of a corner of *this. + * + * \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight, + * \a Eigen::BottomLeft, \a Eigen::BottomRight. + * + * The template parameters CRows and CCols arethe number of rows and columns in the corner. + * + * Example: \include MatrixBase_template_int_int_corner_enum.cpp + * Output: \verbinclude MatrixBase_template_int_int_corner_enum.out + * + * \sa class Block, block(int,int,int,int) + */ +template<typename Derived> +template<int CRows, int CCols> +inline Block<Derived, CRows, CCols> +DenseBase<Derived>::corner(CornerType type) +{ + switch(type) + { + default: + ei_assert(false && "Bad corner type."); + case TopLeft: + return Block<Derived, CRows, CCols>(derived(), 0, 0); + case TopRight: + return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols); + case BottomLeft: + return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0); + case BottomRight: + return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols); + } +} + +/** This is the const version of corner<int, int>(CornerType).*/ +template<typename Derived> +template<int CRows, int CCols> +inline const Block<Derived, CRows, CCols> +DenseBase<Derived>::corner(CornerType type) const +{ + switch(type) + { + default: + ei_assert(false && "Bad corner type."); + case TopLeft: + return Block<Derived, CRows, CCols>(derived(), 0, 0); + case TopRight: + return Block<Derived, CRows, CCols>(derived(), 0, cols() - CCols); + case BottomLeft: + return Block<Derived, CRows, CCols>(derived(), rows() - CRows, 0); + case BottomRight: + return Block<Derived, CRows, CCols>(derived(), rows() - CRows, cols() - CCols); + } +} + +#endif // EIGEN2_SUPPORT + #endif // EIGEN_BLOCK_H diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index 566b4b410..da464067b 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -220,8 +220,18 @@ template<typename Derived> class DenseBase typedef Matrix<typename NumTraits<typename ei_traits<Derived>::Scalar>::Real, ei_traits<Derived>::ColsAtCompileTime, 1> EigenvaluesReturnType; /** \internal expression type of a column */ typedef Block<Derived, ei_traits<Derived>::RowsAtCompileTime, 1> ColXpr; - /** \internal expression type of a column */ + /** \internal expression type of a row */ typedef Block<Derived, 1, ei_traits<Derived>::ColsAtCompileTime> RowXpr; + /** \internal expression type of a block of whole columns */ + typedef Block<Derived, ei_traits<Derived>::RowsAtCompileTime, Dynamic> ColsBlockXpr; + /** \internal expression type of a block of whole rows */ + typedef Block<Derived, Dynamic, ei_traits<Derived>::ColsAtCompileTime> RowsBlockXpr; + /** \internal expression type of a block of whole columns */ + template<int N> struct NColsBlockXpr { typedef Block<Derived, ei_traits<Derived>::RowsAtCompileTime, N> Type; }; + /** \internal expression type of a block of whole rows */ + template<int N> struct NRowsBlockXpr { typedef Block<Derived, N, ei_traits<Derived>::ColsAtCompileTime> Type; }; + + #endif // not EIGEN_PARSED_BY_DOXYGEN const CoeffReturnType x() const; @@ -334,9 +344,8 @@ template<typename Derived> class DenseBase ColXpr col(int i); const ColXpr col(int i) const; - typename BlockReturnType<Derived>::Type block(int startRow, int startCol, int blockRows, int blockCols); - const typename BlockReturnType<Derived>::Type - block(int startRow, int startCol, int blockRows, int blockCols) const; + Block<Derived> block(int startRow, int startCol, int blockRows, int blockCols); + const Block<Derived> block(int startRow, int startCol, int blockRows, int blockCols) const; VectorBlock<Derived> segment(int start, int size); const VectorBlock<Derived> segment(int start, int size) const; @@ -347,18 +356,46 @@ template<typename Derived> class DenseBase VectorBlock<Derived> tail(int size); const VectorBlock<Derived> tail(int size) const; - typename BlockReturnType<Derived>::Type corner(CornerType type, int cRows, int cCols); - const typename BlockReturnType<Derived>::Type corner(CornerType type, int cRows, int cCols) const; + Block<Derived> topLeftCorner(int cRows, int cCols); + const Block<Derived> topLeftCorner(int cRows, int cCols) const; + Block<Derived> topRightCorner(int cRows, int cCols); + const Block<Derived> topRightCorner(int cRows, int cCols) const; + Block<Derived> bottomLeftCorner(int cRows, int cCols); + const Block<Derived> bottomLeftCorner(int cRows, int cCols) const; + Block<Derived> bottomRightCorner(int cRows, int cCols); + const Block<Derived> bottomRightCorner(int cRows, int cCols) const; + + RowsBlockXpr topRows(int n); + const RowsBlockXpr topRows(int n) const; + RowsBlockXpr bottomRows(int n); + const RowsBlockXpr bottomRows(int n) const; + ColsBlockXpr leftCols(int n); + const ColsBlockXpr leftCols(int n) const; + ColsBlockXpr rightCols(int n); + const ColsBlockXpr rightCols(int n) const; + + template<int CRows, int CCols> Block<Derived, CRows, CCols> topLeftCorner(); + template<int CRows, int CCols> const Block<Derived, CRows, CCols> topLeftCorner() const; + template<int CRows, int CCols> Block<Derived, CRows, CCols> topRightCorner(); + template<int CRows, int CCols> const Block<Derived, CRows, CCols> topRightCorner() const; + template<int CRows, int CCols> Block<Derived, CRows, CCols> bottomLeftCorner(); + template<int CRows, int CCols> const Block<Derived, CRows, CCols> bottomLeftCorner() const; + template<int CRows, int CCols> Block<Derived, CRows, CCols> bottomRightCorner(); + template<int CRows, int CCols> const Block<Derived, CRows, CCols> bottomRightCorner() const; + + template<int NRows> typename NRowsBlockXpr<NRows>::Type topRows(); + 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 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 BlockRows, int BlockCols> - typename BlockReturnType<Derived, BlockRows, BlockCols>::Type block(int startRow, int startCol); + Block<Derived, BlockRows, BlockCols> block(int startRow, int startCol); template<int BlockRows, int BlockCols> - const typename BlockReturnType<Derived, BlockRows, BlockCols>::Type block(int startRow, int startCol) const; - - template<int CRows, int CCols> - typename BlockReturnType<Derived, CRows, CCols>::Type corner(CornerType type); - template<int CRows, int CCols> - const typename BlockReturnType<Derived, CRows, CCols>::Type corner(CornerType type) const; + const Block<Derived, BlockRows, BlockCols> block(int startRow, int startCol) const; template<int Size> VectorBlock<Derived,Size> head(void); template<int Size> const VectorBlock<Derived,Size> head() const; @@ -523,6 +560,17 @@ template<typename Derived> class DenseBase const Eigen::Reverse<Derived, BothDirections> reverse() const; void reverseInPlace(); +#ifdef EIGEN2_SUPPORT + + Block<Derived> corner(CornerType type, int cRows, int cCols); + const Block<Derived> corner(CornerType type, int cRows, int cCols) const; + template<int CRows, int CCols> + Block<Derived, CRows, CCols> corner(CornerType type); + template<int CRows, int CCols> + const Block<Derived, CRows, CCols> corner(CornerType type) const; + +#endif // EIGEN2_SUPPORT + #ifdef EIGEN_DENSEBASE_PLUGIN #include EIGEN_DENSEBASE_PLUGIN #endif diff --git a/Eigen/src/Core/DenseStorageBase.h b/Eigen/src/Core/DenseStorageBase.h index 687c76cf8..220cd86c7 100644 --- a/Eigen/src/Core/DenseStorageBase.h +++ b/Eigen/src/Core/DenseStorageBase.h @@ -566,9 +566,9 @@ struct ei_conservative_resize_like_impl const int new_cols = other.cols() - _this.cols(); _this.derived().m_storage.conservativeResize(other.size(),other.rows(),other.cols()); if (new_rows>0) - _this.corner(BottomRight, new_rows, other.cols()) = other.corner(BottomRight, new_rows, other.cols()); + _this.bottomRightCorner(new_rows, other.cols()) = other.bottomRows(new_rows); else if (new_cols>0) - _this.corner(BottomRight, other.rows(), new_cols) = other.corner(BottomRight, other.rows(), new_cols); + _this.bottomRightCorner(other.rows(), new_cols) = other.rightCols(new_cols); } else { diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h index 51c3dd287..023ef3852 100644 --- a/Eigen/src/Core/util/Constants.h +++ b/Eigen/src/Core/util/Constants.h @@ -165,7 +165,11 @@ enum { enum { Unaligned=0, Aligned=1 }; enum { ConditionalJumpCost = 5 }; + +// FIXME after the corner() API change, this was not needed anymore, except by AlignedBox +// TODO: find out what to do with that. Adapt the AlignedBox API ? enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight }; + enum DirectionType { Vertical, Horizontal, BothDirections }; enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct }; diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h index 4eb132cf7..f895dad1c 100644 --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -329,13 +329,6 @@ struct ei_special_scalar_op_base<Derived,Scalar,OtherScalar,true> : public Eige { return static_cast<const ei_special_scalar_op_base&>(matrix).operator*(scalar); } }; -/** \internal Gives the type of a sub-matrix or sub-vector of a matrix of type \a ExpressionType and size \a Size - * TODO: could be a good idea to define a big ReturnType struct ?? - */ -template<typename ExpressionType, int RowsOrSize=Dynamic, int Cols=Dynamic> struct BlockReturnType { - typedef Block<ExpressionType, RowsOrSize, Cols> Type; -}; - template<typename ExpressionType> struct HNormalizedReturnType { enum { diff --git a/Eigen/src/Eigenvalues/HessenbergDecomposition.h b/Eigen/src/Eigenvalues/HessenbergDecomposition.h index 451604252..a1ac31981 100644 --- a/Eigen/src/Eigenvalues/HessenbergDecomposition.h +++ b/Eigen/src/Eigenvalues/HessenbergDecomposition.h @@ -272,11 +272,11 @@ void HessenbergDecomposition<MatrixType>::_compute(MatrixType& matA, CoeffVector // i.e., compute A = H A H' // A = H A - matA.corner(BottomRight, remainingSize, remainingSize) + matA.bottomRightCorner(remainingSize, remainingSize) .applyHouseholderOnTheLeft(matA.col(i).tail(remainingSize-1), h, &temp.coeffRef(0)); // A = A H' - matA.corner(BottomRight, n, remainingSize) + matA.rightCols(remainingSize) .applyHouseholderOnTheRight(matA.col(i).tail(remainingSize-1).conjugate(), ei_conj(h), &temp.coeffRef(0)); } } @@ -290,7 +290,7 @@ HessenbergDecomposition<MatrixType>::matrixQ() const VectorType temp(n); for (int i = n-2; i>=0; i--) { - matQ.corner(BottomRight,n-i-1,n-i-1) + matQ.bottomRightCorner(n-i-1,n-i-1) .applyHouseholderOnTheLeft(m_matrix.col(i).tail(n-i-2), ei_conj(m_hCoeffs.coeff(i)), &temp.coeffRef(0,0)); } return matQ; @@ -307,7 +307,7 @@ HessenbergDecomposition<MatrixType>::matrixH() const int n = m_matrix.rows(); MatrixType matH = m_matrix; if (n>2) - matH.corner(BottomLeft,n-2, n-2).template triangularView<Lower>().setZero(); + matH.bottomLeftCorner(n-2, n-2).template triangularView<Lower>().setZero(); return matH; } diff --git a/Eigen/src/Eigenvalues/RealSchur.h b/Eigen/src/Eigenvalues/RealSchur.h index dd4a1ab7e..c2835f1fb 100644 --- a/Eigen/src/Eigenvalues/RealSchur.h +++ b/Eigen/src/Eigenvalues/RealSchur.h @@ -249,7 +249,7 @@ inline typename MatrixType::Scalar RealSchur<MatrixType>::computeNormOfT() const int size = m_matU.cols(); // FIXME to be efficient the following would requires a triangular reduxion code // Scalar norm = m_matT.upper().cwiseAbs().sum() - // + m_matT.corner(BottomLeft,size-1,size-1).diagonal().cwiseAbs().sum(); + // + m_matT.bottomLeftCorner(size-1,size-1).diagonal().cwiseAbs().sum(); Scalar norm = 0.0; for (int j = 0; j < size; ++j) norm += m_matT.row(j).segment(std::max(j-1,0), size-std::max(j-1,0)).cwiseAbs().sum(); diff --git a/Eigen/src/Eigenvalues/Tridiagonalization.h b/Eigen/src/Eigenvalues/Tridiagonalization.h index c320242ef..a41a5f670 100644 --- a/Eigen/src/Eigenvalues/Tridiagonalization.h +++ b/Eigen/src/Eigenvalues/Tridiagonalization.h @@ -171,11 +171,11 @@ Tridiagonalization<MatrixType>::matrixT(void) const // and fill it ? (to avoid temporaries) int n = m_matrix.rows(); MatrixType matT = m_matrix; - matT.corner(TopRight,n-1, n-1).diagonal() = subDiagonal().template cast<Scalar>().conjugate(); + matT.topRightCorner(n-1, n-1).diagonal() = subDiagonal().template cast<Scalar>().conjugate(); if (n>2) { - matT.corner(TopRight,n-2, n-2).template triangularView<Upper>().setZero(); - matT.corner(BottomLeft,n-2, n-2).template triangularView<Lower>().setZero(); + matT.topRightCorner(n-2, n-2).template triangularView<Upper>().setZero(); + matT.bottomLeftCorner(n-2, n-2).template triangularView<Lower>().setZero(); } return matT; } @@ -210,12 +210,12 @@ void Tridiagonalization<MatrixType>::_compute(MatrixType& matA, CoeffVectorType& // i.e., A = H A H' where H = I - h v v' and v = matA.col(i).tail(n-i-1) matA.col(i).coeffRef(i+1) = 1; - hCoeffs.tail(n-i-1).noalias() = (matA.corner(BottomRight,remainingSize,remainingSize).template selfadjointView<Lower>() + hCoeffs.tail(n-i-1).noalias() = (matA.bottomRightCorner(remainingSize,remainingSize).template selfadjointView<Lower>() * (ei_conj(h) * matA.col(i).tail(remainingSize))); hCoeffs.tail(n-i-1) += (ei_conj(h)*Scalar(-0.5)*(hCoeffs.tail(remainingSize).dot(matA.col(i).tail(remainingSize)))) * matA.col(i).tail(n-i-1); - matA.corner(BottomRight, remainingSize, remainingSize).template selfadjointView<Lower>() + matA.bottomRightCorner(remainingSize, remainingSize).template selfadjointView<Lower>() .rankUpdate(matA.col(i).tail(remainingSize), hCoeffs.tail(remainingSize), -1); matA.col(i).coeffRef(i+1) = beta; @@ -243,7 +243,7 @@ void Tridiagonalization<MatrixType>::matrixQInPlace(MatrixBase<QDerived>* q) con RowVectorType aux(n); for (int i = n-2; i>=0; i--) { - matQ.corner(BottomRight,n-i-1,n-i-1) + matQ.bottomRightCorner(n-i-1,n-i-1) .applyHouseholderOnTheLeft(m_matrix.col(i).tail(n-i-2), ei_conj(m_hCoeffs.coeff(i)), &aux.coeffRef(0,0)); } } diff --git a/Eigen/src/Geometry/Transform.h b/Eigen/src/Geometry/Transform.h index 1240a95bc..1f4db8098 100644 --- a/Eigen/src/Geometry/Transform.h +++ b/Eigen/src/Geometry/Transform.h @@ -653,7 +653,7 @@ Transform<Scalar,Dim,Mode>::prescale(const MatrixBase<OtherDerived> &other) template<typename Scalar, int Dim, int Mode> inline Transform<Scalar,Dim,Mode>& Transform<Scalar,Dim,Mode>::prescale(Scalar s) { - m_matrix.template corner<Dim,HDim>(TopLeft) *= s; + m_matrix.template topRows<Dim>() *= s; return *this; } @@ -940,18 +940,19 @@ Transform<Scalar,Dim,Mode>::inverse(TransformTraits hint) const { if (hint == Isometry) { - res.matrix().template corner<Dim,Dim>(TopLeft) = linear().transpose(); + res.matrix().template topLeftCorner<Dim,Dim>() = linear().transpose(); } else if(hint&Affine) { - res.matrix().template corner<Dim,Dim>(TopLeft) = linear().inverse(); + res.matrix().template topLeftCorner<Dim,Dim>() = linear().inverse(); } else { ei_assert(false && "Invalid transform traits in Transform::Inverse"); } // translation and remaining parts - res.matrix().template corner<Dim,1>(TopRight) = - res.matrix().template corner<Dim,Dim>(TopLeft) * translation(); + res.matrix().template topRightCorner<Dim,1>() + = - res.matrix().template topLeftCorner<Dim,Dim>() * translation(); if(int(Mode)!=int(AffineCompact)) { res.matrix().template block<1,Dim>(Dim,0).setZero(); @@ -1247,8 +1248,8 @@ struct ei_transform_left_product_impl<Other,Mode,Dim,HDim, Dim,Dim> TransformType res; if(Mode!=AffineCompact) res.matrix().row(Dim) = tr.matrix().row(Dim); - res.matrix().template corner<Dim,HDim>(TopLeft).noalias() - = other * tr.matrix().template corner<Dim,HDim>(TopLeft); + res.matrix().template topRows<Dim>().noalias() + = other * tr.matrix().template topRows<Dim>(); return res; } }; diff --git a/Eigen/src/Geometry/Umeyama.h b/Eigen/src/Geometry/Umeyama.h index c5d99d533..262d27aa3 100644 --- a/Eigen/src/Geometry/Umeyama.h +++ b/Eigen/src/Geometry/Umeyama.h @@ -171,7 +171,7 @@ umeyama(const MatrixBase<Derived>& src, const MatrixBase<OtherDerived>& dst, boo // Note that we first assign dst_mean to the destination so that there no need // for a temporary. Rt.col(m).head(m) = dst_mean; - Rt.col(m).head(m).noalias() -= c*Rt.corner(TopLeft,m,m)*src_mean; + Rt.col(m).head(m).noalias() -= c*Rt.topLeftCorner(m,m)*src_mean; if (with_scaling) Rt.block(0,0,m,m) *= c; diff --git a/Eigen/src/Householder/HouseholderSequence.h b/Eigen/src/Householder/HouseholderSequence.h index 05e883168..4bac484eb 100644 --- a/Eigen/src/Householder/HouseholderSequence.h +++ b/Eigen/src/Householder/HouseholderSequence.h @@ -161,10 +161,10 @@ template<typename VectorsType, typename CoeffsType, int Side> class HouseholderS { int cornerSize = rows() - k - m_shift; if(m_trans) - dst.corner(BottomRight, cornerSize, cornerSize) + dst.bottomRightCorner(cornerSize, cornerSize) .applyHouseholderOnTheRight(essentialVector(k), m_coeffs.coeff(k), &temp.coeffRef(0)); else - dst.corner(BottomRight, cornerSize, cornerSize) + dst.bottomRightCorner(cornerSize, cornerSize) .applyHouseholderOnTheLeft(essentialVector(k), m_coeffs.coeff(k), &temp.coeffRef(0)); } } @@ -176,7 +176,7 @@ template<typename VectorsType, typename CoeffsType, int Side> class HouseholderS for(int k = 0; k < m_actualVectors; ++k) { int actual_k = m_trans ? m_actualVectors-k-1 : k; - dst.corner(BottomRight, dst.rows(), rows()-m_shift-actual_k) + dst.rightCols(rows()-m_shift-actual_k) .applyHouseholderOnTheRight(essentialVector(actual_k), m_coeffs.coeff(actual_k), &temp.coeffRef(0)); } } @@ -188,7 +188,7 @@ template<typename VectorsType, typename CoeffsType, int Side> class HouseholderS for(int k = 0; k < m_actualVectors; ++k) { int actual_k = m_trans ? k : m_actualVectors-k-1; - dst.corner(BottomRight, rows()-m_shift-actual_k, dst.cols()) + dst.bottomRows(rows()-m_shift-actual_k) .applyHouseholderOnTheLeft(essentialVector(actual_k), m_coeffs.coeff(actual_k), &temp.coeffRef(0)); } } diff --git a/Eigen/src/LU/FullPivLU.h b/Eigen/src/LU/FullPivLU.h index 241fb9d16..1b0e67b3a 100644 --- a/Eigen/src/LU/FullPivLU.h +++ b/Eigen/src/LU/FullPivLU.h @@ -450,7 +450,7 @@ FullPivLU<MatrixType>& FullPivLU<MatrixType>::compute(const MatrixType& matrix) // biggest coefficient in the remaining bottom-right corner (starting at row k, col k) int row_of_biggest_in_corner, col_of_biggest_in_corner; RealScalar biggest_in_corner; - biggest_in_corner = m_lu.corner(Eigen::BottomRight, rows-k, cols-k) + biggest_in_corner = m_lu.bottomRightCorner(rows-k, cols-k) .cwiseAbs() .maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner); row_of_biggest_in_corner += k; // correct the values! since they were computed in the corner, @@ -535,9 +535,9 @@ MatrixType FullPivLU<MatrixType>::reconstructedMatrix() const // LU MatrixType res(m_lu.rows(),m_lu.cols()); // FIXME the .toDenseMatrix() should not be needed... - res = m_lu.corner(TopLeft,m_lu.rows(),smalldim) + res = m_lu.leftCols(smalldim) .template triangularView<UnitLower>().toDenseMatrix() - * m_lu.corner(TopLeft,smalldim,m_lu.cols()) + * m_lu.topRows(smalldim) .template triangularView<Upper>().toDenseMatrix(); // P^{-1}(LU) @@ -618,9 +618,9 @@ struct ei_kernel_retval<FullPivLU<_MatrixType> > // ok, we have our trapezoid matrix, we can apply the triangular solver. // notice that the math behind this suggests that we should apply this to the // negative of the RHS, but for performance we just put the negative sign elsewhere, see below. - m.corner(TopLeft, rank(), rank()) + m.topLeftCorner(rank(), rank()) .template triangularView<Upper>().solveInPlace( - m.corner(TopRight, rank(), dimker) + m.topRightCorner(rank(), dimker) ); // now we must undo the column permutation that we had applied! @@ -707,21 +707,21 @@ struct ei_solve_retval<FullPivLU<_MatrixType>, Rhs> // Step 2 dec().matrixLU() - .corner(Eigen::TopLeft,smalldim,smalldim) + .topLeftCorner(smalldim,smalldim) .template triangularView<UnitLower>() - .solveInPlace(c.corner(Eigen::TopLeft, smalldim, c.cols())); + .solveInPlace(c.topRows(smalldim)); if(rows>cols) { - c.corner(Eigen::BottomLeft, rows-cols, c.cols()) - -= dec().matrixLU().corner(Eigen::BottomLeft, rows-cols, cols) - * c.corner(Eigen::TopLeft, cols, c.cols()); + c.bottomRows(rows-cols) + -= dec().matrixLU().bottomRows(rows-cols) + * c.topRows(cols); } // Step 3 dec().matrixLU() - .corner(TopLeft, nonzero_pivots, nonzero_pivots) + .topLeftCorner(nonzero_pivots, nonzero_pivots) .template triangularView<Upper>() - .solveInPlace(c.corner(TopLeft, nonzero_pivots, c.cols())); + .solveInPlace(c.topRows(nonzero_pivots)); // Step 4 for(int i = 0; i < nonzero_pivots; ++i) diff --git a/Eigen/src/LU/PartialPivLU.h b/Eigen/src/LU/PartialPivLU.h index 42c74ee53..695b7d75c 100644 --- a/Eigen/src/LU/PartialPivLU.h +++ b/Eigen/src/LU/PartialPivLU.h @@ -283,7 +283,7 @@ struct ei_partial_lu_impl int rrows = rows-k-1; int rsize = size-k-1; lu.col(k).tail(rrows) /= lu.coeff(k,k); - lu.corner(BottomRight,rrows,rsize).noalias() -= lu.col(k).tail(rrows) * lu.row(k).tail(rsize); + lu.bottomRightCorner(rrows,rsize).noalias() -= lu.col(k).tail(rrows) * lu.row(k).tail(rsize); } } return true; diff --git a/Eigen/src/QR/ColPivHouseholderQR.h b/Eigen/src/QR/ColPivHouseholderQR.h index 5893125cd..8c9c8840b 100644 --- a/Eigen/src/QR/ColPivHouseholderQR.h +++ b/Eigen/src/QR/ColPivHouseholderQR.h @@ -411,7 +411,7 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const { m_nonzero_pivots = k; m_hCoeffs.tail(size-k).setZero(); - m_qr.corner(BottomRight,rows-k,cols-k) + m_qr.bottomRightCorner(rows-k,cols-k) .template triangularView<StrictlyLower>() .setZero(); break; @@ -436,7 +436,7 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const if(ei_abs(beta) > m_maxpivot) m_maxpivot = ei_abs(beta); // apply the householder transformation - m_qr.corner(BottomRight, rows-k, cols-k-1) + m_qr.bottomRightCorner(rows-k, cols-k-1) .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), m_hCoeffs.coeffRef(k), &m_temp.coeffRef(k+1)); // update our table of squared norms of the columns @@ -483,17 +483,17 @@ struct ei_solve_retval<ColPivHouseholderQR<_MatrixType>, Rhs> )); dec().matrixQR() - .corner(TopLeft, nonzero_pivots, nonzero_pivots) + .topLeftCorner(nonzero_pivots, nonzero_pivots) .template triangularView<Upper>() - .solveInPlace(c.corner(TopLeft, nonzero_pivots, c.cols())); + .solveInPlace(c.topRows(nonzero_pivots)); typename Rhs::PlainObject d(c); - d.corner(TopLeft, nonzero_pivots, c.cols()) + d.topRows(nonzero_pivots) = dec().matrixQR() - .corner(TopLeft, nonzero_pivots, nonzero_pivots) + .topLeftCorner(nonzero_pivots, nonzero_pivots) .template triangularView<Upper>() - * c.corner(TopLeft, nonzero_pivots, c.cols()); + * c.topRows(nonzero_pivots); for(int i = 0; i < nonzero_pivots; ++i) dst.row(dec().colsPermutation().indices().coeff(i)) = c.row(i); for(int i = nonzero_pivots; i < cols; ++i) dst.row(dec().colsPermutation().indices().coeff(i)).setZero(); diff --git a/Eigen/src/QR/FullPivHouseholderQR.h b/Eigen/src/QR/FullPivHouseholderQR.h index 8df2ed1e0..0195e1330 100644 --- a/Eigen/src/QR/FullPivHouseholderQR.h +++ b/Eigen/src/QR/FullPivHouseholderQR.h @@ -314,7 +314,7 @@ FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(cons int row_of_biggest_in_corner, col_of_biggest_in_corner; RealScalar biggest_in_corner; - biggest_in_corner = m_qr.corner(Eigen::BottomRight, rows-k, cols-k) + biggest_in_corner = m_qr.bottomRightCorner(rows-k, cols-k) .cwiseAbs() .maxCoeff(&row_of_biggest_in_corner, &col_of_biggest_in_corner); row_of_biggest_in_corner += k; @@ -349,7 +349,7 @@ FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(cons m_qr.col(k).tail(rows-k).makeHouseholderInPlace(m_hCoeffs.coeffRef(k), beta); m_qr.coeffRef(k,k) = beta; - m_qr.corner(BottomRight, rows-k, cols-k-1) + m_qr.bottomRightCorner(rows-k, cols-k-1) .applyHouseholderOnTheLeft(m_qr.col(k).tail(rows-k-1), m_hCoeffs.coeffRef(k), &m_temp.coeffRef(k+1)); } @@ -389,7 +389,7 @@ struct ei_solve_retval<FullPivHouseholderQR<_MatrixType>, Rhs> { int remainingSize = rows-k; c.row(k).swap(c.row(dec().rowsTranspositions().coeff(k))); - c.corner(BottomRight, remainingSize, rhs().cols()) + c.bottomRightCorner(remainingSize, rhs().cols()) .applyHouseholderOnTheLeft(dec().matrixQR().col(k).tail(remainingSize-1), dec().hCoeffs().coeff(k), &temp.coeffRef(0)); } @@ -397,17 +397,17 @@ struct ei_solve_retval<FullPivHouseholderQR<_MatrixType>, Rhs> if(!dec().isSurjective()) { // is c is in the image of R ? - RealScalar biggest_in_upper_part_of_c = c.corner(TopLeft, dec().rank(), c.cols()).cwiseAbs().maxCoeff(); - RealScalar biggest_in_lower_part_of_c = c.corner(BottomLeft, rows-dec().rank(), c.cols()).cwiseAbs().maxCoeff(); + RealScalar biggest_in_upper_part_of_c = c.topRows( dec().rank() ).cwiseAbs().maxCoeff(); + RealScalar biggest_in_lower_part_of_c = c.bottomRows(rows-dec().rank()).cwiseAbs().maxCoeff(); // FIXME brain dead const RealScalar m_precision = NumTraits<Scalar>::epsilon() * std::min(rows,cols); if(!ei_isMuchSmallerThan(biggest_in_lower_part_of_c, biggest_in_upper_part_of_c, m_precision)) return; } dec().matrixQR() - .corner(TopLeft, dec().rank(), dec().rank()) + .topLeftCorner(dec().rank(), dec().rank()) .template triangularView<Upper>() - .solveInPlace(c.corner(TopLeft, dec().rank(), c.cols())); + .solveInPlace(c.topRows(dec().rank())); for(int i = 0; i < dec().rank(); ++i) dst.row(dec().colsPermutation().indices().coeff(i)) = c.row(i); for(int i = dec().rank(); i < cols; ++i) dst.row(dec().colsPermutation().indices().coeff(i)).setZero(); diff --git a/Eigen/src/QR/HouseholderQR.h b/Eigen/src/QR/HouseholderQR.h index 10b9fb93f..6a2883939 100644 --- a/Eigen/src/QR/HouseholderQR.h +++ b/Eigen/src/QR/HouseholderQR.h @@ -216,7 +216,7 @@ HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const MatrixType& m_qr.coeffRef(k,k) = beta; // apply H to remaining part of m_qr from the left - m_qr.corner(BottomRight, remainingRows, remainingCols) + m_qr.bottomRightCorner(remainingRows, remainingCols) .applyHouseholderOnTheLeft(m_qr.col(k).tail(remainingRows-1), m_hCoeffs.coeffRef(k), &m_temp.coeffRef(k+1)); } m_isInitialized = true; @@ -239,17 +239,17 @@ struct ei_solve_retval<HouseholderQR<_MatrixType>, Rhs> // Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T c.applyOnTheLeft(householderSequence( - dec().matrixQR().corner(TopLeft,rows,rank), + dec().matrixQR().leftCols(rank), dec().hCoeffs().head(rank)).transpose() ); dec().matrixQR() - .corner(TopLeft, rank, rank) + .topLeftCorner(rank, rank) .template triangularView<Upper>() - .solveInPlace(c.corner(TopLeft, rank, c.cols())); + .solveInPlace(c.topRows(rank)); - dst.corner(TopLeft, rank, c.cols()) = c.corner(TopLeft, rank, c.cols()); - dst.corner(BottomLeft, cols-rank, c.cols()).setZero(); + dst.topRows(rank) = c.topRows(rank); + dst.bottomRows(cols-rank).setZero(); } }; diff --git a/Eigen/src/SVD/UpperBidiagonalization.h b/Eigen/src/SVD/UpperBidiagonalization.h index 0a63b4265..53e04076a 100644 --- a/Eigen/src/SVD/UpperBidiagonalization.h +++ b/Eigen/src/SVD/UpperBidiagonalization.h @@ -114,7 +114,7 @@ UpperBidiagonalization<_MatrixType>& UpperBidiagonalization<_MatrixType>::comput .makeHouseholderInPlace(m_householder.coeffRef(k,k), m_bidiagonal.template diagonal<0>().coeffRef(k)); // apply householder transform to remaining part of m_householder on the left - m_householder.corner(BottomRight, remainingRows, remainingCols) + m_householder.bottomRightCorner(remainingRows, remainingCols) .applyHouseholderOnTheLeft(m_householder.col(k).tail(remainingRows-1), m_householder.coeff(k,k), temp.data()); @@ -126,7 +126,7 @@ UpperBidiagonalization<_MatrixType>& UpperBidiagonalization<_MatrixType>::comput .makeHouseholderInPlace(m_householder.coeffRef(k,k+1), m_bidiagonal.template diagonal<1>().coeffRef(k)); // apply householder transform to remaining part of m_householder on the left - m_householder.corner(BottomRight, remainingRows-1, remainingCols) + m_householder.bottomRightCorner(remainingRows-1, remainingCols) .applyHouseholderOnTheRight(m_householder.row(k).tail(remainingCols-1).transpose(), m_householder.coeff(k,k+1), temp.data()); diff --git a/Eigen/src/Sparse/SparseMatrixBase.h b/Eigen/src/Sparse/SparseMatrixBase.h index d269ce604..65fa19a79 100644 --- a/Eigen/src/Sparse/SparseMatrixBase.h +++ b/Eigen/src/Sparse/SparseMatrixBase.h @@ -433,19 +433,11 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived> // typename BlockReturnType<Derived,Dynamic>::SubVectorType end(int size); // const typename BlockReturnType<Derived,Dynamic>::SubVectorType end(int size) const; // -// typename BlockReturnType<Derived>::Type corner(CornerType type, int cRows, int cCols); -// const typename BlockReturnType<Derived>::Type corner(CornerType type, int cRows, int cCols) const; -// // template<int BlockRows, int BlockCols> // typename BlockReturnType<Derived, BlockRows, BlockCols>::Type block(int startRow, int startCol); // template<int BlockRows, int BlockCols> // const typename BlockReturnType<Derived, BlockRows, BlockCols>::Type block(int startRow, int startCol) const; -// template<int CRows, int CCols> -// typename BlockReturnType<Derived, CRows, CCols>::Type corner(CornerType type); -// template<int CRows, int CCols> -// const typename BlockReturnType<Derived, CRows, CCols>::Type corner(CornerType type) const; - // template<int Size> typename BlockReturnType<Derived,Size>::SubVectorType start(void); // template<int Size> const typename BlockReturnType<Derived,Size>::SubVectorType start() const; diff --git a/doc/A05_PortingFrom2To3.dox b/doc/A05_PortingFrom2To3.dox index 57f801f84..554ca7f2c 100644 --- a/doc/A05_PortingFrom2To3.dox +++ b/doc/A05_PortingFrom2To3.dox @@ -9,6 +9,7 @@ and to help porting an application from Eigen2 to Eigen3. - \ref CompatibilitySupport - \ref ChangeList - \ref CoefficientWiseOperations + - \ref Corners - \ref LazyVsNoalias \section CompatibilitySupport Eigen2 compatibility support @@ -81,6 +82,34 @@ With Eigen2 you would have written: c = (a.cwise().abs().cwise().pow(3)).cwise() * (b.cwise().abs().cwise().sin()); \endcode +\section Corners Corners + +<table> +<tr><td>Eigen 2</td><td>Eigen 3</td></tr> +<tr><td>\code +matrix.corner(TopLeft,r,c) +matrix.corner(TopRight,r,c) +matrix.corner(BottomLeft,r,c) +matrix.corner(BottomRight,r,c) +matrix.corner<r,c>(TopLeft) +matrix.corner<r,c>(TopRight) +matrix.corner<r,c>(BottomLeft) +matrix.corner<r,c>(BottomRight) +\endcode</td><td>\code +matrix.topLeftCorner(r,c) +matrix.topRightCorner(r,c) +matrix.bottomLeftCorner(r,c) +matrix.bottomRightCorner(r,c) +matrix.topLeftCorner<r,c>() +matrix.topRightCorner<r,c>() +matrix.bottomLeftCorner<r,c>() +matrix.bottomRightCorner<r,c>() +\endcode</td> +</tr> +</table> + +Notice that Eigen3 also provides these new convenience methods: topRows(), bottomRows(), leftCols(), rightCols(). See in class DenseBase. + \section LazyVsNoalias Lazy evaluation and noalias In Eigen all operations are performed in a lazy fashion except the matrix products which are always evaluated into a temporary by default. diff --git a/doc/AsciiQuickReference.txt b/doc/AsciiQuickReference.txt index 74de7344b..d2e973f5d 100644 --- a/doc/AsciiQuickReference.txt +++ b/doc/AsciiQuickReference.txt @@ -47,15 +47,14 @@ x.segment(i, n) // x(i+1 : i+n) x.segment<n>(i) // x(i+1 : i+n) P.block(i, j, rows, cols) // P(i+1 : i+rows, j+1 : j+cols) P.block<rows, cols>(i, j) // P(i+1 : i+rows, j+1 : j+cols) -P.corner(TopLeft, rows, cols) // P(1:rows, 1:cols) -P.corner(TopRight, rows, cols) // [m n]=size(P); P(1:rows, n-cols+1:n) -P.corner(BottomLeft, rows, cols) // [m n]=size(P); P(m-rows+1:m, 1:cols) -P.corner(BottomRight, rows, cols) // [m n]=size(P); P(m-rows+1:m, n-cols+1:n) -P.corner<rows,cols>(TopLeft) // P(1:rows, 1:cols) -P.corner<rows,cols>(TopRight) // [m n]=size(P); P(1:rows, n-cols+1:n) -P.corner<rows,cols>(BottomLeft) // [m n]=size(P); P(m-rows+1:m, 1:cols) -P.corner<rows,cols>(BottomRight) // [m n]=size(P); P(m-rows+1:m, n-cols+1:n) -P.minor(i, j) // Something nasty. +P.topLeftCorner(rows, cols) // P(1:rows, 1:cols) +P.topRightCorner(rows, cols) // [m n]=size(P); P(1:rows, n-cols+1:n) +P.bottomLeftCorner(rows, cols) // [m n]=size(P); P(m-rows+1:m, 1:cols) +P.bottomRightCorner(rows, cols) // [m n]=size(P); P(m-rows+1:m, n-cols+1:n) +P.topLeftCorner<rows,cols>() // P(1:rows, 1:cols) +P.topRightCorner<rows,cols>() // [m n]=size(P); P(1:rows, n-cols+1:n) +P.bottomLeftCorner<rows,cols>() // [m n]=size(P); P(m-rows+1:m, 1:cols) +P.bottomRightCorner<rows,cols>() // [m n]=size(P); P(m-rows+1:m, n-cols+1:n) // Of particular note is Eigen's swap function which is highly optimized. // Eigen // Matlab diff --git a/doc/C01_QuickStartGuide.dox b/doc/C01_QuickStartGuide.dox index b346e2371..79705aa9d 100644 --- a/doc/C01_QuickStartGuide.dox +++ b/doc/C01_QuickStartGuide.dox @@ -577,29 +577,22 @@ Read-write access to sub-matrices:</td><td></td><td></td></tr> \link DenseBase::block(int,int) (more) \endlink</td> <td>the \c rows x \c cols sub-matrix \n starting from position (\c i,\c j)</td></tr><tr> <td>\code - mat1.corner(TopLeft,rows,cols) - mat1.corner(TopRight,rows,cols) - mat1.corner(BottomLeft,rows,cols) - mat1.corner(BottomRight,rows,cols)\endcode - \link DenseBase::corner(CornerType,int,int) (more) \endlink</td> + mat1.topLeftCorner(rows,cols) + mat1.topRightCorner(rows,cols) + mat1.bottomLeftCorner(rows,cols) + mat1.bottomRightCorner(rows,cols)\endcode <td>\code - mat1.corner<rows,cols>(TopLeft) - mat1.corner<rows,cols>(TopRight) - mat1.corner<rows,cols>(BottomLeft) - mat1.corner<rows,cols>(BottomRight)\endcode - \link DenseBase::corner(CornerType) (more) \endlink</td> + mat1.topLeftCorner<rows,cols>() + mat1.topRightCorner<rows,cols>() + mat1.bottomLeftCorner<rows,cols>() + mat1.bottomRightCorner<rows,cols>()\endcode <td>the \c rows x \c cols sub-matrix \n taken in one of the four corners</td></tr> -<tr><td>\code -mat4x4.minor(i,j) = mat3x3; -mat3x3 = mat4x4.minor(i,j);\endcode -</td><td></td><td> -\link DenseBase::minor() minor \endlink (read-write)</td> -</tr> </table> -<a href="#" class="top">top</a>\section TutorialCoreDiagonalMatrices Diagonal matrices \matrixworld +<a href="#" class="top">top</a>\section TutorialCoreDiagonalMatrices Diagonal matrices +\matrixworld <table class="tutorial_code"> <tr><td> diff --git a/doc/C03_TutorialGeometry.dox b/doc/C03_TutorialGeometry.dox index e349c68ce..6d02df40c 100644 --- a/doc/C03_TutorialGeometry.dox +++ b/doc/C03_TutorialGeometry.dox @@ -153,7 +153,7 @@ glLoadMatrixf(t.data());\endcode</td></tr> <tr><td> OpenGL compatibility \b 2D </td><td>\code Transform3f aux(Transform3f::Identity); -aux.linear().corner<2,2>(TopLeft) = t.linear(); +aux.linear().topLeftCorner<2,2>() = t.linear(); aux.translation().start<2>() = t.translation(); glLoadMatrixf(aux.data());\endcode</td></tr> </table> diff --git a/doc/Overview.dox b/doc/Overview.dox index 10463900e..6b7000c4d 100644 --- a/doc/Overview.dox +++ b/doc/Overview.dox @@ -11,7 +11,7 @@ o /** \mainpage Eigen This is the API documentation for Eigen3. -You come from Eigen2? Here is a \ref Eigen2ToEigen3 guide for porting your application from Eigen2 to Eigen3. +Eigen2 users: here is a \ref Eigen2ToEigen3 guide to help porting your application. For a first contact with Eigen, the best place is to have a look at the \ref TutorialCore "tutorial". For an even shorter overview, we have an <a href="AsciiQuickReference.txt">ASCII quick reference</a> with Matlab translations. diff --git a/doc/echelon.cpp b/doc/echelon.cpp deleted file mode 100644 index c95be6f3b..000000000 --- a/doc/echelon.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include <Eigen/Core> - -USING_PART_OF_NAMESPACE_EIGEN - -namespace Eigen { - -/* Echelon a matrix in-place: - * - * Meta-Unrolled version, for small fixed-size matrices - */ -template<typename Derived, int Step> -struct unroll_echelon -{ - enum { k = Step - 1, - Rows = Derived::RowsAtCompileTime, - Cols = Derived::ColsAtCompileTime, - CornerRows = Rows - k, - CornerCols = Cols - k - }; - static void run(MatrixBase<Derived>& m) - { - unroll_echelon<Derived, Step-1>::run(m); - int rowOfBiggest, colOfBiggest; - m.template corner<CornerRows, CornerCols>(BottomRight) - .cwise().abs() - .maxCoeff(&rowOfBiggest, &colOfBiggest); - m.row(k).swap(m.row(k+rowOfBiggest)); - m.col(k).swap(m.col(k+colOfBiggest)); - m.template corner<CornerRows-1, CornerCols>(BottomRight) - -= m.col(k).template tail<CornerRows-1>() - * (m.row(k).template tail<CornerCols>() / m(k,k)); - } -}; - -template<typename Derived> -struct unroll_echelon<Derived, 0> -{ - static void run(MatrixBase<Derived>& m) {} -}; - -/* Echelon a matrix in-place: - * - * Non-unrolled version, for dynamic-size matrices. - * (this version works for all matrices, but in the fixed-size case the other - * version is faster). - */ -template<typename Derived> -struct unroll_echelon<Derived, Dynamic> -{ - static void run(MatrixBase<Derived>& m) - { - for(int k = 0; k < m.diagonal().size() - 1; k++) - { - int rowOfBiggest, colOfBiggest; - int cornerRows = m.rows()-k, cornerCols = m.cols()-k; - m.corner(BottomRight, cornerRows, cornerCols) - .cwise().abs() - .maxCoeff(&rowOfBiggest, &colOfBiggest); - m.row(k).swap(m.row(k+rowOfBiggest)); - m.col(k).swap(m.col(k+colOfBiggest)); - m.corner(BottomRight, cornerRows-1, cornerCols) - -= m.col(k).tail(cornerRows-1) * (m.row(k).tail(cornerCols) / m(k,k)); - } - } -}; - -using namespace std; -template<typename Derived> -void echelon(MatrixBase<Derived>& m) -{ - const int size = DiagonalCoeffs<Derived>::SizeAtCompileTime; - const bool unroll = size <= 4; - unroll_echelon<Derived, unroll ? size-1 : Dynamic>::run(m); -} - -template<typename Derived> -void doSomeRankPreservingOperations(MatrixBase<Derived>& m) -{ - for(int a = 0; a < 3*(m.rows()+m.cols()); a++) - { - double d = ei_random<double>(-1,1); - int i = ei_random<int>(0,m.rows()-1); // i is a random row number - int j; - do { - j = ei_random<int>(0,m.rows()-1); - } while (i==j); // j is another one (must be different) - m.row(i) += d * m.row(j); - - i = ei_random<int>(0,m.cols()-1); // i is a random column number - do { - j = ei_random<int>(0,m.cols()-1); - } while (i==j); // j is another one (must be different) - m.col(i) += d * m.col(j); - } -} - -} // namespace Eigen - -using namespace std; - -int main(int, char **) -{ - srand((unsigned int)time(0)); - const int Rows = 6, Cols = 4; - typedef Matrix<double, Rows, Cols> Mat; - const int N = Rows < Cols ? Rows : Cols; - - // start with a matrix m that's obviously of rank N-1 - Mat m = Mat::identity(Rows, Cols); // args just in case of dyn. size - m.row(0) = m.row(1) = m.row(0) + m.row(1); - - doSomeRankPreservingOperations(m); - - // now m is still a matrix of rank N-1 - cout << "Here's the matrix m:" << endl << m << endl; - - cout << "Now let's echelon m (repeating many times for benchmarking purposes):" << endl; - for(int i = 0; i < 1000000; i++) echelon(m); - - cout << "Now m is:" << endl << m << endl; -} diff --git a/doc/snippets/MatrixBase_corner_enum_int_int.cpp b/doc/snippets/MatrixBase_corner_enum_int_int.cpp deleted file mode 100644 index fd6c950cc..000000000 --- a/doc/snippets/MatrixBase_corner_enum_int_int.cpp +++ /dev/null @@ -1,6 +0,0 @@ -Matrix4i m = Matrix4i::Random(); -cout << "Here is the matrix m:" << endl << m << endl; -cout << "Here is the bottom-right 2x3 corner in m:" << endl - << m.corner(Eigen::BottomRight, 2, 3) << endl; -m.corner(Eigen::BottomRight, 2, 3).setZero(); -cout << "Now the matrix m is:" << endl << m << endl; diff --git a/doc/snippets/MatrixBase_template_int_int_corner_enum.cpp b/doc/snippets/MatrixBase_template_int_int_corner_enum.cpp deleted file mode 100644 index 05ed0ad2f..000000000 --- a/doc/snippets/MatrixBase_template_int_int_corner_enum.cpp +++ /dev/null @@ -1,6 +0,0 @@ -Matrix4i m = Matrix4i::Random(); -cout << "Here is the matrix m:" << endl << m << endl; -cout << "Here is the bottom-right 2x3 corner in m:" << endl - << m.corner<2,3>(Eigen::BottomRight) << endl; -m.corner<2,3>(Eigen::BottomRight).setZero(); -cout << "Now the matrix m is:" << endl << m << endl; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cadd3e31a..b89b54d57 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -105,6 +105,7 @@ ei_add_test(unalignedcount) ei_add_test(redux) ei_add_test(visitor) ei_add_test(block) +ei_add_test(corners) ei_add_test(product_small) ei_add_test(product_large) ei_add_test(product_extra) diff --git a/test/corners.cpp b/test/corners.cpp new file mode 100644 index 000000000..3baea1b96 --- /dev/null +++ b/test/corners.cpp @@ -0,0 +1,99 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com> +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see <http://www.gnu.org/licenses/>. + +#include "main.h" + +#define COMPARE_CORNER(A,B) \ + VERIFY_IS_EQUAL(matrix.A, matrix.B); \ + VERIFY_IS_EQUAL(const_matrix.A, const_matrix.B); + +template<typename MatrixType> void corners(const MatrixType& m) +{ + int rows = m.rows(); + int cols = m.cols(); + + int r = ei_random<int>(1,rows); + int c = ei_random<int>(1,cols); + + MatrixType matrix = MatrixType::Random(rows,cols); + const MatrixType const_matrix = MatrixType::Random(rows,cols); + + COMPARE_CORNER(topLeftCorner(r,c), block(0,0,r,c)); + COMPARE_CORNER(topRightCorner(r,c), block(0,cols-c,r,c)); + COMPARE_CORNER(bottomLeftCorner(r,c), block(rows-r,0,r,c)); + COMPARE_CORNER(bottomRightCorner(r,c), block(rows-r,cols-c,r,c)); + + COMPARE_CORNER(topRows(r), block(0,0,r,cols)); + COMPARE_CORNER(bottomRows(r), block(rows-r,0,r,cols)); + COMPARE_CORNER(leftCols(c), block(0,0,rows,c)); + COMPARE_CORNER(rightCols(c), block(0,cols-c,rows,c)); +} + +template<typename MatrixType, int CRows, int CCols> void corners_fixedsize() +{ + MatrixType matrix = MatrixType::Random(); + const MatrixType const_matrix = MatrixType::Random(); + + enum { + rows = MatrixType::RowsAtCompileTime, + cols = MatrixType::ColsAtCompileTime, + r = CRows, + c = CCols + }; + + VERIFY_IS_EQUAL((matrix.template topLeftCorner<r,c>()), (matrix.template block<r,c>(0,0))); + VERIFY_IS_EQUAL((matrix.template topRightCorner<r,c>()), (matrix.template block<r,c>(0,cols-c))); + VERIFY_IS_EQUAL((matrix.template bottomLeftCorner<r,c>()), (matrix.template block<r,c>(rows-r,0))); + VERIFY_IS_EQUAL((matrix.template bottomRightCorner<r,c>()), (matrix.template block<r,c>(rows-r,cols-c))); + + VERIFY_IS_EQUAL((matrix.template topRows<r>()), (matrix.template block<r,cols>(0,0))); + VERIFY_IS_EQUAL((matrix.template bottomRows<r>()), (matrix.template block<r,cols>(rows-r,0))); + VERIFY_IS_EQUAL((matrix.template leftCols<c>()), (matrix.template block<rows,c>(0,0))); + VERIFY_IS_EQUAL((matrix.template rightCols<c>()), (matrix.template block<rows,c>(0,cols-c))); + + VERIFY_IS_EQUAL((const_matrix.template topLeftCorner<r,c>()), (const_matrix.template block<r,c>(0,0))); + VERIFY_IS_EQUAL((const_matrix.template topRightCorner<r,c>()), (const_matrix.template block<r,c>(0,cols-c))); + VERIFY_IS_EQUAL((const_matrix.template bottomLeftCorner<r,c>()), (const_matrix.template block<r,c>(rows-r,0))); + VERIFY_IS_EQUAL((const_matrix.template bottomRightCorner<r,c>()), (const_matrix.template block<r,c>(rows-r,cols-c))); + + VERIFY_IS_EQUAL((const_matrix.template topRows<r>()), (const_matrix.template block<r,cols>(0,0))); + VERIFY_IS_EQUAL((const_matrix.template bottomRows<r>()), (const_matrix.template block<r,cols>(rows-r,0))); + VERIFY_IS_EQUAL((const_matrix.template leftCols<c>()), (const_matrix.template block<rows,c>(0,0))); + VERIFY_IS_EQUAL((const_matrix.template rightCols<c>()), (const_matrix.template block<rows,c>(0,cols-c))); +} + +void test_corners() +{ + for(int i = 0; i < g_repeat; i++) { + CALL_SUBTEST_1( corners(Matrix<float, 1, 1>()) ); + CALL_SUBTEST_2( corners(Matrix4d()) ); + CALL_SUBTEST_3( corners(Matrix<int,10,12>()) ); + CALL_SUBTEST_4( corners(MatrixXcf(5, 7)) ); + CALL_SUBTEST_5( corners(MatrixXf(21, 20)) ); + + CALL_SUBTEST_1(( corners_fixedsize<Matrix<float, 1, 1>, 1, 1>() )); + CALL_SUBTEST_2(( corners_fixedsize<Matrix4d,2,2>() )); + CALL_SUBTEST_3(( corners_fixedsize<Matrix<int,10,12>,4,7>() )); + } +} diff --git a/test/main.h b/test/main.h index 0603f6e7a..a1c45b4fe 100644 --- a/test/main.h +++ b/test/main.h @@ -351,9 +351,10 @@ struct test_is_equal_impl { static bool run(const Derived1& a1, const Derived2& a2) { + if(a1.size() == 0 && a2.size() == 0) return true; if(a1.size() != a2.size()) return false; // we evaluate a2 into a temporary of the shape of a1. this allows to let Assign.h handle the transposing if needed. - typename Derived1::PlainObject a2_evaluated; + typename Derived1::PlainObject a2_evaluated(a2.size()); a2_evaluated(0,0) = a2(0,0); // shut up GCC 4.5.0 bogus warning about a2_evaluated's array being used uninitialized in the 1x1 case, see block_1 test a2_evaluated = a2; for(int i = 0; i < a1.size(); ++i) @@ -367,6 +368,7 @@ struct test_is_equal_impl<Derived1, Derived2, false> { static bool run(const Derived1& a1, const Derived2& a2) { + if(a1.size() == 0 && a2.size() == 0) return true; if(a1.rows() != a2.rows()) return false; if(a1.cols() != a2.cols()) return false; for(int j = 0; j < a1.cols(); ++j) diff --git a/test/product_notemporary.cpp b/test/product_notemporary.cpp index 9084cde6b..ca1140353 100644 --- a/test/product_notemporary.cpp +++ b/test/product_notemporary.cpp @@ -86,7 +86,8 @@ template<typename MatrixType> void product_notemporary(const MatrixType& m) VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<Upper>() * (m2+m2), 1); VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * m2.adjoint(), 0); - VERIFY_EVALUATION_COUNT( rm3.col(c0).noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * (s2*m2.row(c0)).adjoint(), 0); + // NOTE this is because the blas_traits require innerstride==1 to avoid a temporary, but that doesn't seem to be actually needed for the triangular products + VERIFY_EVALUATION_COUNT( rm3.col(c0).noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpper>() * (s2*m2.row(c0)).adjoint(), 1); VERIFY_EVALUATION_COUNT( m1.template triangularView<Lower>().solveInPlace(m3), 0); VERIFY_EVALUATION_COUNT( m1.adjoint().template triangularView<Lower>().solveInPlace(m3.transpose()), 0); @@ -95,8 +96,9 @@ template<typename MatrixType> void product_notemporary(const MatrixType& m) VERIFY_EVALUATION_COUNT( m3.noalias() = s2 * m2.adjoint() * (s1 * m1.adjoint()).template selfadjointView<Upper>(), 0); VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template selfadjointView<Lower>() * m2.adjoint(), 0); - VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() = (s1 * m1).adjoint().template selfadjointView<Lower>() * (-m2.row(c0)*s3).adjoint(), 0); - VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() -= (s1 * m1).adjoint().template selfadjointView<Upper>() * (-m2.row(c0)*s3).adjoint(), 0); + // NOTE this is because the blas_traits require innerstride==1 to avoid a temporary, but that doesn't seem to be actually needed for the triangular products + VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() = (s1 * m1).adjoint().template selfadjointView<Lower>() * (-m2.row(c0)*s3).adjoint(), 1); + VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() -= (s1 * m1).adjoint().template selfadjointView<Upper>() * (-m2.row(c0)*s3).adjoint(), 1); VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() += m1.block(r0,r0,r1,r1).template selfadjointView<Upper>() * (s1*m2.block(r0,c0,r1,c1)), 0); VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<Upper>() * m2.block(r0,c0,r1,c1), 0); diff --git a/unsupported/Eigen/NonLinearOptimization b/unsupported/Eigen/NonLinearOptimization index 149b658f8..e19db33cc 100644 --- a/unsupported/Eigen/NonLinearOptimization +++ b/unsupported/Eigen/NonLinearOptimization @@ -88,7 +88,7 @@ namespace Eigen { * (c)minpack performs VERY well compared to those, both in accuracy and speed. * * The documentation for running the tests is on the wiki - * http://eigen.tuxfamily.org/index.php?title=Developer%27s_Corner#Running_the_unit_tests + * http://eigen.tuxfamily.org/index.php?title=Tests * * \section API API : overview of methods * diff --git a/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h b/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h index 270d23b8b..8ed856770 100644 --- a/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h +++ b/unsupported/Eigen/src/MatrixFunctions/MatrixFunction.h @@ -159,7 +159,7 @@ class MatrixFunction<MatrixType, 1> void permuteSchur(); void swapEntriesInSchur(int index); void computeBlockAtomic(); - typename BlockReturnType<MatrixType>::Type block(const MatrixType& A, int i, int j); + Block<MatrixType> block(const MatrixType& A, int i, int j); void computeOffDiagonal(); DynMatrixType solveTriangularSylvester(const DynMatrixType& A, const DynMatrixType& B, const DynMatrixType& C); @@ -379,7 +379,7 @@ void MatrixFunction<MatrixType,1>::computeBlockAtomic() /** \brief Return block of matrix according to blocking given by #m_blockStart */ template <typename MatrixType> -typename BlockReturnType<MatrixType>::Type MatrixFunction<MatrixType,1>::block(const MatrixType& A, int i, int j) +Block<MatrixType> MatrixFunction<MatrixType,1>::block(const MatrixType& A, int i, int j) { return A.block(m_blockStart(i), m_blockStart(j), m_clusterSize(i), m_clusterSize(j)); } diff --git a/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h b/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h index f99366bbc..3d5b6ea70 100644 --- a/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h +++ b/unsupported/Eigen/src/NonLinearOptimization/LevenbergMarquardt.h @@ -543,7 +543,7 @@ LevenbergMarquardt<FunctorType,Scalar>::minimizeOptimumStorageOneStep(FVectorTyp /* compute the scaled predicted reduction and */ /* the scaled directional derivative. */ - wa3 = fjac.corner(TopLeft,n,n).template triangularView<Upper>() * (permutation.inverse() * wa1); + wa3 = fjac.topLeftCorner(n,n).template triangularView<Upper>() * (permutation.inverse() * wa1); temp1 = ei_abs2(wa3.stableNorm() / fnorm); temp2 = ei_abs2(ei_sqrt(par) * pnorm / fnorm); prered = temp1 + temp2 / Scalar(.5); diff --git a/unsupported/Eigen/src/NonLinearOptimization/covar.h b/unsupported/Eigen/src/NonLinearOptimization/covar.h index 2f983a958..97709a6a6 100644 --- a/unsupported/Eigen/src/NonLinearOptimization/covar.h +++ b/unsupported/Eigen/src/NonLinearOptimization/covar.h @@ -55,7 +55,7 @@ void ei_covar( } /* symmetrize the covariance matrix in r. */ - r.corner(TopLeft,n,n).template triangularView<StrictlyUpper>() = r.corner(TopLeft,n,n).transpose(); + r.topLeftCorner(n,n).template triangularView<StrictlyUpper>() = r.topLeftCorner(n,n).transpose(); r.diagonal() = wa; } diff --git a/unsupported/Eigen/src/NonLinearOptimization/lmpar.h b/unsupported/Eigen/src/NonLinearOptimization/lmpar.h index d763bd4e7..850011912 100644 --- a/unsupported/Eigen/src/NonLinearOptimization/lmpar.h +++ b/unsupported/Eigen/src/NonLinearOptimization/lmpar.h @@ -188,7 +188,7 @@ void ei_lmpar2( const int rank = qr.rank(); // use a threshold wa1 = qtb; wa1.tail(n-rank).setZero(); - qr.matrixQR().corner(TopLeft, rank, rank).template triangularView<Upper>().solveInPlace(wa1.head(rank)); + qr.matrixQR().topLeftCorner(rank, rank).template triangularView<Upper>().solveInPlace(wa1.head(rank)); x = qr.colsPermutation()*wa1; @@ -210,7 +210,7 @@ void ei_lmpar2( parl = 0.; if (rank==n) { wa1 = qr.colsPermutation().inverse() * diag.cwiseProduct(wa2)/dxnorm; - qr.matrixQR().corner(TopLeft, n, n).transpose().template triangularView<Lower>().solveInPlace(wa1); + qr.matrixQR().topLeftCorner(n, n).transpose().template triangularView<Lower>().solveInPlace(wa1); temp = wa1.blueNorm(); parl = fp / delta / temp / temp; } @@ -258,7 +258,7 @@ void ei_lmpar2( /* compute the newton correction. */ wa1 = qr.colsPermutation().inverse() * diag.cwiseProduct(wa2/dxnorm); // we could almost use this here, but the diagonal is outside qr, in sdiag[] - // qr.matrixQR().corner(TopLeft, n, n).transpose().template triangularView<Lower>().solveInPlace(wa1); + // qr.matrixQR().topLeftCorner(n, n).transpose().template triangularView<Lower>().solveInPlace(wa1); for (j = 0; j < n; ++j) { wa1[j] /= sdiag[j]; temp = wa1[j]; diff --git a/unsupported/Eigen/src/NonLinearOptimization/qrsolv.h b/unsupported/Eigen/src/NonLinearOptimization/qrsolv.h index f89a5f9a8..205d934bd 100644 --- a/unsupported/Eigen/src/NonLinearOptimization/qrsolv.h +++ b/unsupported/Eigen/src/NonLinearOptimization/qrsolv.h @@ -27,7 +27,7 @@ void ei_qrsolv( x = s.diagonal(); wa = qtb; - s.corner(TopLeft,n,n).template triangularView<StrictlyLower>() = s.corner(TopLeft,n,n).transpose(); + s.topLeftCorner(n,n).template triangularView<StrictlyLower>() = s.topLeftCorner(n,n).transpose(); /* eliminate the diagonal matrix d using a givens rotation. */ for (j = 0; j < n; ++j) { @@ -71,7 +71,7 @@ void ei_qrsolv( for (nsing=0; nsing<n && sdiag[nsing]!=0; nsing++); wa.tail(n-nsing).setZero(); - s.corner(TopLeft, nsing, nsing).transpose().template triangularView<Upper>().solveInPlace(wa.head(nsing)); + s.topLeftCorner(nsing, nsing).transpose().template triangularView<Upper>().solveInPlace(wa.head(nsing)); // restore sdiag = s.diagonal(); diff --git a/unsupported/test/NonLinearOptimization.cpp b/unsupported/test/NonLinearOptimization.cpp index 38329ea81..3867c316e 100644 --- a/unsupported/test/NonLinearOptimization.cpp +++ b/unsupported/test/NonLinearOptimization.cpp @@ -227,10 +227,10 @@ void testLmder() // std::cout << fjac*covfac << std::endl; MatrixXd cov; - cov = covfac*lm.fjac.corner<n,n>(TopLeft); + cov = covfac*lm.fjac.topLeftCorner<n,n>(); VERIFY_IS_APPROX( cov, cov_ref); // TODO: why isn't this allowed ? : - // VERIFY_IS_APPROX( covfac*fjac.corner<n,n>(TopLeft) , cov_ref); + // VERIFY_IS_APPROX( covfac*fjac.topLeftCorner<n,n>() , cov_ref); } struct hybrj_functor : Functor<double> @@ -618,10 +618,10 @@ void testLmdif() // std::cout << fjac*covfac << std::endl; MatrixXd cov; - cov = covfac*lm.fjac.corner<n,n>(TopLeft); + cov = covfac*lm.fjac.topLeftCorner<n,n>(); VERIFY_IS_APPROX( cov, cov_ref); // TODO: why isn't this allowed ? : - // VERIFY_IS_APPROX( covfac*fjac.corner<n,n>(TopLeft) , cov_ref); + // VERIFY_IS_APPROX( covfac*fjac.topLeftCorner<n,n>() , cov_ref); } struct chwirut2_functor : Functor<double> |