diff --git a/Eigen/src/Core/CoreEvaluators.h b/Eigen/src/Core/CoreEvaluators.h index 47835f576..1c6c06493 100644 --- a/Eigen/src/Core/CoreEvaluators.h +++ b/Eigen/src/Core/CoreEvaluators.h @@ -666,7 +666,7 @@ struct evaluator_impl > protected: typename evaluator::type m_argImpl; - Index m_rows; + Index m_rows; // TODO: Get rid of this if known at compile time Index m_cols; }; @@ -787,6 +787,100 @@ struct evaluator_impl > }; +// -------------------- Reverse -------------------- + +// defined in Reverse.h: +template struct reverse_packet_cond; + +template +struct evaluator_impl > +{ + typedef Reverse ReverseType; + + evaluator_impl(const ReverseType& reverse) + : m_argImpl(reverse.nestedExpression()), + m_rows(reverse.nestedExpression().rows()), + m_cols(reverse.nestedExpression().cols()) + { } + + typedef typename ReverseType::Index Index; + typedef typename ReverseType::Scalar Scalar; + typedef typename ReverseType::CoeffReturnType CoeffReturnType; + typedef typename ReverseType::PacketScalar PacketScalar; + typedef typename ReverseType::PacketReturnType PacketReturnType; + + enum { + PacketSize = internal::packet_traits::size, + IsRowMajor = ReverseType::IsRowMajor, + IsColMajor = !IsRowMajor, + ReverseRow = (Direction == Vertical) || (Direction == BothDirections), + ReverseCol = (Direction == Horizontal) || (Direction == BothDirections), + OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1, + OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1, + ReversePacket = (Direction == BothDirections) + || ((Direction == Vertical) && IsColMajor) + || ((Direction == Horizontal) && IsRowMajor) + }; + typedef internal::reverse_packet_cond reverse_packet; + + CoeffReturnType coeff(Index row, Index col) const + { + return m_argImpl.coeff(ReverseRow ? m_rows - row - 1 : row, + ReverseCol ? m_cols - col - 1 : col); + } + + CoeffReturnType coeff(Index index) const + { + return m_argImpl.coeff(m_rows * m_cols - index - 1); + } + + Scalar& coeffRef(Index row, Index col) + { + return m_argImpl.coeffRef(ReverseRow ? m_rows - row - 1 : row, + ReverseCol ? m_cols - col - 1 : col); + } + + Scalar& coeffRef(Index index) + { + return m_argImpl.coeffRef(m_rows * m_cols - index - 1); + } + + template + PacketScalar packet(Index row, Index col) const + { + return reverse_packet::run(m_argImpl.template packet( + ReverseRow ? m_rows - row - OffsetRow : row, + ReverseCol ? m_cols - col - OffsetCol : col)); + } + + template + PacketScalar packet(Index index) const + { + return preverse(m_argImpl.template packet(m_rows * m_cols - index - PacketSize)); + } + + template + void writePacket(Index row, Index col, const PacketScalar& x) + { + m_argImpl.template writePacket( + ReverseRow ? m_rows - row - OffsetRow : row, + ReverseCol ? m_cols - col - OffsetCol : col, + reverse_packet::run(x)); + } + + template + void writePacket(Index index, const PacketScalar& x) + { + m_argImpl.template writePacket(m_rows * m_cols - index - PacketSize, preverse(x)); + } + +protected: + typename evaluator::type m_argImpl; + Index m_rows; // TODO: Don't use if known at compile time or not needed + Index m_cols; +}; + + } // namespace internal #endif // EIGEN_COREEVALUATORS_H diff --git a/Eigen/src/Core/Reverse.h b/Eigen/src/Core/Reverse.h index 600744ae7..cef3114c7 100644 --- a/Eigen/src/Core/Reverse.h +++ b/Eigen/src/Core/Reverse.h @@ -183,6 +183,12 @@ template class Reverse m_matrix.const_cast_derived().template writePacket(m_matrix.size() - index - PacketSize, internal::preverse(x)); } + const typename internal::remove_all::type& + nestedExpression() const + { + return m_matrix; + } + protected: const typename MatrixType::Nested m_matrix; }; diff --git a/test/evaluators.cpp b/test/evaluators.cpp index da6b9064b..fa545c7a5 100644 --- a/test/evaluators.cpp +++ b/test/evaluators.cpp @@ -192,4 +192,12 @@ void test_evaluators() VERIFY_IS_APPROX(mat2, (arr1 * arr1).matrix()); arr2.matrix() = MatrixXd::Identity(6,6); VERIFY_IS_APPROX(arr2, MatrixXd::Identity(6,6).array()); + + // test Reverse + VERIFY_IS_APPROX_EVALUATOR(arr2, arr1.reverse()); + VERIFY_IS_APPROX_EVALUATOR(arr2, arr1.colwise().reverse()); + VERIFY_IS_APPROX_EVALUATOR(arr2, arr1.rowwise().reverse()); + + arr2.reverse() = arr1; + VERIFY_IS_APPROX(arr2, arr1.reverse()); }