Add row/column-wise reverseInPlace feature.

This commit is contained in:
Gael Guennebaud 2015-03-31 21:35:53 +02:00
parent dfb674a25e
commit 8313fb7df7
3 changed files with 59 additions and 3 deletions

View File

@ -200,13 +200,13 @@ DenseBase<Derived>::reverse() const
* In most cases it is probably better to simply use the reversed expression * In most cases it is probably better to simply use the reversed expression
* of a matrix. However, when reversing the matrix data itself is really needed, * of a matrix. However, when reversing the matrix data itself is really needed,
* then this "in-place" version is probably the right choice because it provides * then this "in-place" version is probably the right choice because it provides
* the following additional features: * the following additional benefits:
* - less error prone: doing the same operation with .reverse() requires special care: * - less error prone: doing the same operation with .reverse() requires special care:
* \code m = m.reverse().eval(); \endcode * \code m = m.reverse().eval(); \endcode
* - this API allows to avoid creating a temporary (the current implementation creates a temporary, but that could be avoided using swap) * - this API enables reverse operations without the need for a temporary
* - it allows future optimizations (cache friendliness, etc.) * - it allows future optimizations (cache friendliness, etc.)
* *
* \sa reverse() */ * \sa VectorwiseOp::reverseInPlace(), reverse() */
template<typename Derived> template<typename Derived>
inline void DenseBase<Derived>::reverseInPlace() inline void DenseBase<Derived>::reverseInPlace()
{ {
@ -232,6 +232,52 @@ inline void DenseBase<Derived>::reverseInPlace()
} }
} }
namespace internal {
template<int Direction>
struct vectorwise_reverse_inplace_impl;
template<>
struct vectorwise_reverse_inplace_impl<Vertical>
{
template<typename ExpressionType>
static void run(ExpressionType &xpr)
{
Index half = xpr.rows()/2;
xpr.topRows(half).swap(xpr.bottomRows(half).colwise().reverse());
}
};
template<>
struct vectorwise_reverse_inplace_impl<Horizontal>
{
template<typename ExpressionType>
static void run(ExpressionType &xpr)
{
Index half = xpr.cols()/2;
xpr.leftCols(half).swap(xpr.rightCols(half).rowwise().reverse());
}
};
} // end namespace internal
/** This is the "in place" version of VectorwiseOp::reverse: it reverses each column or row of \c *this.
*
* In most cases it is probably better to simply use the reversed expression
* of a matrix. However, when reversing the matrix data itself is really needed,
* then this "in-place" version is probably the right choice because it provides
* the following additional benefits:
* - less error prone: doing the same operation with .reverse() requires special care:
* \code m = m.reverse().eval(); \endcode
* - this API enables reverse operations without the need for a temporary
*
* \sa DenseBase::reverseInPlace(), reverse() */
template<typename ExpressionType, int Direction>
void VectorwiseOp<ExpressionType,Direction>::reverseInPlace()
{
internal::vectorwise_reverse_inplace_impl<Direction>::run(_expression().const_cast_derived());
}
} // end namespace Eigen } // end namespace Eigen
#endif // EIGEN_REVERSE_H #endif // EIGEN_REVERSE_H

View File

@ -563,6 +563,8 @@ template<typename ExpressionType, int Direction> class VectorwiseOp
m_matrix = this->normalized(); m_matrix = this->normalized();
} }
inline void reverseInPlace();
/////////// Geometry module /////////// /////////// Geometry module ///////////
typedef Homogeneous<ExpressionType,Direction> HomogeneousReturnType; typedef Homogeneous<ExpressionType,Direction> HomogeneousReturnType;

View File

@ -109,6 +109,14 @@ template<typename MatrixType> void reverse(const MatrixType& m)
m2.row(0).reverseInPlace(); m2.row(0).reverseInPlace();
VERIFY_IS_APPROX(m2.row(0),m1.row(0).reverse().eval()); VERIFY_IS_APPROX(m2.row(0),m1.row(0).reverse().eval());
m2 = m1;
m2.rowwise().reverseInPlace();
VERIFY_IS_APPROX(m2,m1.rowwise().reverse().eval());
m2 = m1;
m2.colwise().reverseInPlace();
VERIFY_IS_APPROX(m2,m1.colwise().reverse().eval());
/* /*
m1.colwise().reverse()(r, c) = x; m1.colwise().reverse()(r, c) = x;
VERIFY_IS_APPROX(x, m1(rows - 1 - r, c)); VERIFY_IS_APPROX(x, m1(rows - 1 - r, c));