diff options
author | Gael Guennebaud <g.gael@free.fr> | 2015-03-31 21:35:53 +0200 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2015-03-31 21:35:53 +0200 |
commit | 8313fb7df7f5f116834b412d6a6f5aff8862a173 (patch) | |
tree | 7d2ade8fe6b1b1fe49006ac8eab9e768ff75432e | |
parent | dfb674a25ead137118eebf0230c4c8a4c81db5d0 (diff) |
Add row/column-wise reverseInPlace feature.
-rw-r--r-- | Eigen/src/Core/Reverse.h | 52 | ||||
-rw-r--r-- | Eigen/src/Core/VectorwiseOp.h | 2 | ||||
-rw-r--r-- | test/array_reverse.cpp | 8 |
3 files changed, 59 insertions, 3 deletions
diff --git a/Eigen/src/Core/Reverse.h b/Eigen/src/Core/Reverse.h index b3fba9704..5237fbf1c 100644 --- a/Eigen/src/Core/Reverse.h +++ b/Eigen/src/Core/Reverse.h @@ -200,13 +200,13 @@ DenseBase<Derived>::reverse() const * 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 features: + * the following additional benefits: * - less error prone: doing the same operation with .reverse() requires special care: * \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.) * - * \sa reverse() */ + * \sa VectorwiseOp::reverseInPlace(), reverse() */ template<typename Derived> 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 #endif // EIGEN_REVERSE_H diff --git a/Eigen/src/Core/VectorwiseOp.h b/Eigen/src/Core/VectorwiseOp.h index a15777a5e..ea3d8f4b1 100644 --- a/Eigen/src/Core/VectorwiseOp.h +++ b/Eigen/src/Core/VectorwiseOp.h @@ -562,6 +562,8 @@ template<typename ExpressionType, int Direction> class VectorwiseOp void normalize() { m_matrix = this->normalized(); } + + inline void reverseInPlace(); /////////// Geometry module /////////// diff --git a/test/array_reverse.cpp b/test/array_reverse.cpp index 9ba19246b..a5c0d37f9 100644 --- a/test/array_reverse.cpp +++ b/test/array_reverse.cpp @@ -108,6 +108,14 @@ template<typename MatrixType> void reverse(const MatrixType& m) m2 = m1; m2.row(0).reverseInPlace(); 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; |