[eigen] Re: [PATCH] Reverse expression (trying again) |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen@xxxxxxxxxxxxxxxxxxx
- Subject: [eigen] Re: [PATCH] Reverse expression (trying again)
- From: Ricard Marxer Piñón <email@xxxxxxxxxxxxxxxx>
- Date: Thu, 5 Feb 2009 20:48:20 +0100
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:sender:received:in-reply-to :references:date:x-google-sender-auth:message-id:subject:from:to :content-type; bh=JMdBkJb8q2dPVNfY+kvtJvXAIOAMrK/9OdOIdXUaftc=; b=sRJIna6k5aA7C5kbmxX+08aZH44aFqwu4tQWw8LBAJNYmaLCUVU7sRxEifKHlgbuU/ uMjuqN2RScNGrVxjBtOMshx3i71zRCq2WtP4BhNgJJ2PdO/U4dCjLj5phM6/aYV6S8yb moAN4vSKyAHn4rYnyIDe5RQRmSpk3WBXrN2Z4=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:content-type; b=VAsOH4zet5FNWJV59NR/08twUmTH+wataKe0i4/Bqqct2AKV6IfFunMbEJFdMQ5TfX LsAUmad/YgQQoEIfaes8RvNQwq76E2WEM0mBVjOs/0UbifHR4PhCQ1ELA1ZDjaiEl2oR 3M+6C7UmK+JCvr5GMcqLj9yOPx2c8TqKj4eK0=
Ok here is part 2.
I tried to tackle the index based coeff, coeffRef, packet and writePacket.
I'm not sure it is right, please review it.
I have also made a small change to the doc snippet of PartialRedux.
Let me know if I'm on the right track.
ricard
On Thu, Feb 5, 2009 at 3:35 PM, Ricard Marxer Piñón
<email@xxxxxxxxxxxxxxxx> wrote:
Hi again,
This time I think I've got it right. Or at least righter.
I have added tests and as Gael suggested I have added a template parameter to Reverse so that PartialRedux returns an _expression_ (however I still don't know if I've got that part right).
In the tests there is one commented part, which I would like to pass in the future but I think it is a bit more complicated.
The patch as been generated using git:
git format-patch git-svn
So to apply to svn it you will need to do (I think):
patch -p1 -i 0001-adding-Reverse.patch
The coeff(int index) and coeffRef(int index) are still not handled (reversed). That will come in the next patch.
Ricard
--
ricard
http://www.ricardmarxer.com
http://www.caligraft..com
--
ricard
http://www.ricardmarxer.com
http://www.caligraft.com
From 25a9086ad78938454f0776c9698a80b00b7b1114 Mon Sep 17 00:00:00 2001
From: Ricard Marxer <email@xxxxxxxxxxxxxxxx>
Date: Thu, 5 Feb 2009 15:26:48 +0100
Subject: [PATCH] adding Reverse
---
Eigen/Core | 1 +
Eigen/src/Array/PartialRedux.h | 16 +++-
Eigen/src/Core/MatrixBase.h | 5 +-
Eigen/src/Core/Reverse.h | 172 +++++++++++++++++++++++++++++
Eigen/src/Core/util/Constants.h | 2 +-
Eigen/src/Core/util/ForwardDeclarations.h | 1 +
doc/snippets/MatrixBase_reverse.cpp | 8 ++
doc/snippets/PartialRedux_reverse.cpp | 10 ++
test/CMakeLists.txt | 1 +
test/reverse.cpp | 131 ++++++++++++++++++++++
10 files changed, 344 insertions(+), 3 deletions(-)
create mode 100644 Eigen/src/Core/Reverse.h
create mode 100644 doc/snippets/MatrixBase_reverse.cpp
create mode 100644 doc/snippets/PartialRedux_reverse.cpp
create mode 100644 test/reverse.cpp
diff --git a/Eigen/Core b/Eigen/Core
index 211e0f9..88f5228 100644
--- a/Eigen/Core
+++ b/Eigen/Core
@@ -136,6 +136,7 @@ namespace Eigen {
#include "src/Core/Block.h"
#include "src/Core/Minor.h"
#include "src/Core/Transpose.h"
+#include "src/Core/Reverse.h"
#include "src/Core/DiagonalMatrix.h"
#include "src/Core/DiagonalCoeffs.h"
#include "src/Core/Sum.h"
diff --git a/Eigen/src/Array/PartialRedux.h b/Eigen/src/Array/PartialRedux.h
index 96c13ca..d2813cf 100644
--- a/Eigen/src/Array/PartialRedux.h
+++ b/Eigen/src/Array/PartialRedux.h
@@ -257,7 +257,21 @@ template<typename ExpressionType, int Direction> class PartialRedux
* \sa MatrixBase::count() */
const PartialReduxExpr<ExpressionType, ei_member_count<int>, Direction> count() const
{ return _expression(); }
-
+
+
+ /** \returns a matrix expression
+ * where each column (or row) are reversed.
+ *
+ * Example: \include PartialRedux_reverse.cpp
+ * Output: \verbinclude PartialRedux_reverse.out
+ *
+ * \sa MatrixBase::reverse() */
+ const Reverse<ExpressionType, Direction> reverse() const
+ {
+ return Reverse<ExpressionType, Direction>( _expression() );
+ }
+
+
/** \returns a 3x3 matrix expression of the cross product
* of each column or row of the referenced expression with the \a other vector.
*
diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h
index 6b7b002..c558881 100644
--- a/Eigen/src/Core/MatrixBase.h
+++ b/Eigen/src/Core/MatrixBase.h
@@ -359,7 +359,10 @@ template<typename Derived> class MatrixBase
const Eigen::Transpose<Derived> transpose() const;
void transposeInPlace();
const AdjointReturnType adjoint() const;
-
+
+ Eigen::Reverse<Derived, BothDirections> reverse();
+ const Eigen::Reverse<Derived, BothDirections> reverse() const;
+ void reverseInPlace();
RowXpr row(int i);
const RowXpr row(int i) const;
diff --git a/Eigen/src/Core/Reverse.h b/Eigen/src/Core/Reverse.h
new file mode 100644
index 0000000..a53eaed
--- /dev/null
+++ b/Eigen/src/Core/Reverse.h
@@ -0,0 +1,172 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@xxxxxxxxx>
+// Copyright (C) 2009 Ricard Marxer <email@xxxxxxxxxxxxxxxx>
+//
+// 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/>.
+
+#ifndef EIGEN_REVERSE_H
+#define EIGEN_REVERSE_H
+
+/** \class Reverse
+ *
+ * \brief Expression of the reverse of a vector
+ *
+ * \param MatrixType the type of the object of which we are taking the reverse
+ *
+ * This class represents an expression of the reverse of a vector.
+ * It is the return type of MatrixBase::reverse()
+ * and most of the time this is the only way it is used.
+ *
+ * \sa MatrixBase::reverse()
+ */
+template<typename MatrixType, int Direction>
+struct ei_traits<Reverse<MatrixType, Direction> >
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef typename ei_nested<MatrixType>::type MatrixTypeNested;
+ typedef typename ei_unref<MatrixTypeNested>::type _MatrixTypeNested;
+ enum {
+ RowsAtCompileTime = MatrixType::RowsAtCompileTime,
+ ColsAtCompileTime = MatrixType::ColsAtCompileTime,
+ MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
+ MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
+
+ // TODO: check how to correctly set the new flags
+ Flags = ((int(_MatrixTypeNested::Flags) ^ RowMajorBit)
+ & ~(LowerTriangularBit | UpperTriangularBit))
+ | (int(_MatrixTypeNested::Flags)&UpperTriangularBit ? LowerTriangularBit : 0)
+ | (int(_MatrixTypeNested::Flags)&LowerTriangularBit ? UpperTriangularBit : 0),
+
+ // TODO: should add two add costs (due to the -1) or only one, and add the cost of calling .rows() and .cols()
+ CoeffReadCost = _MatrixTypeNested::CoeffReadCost
+ };
+};
+
+template<typename MatrixType, int Direction> class Reverse
+ : public MatrixBase<Reverse<MatrixType, Direction> >
+{
+ public:
+
+ EIGEN_GENERIC_PUBLIC_INTERFACE(Reverse)
+
+ inline Reverse(const MatrixType& matrix) : m_matrix(matrix) { }
+
+ EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Reverse)
+
+ inline int rows() const { return m_matrix.rows(); }
+ inline int cols() const { return m_matrix.cols(); }
+
+ inline Scalar& coeffRef(int row, int col)
+ {
+ return m_matrix.const_cast_derived().coeffRef(((Direction == Vertical) || (Direction == BothDirections)) ? m_matrix.rows() - row - 1 : row,
+ ((Direction == Horizontal) || (Direction == BothDirections)) ? m_matrix.cols() - col - 1 : col);
+ }
+
+ inline const Scalar coeff(int row, int col) const
+ {
+ return m_matrix.coeff(((Direction == Vertical) || (Direction == BothDirections)) ? m_matrix.rows() - row - 1 : row,
+ ((Direction == Horizontal) || (Direction == BothDirections)) ? m_matrix.cols() - col - 1 : col);
+ }
+
+ inline const Scalar coeff(int index) const
+ {
+ return m_matrix.coeff(m_matrix.rows() * m_matrix.cols() - index - 1);
+ }
+
+ inline Scalar& coeffRef(int index)
+ {
+ return m_matrix.const_cast_derived().coeffRef(m_matrix.rows() * m_matrix.cols() - index - 1);
+ }
+
+ // TODO: We must reverse the packet reading and writing, which is currently not done here, I think
+ template<int LoadMode>
+ inline const PacketScalar packet(int row, int col) const
+ {
+ return m_matrix.template packet<LoadMode>(((Direction == Vertical) || (Direction == BothDirections)) ? m_matrix.rows() - row - 1 : row,
+ ((Direction == Horizontal) || (Direction == BothDirections)) ? m_matrix.cols() - col - 1 : col);
+ }
+
+ template<int LoadMode>
+ inline void writePacket(int row, int col, const PacketScalar& x)
+ {
+ m_matrix.const_cast_derived().template writePacket<LoadMode>(((Direction == Vertical) || (Direction == BothDirections)) ? m_matrix.rows() - row - 1 : row,
+ ((Direction == Horizontal) || (Direction == BothDirections)) ? m_matrix.cols() - col - 1 : col,
+ x);
+ }
+
+ template<int LoadMode>
+ inline const PacketScalar packet(int index) const
+ {
+ return m_matrix.template packet<LoadMode>(m_matrix.rows() * m_matrix.cols() - index - 1);
+ }
+
+ template<int LoadMode>
+ inline void writePacket(int index, const PacketScalar& x)
+ {
+ m_matrix.const_cast_derived().template writePacket<LoadMode>(m_matrix.rows() * m_matrix.cols() - index - 1, x);
+ }
+
+ protected:
+ const typename MatrixType::Nested m_matrix;
+};
+
+/** \returns an expression of the reverse of *this.
+ *
+ * Example: \include MatrixBase_reverse.cpp
+ * Output: \verbinclude MatrixBase_reverse.out
+ *
+ */
+template<typename Derived>
+inline Reverse<Derived, BothDirections>
+MatrixBase<Derived>::reverse()
+{
+ return derived();
+}
+
+/** This is the const version of reverse(). */
+template<typename Derived>
+inline const Reverse<Derived, BothDirections>
+MatrixBase<Derived>::reverse() const
+{
+ return derived();
+}
+
+/** This is the "in place" version of reverse: it reverses \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 features:
+ * - less error prone: doing the same operation with .reverse() requires special care:
+ * \code m = m.reverse().eval(); \endcode
+ * - no temporary object is created (currently there is one created but could be avoided using swap)
+ * - it allows future optimizations (cache friendliness, etc.)
+ *
+ * \sa reverse() */
+template<typename Derived>
+inline void MatrixBase<Derived>::reverseInPlace()
+{
+ this = this.reverse().eval();
+}
+
+
+#endif // EIGEN_REVERSE_H
diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h
index 1cbf501..603e595 100644
--- a/Eigen/src/Core/util/Constants.h
+++ b/Eigen/src/Core/util/Constants.h
@@ -200,7 +200,7 @@ enum { Aligned, Unaligned };
enum { ForceAligned, AsRequested };
enum { ConditionalJumpCost = 5 };
enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight };
-enum DirectionType { Vertical, Horizontal };
+enum DirectionType { Vertical, Horizontal, BothDirections };
enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct, DiagonalProduct, SparseTimeSparseProduct, SparseTimeDenseProduct, DenseTimeSparseProduct };
enum {
diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h
index 83c4244..759efda 100644
--- a/Eigen/src/Core/util/ForwardDeclarations.h
+++ b/Eigen/src/Core/util/ForwardDeclarations.h
@@ -40,6 +40,7 @@ template<typename MatrixType, int BlockRows=Dynamic, int BlockCols=Dynamic, int
int _DirectAccessStatus = ei_traits<MatrixType>::Flags&DirectAccessBit ? DirectAccessBit
: ei_traits<MatrixType>::Flags&SparseBit> class Block;
template<typename MatrixType> class Transpose;
+template<typename MatrixType, int Direction = BothDirections> class Reverse;
template<typename MatrixType> class Conjugate;
template<typename NullaryOp, typename MatrixType> class CwiseNullaryOp;
template<typename UnaryOp, typename MatrixType> class CwiseUnaryOp;
diff --git a/doc/snippets/MatrixBase_reverse.cpp b/doc/snippets/MatrixBase_reverse.cpp
new file mode 100644
index 0000000..f545a28
--- /dev/null
+++ b/doc/snippets/MatrixBase_reverse.cpp
@@ -0,0 +1,8 @@
+MatrixXi m = MatrixXi::Random(3,4);
+cout << "Here is the matrix m:" << endl << m << endl;
+cout << "Here is the reverse of m:" << endl << m.reverse() << endl;
+cout << "Here is the coefficient (1,0) in the reverse of m:" << endl
+ << m.reverse()(1,0) << endl;
+cout << "Let us overwrite this coefficient with the value 4." << endl;
+m.reverse()(1,0) = 4;
+cout << "Now the matrix m is:" << endl << m << endl;
diff --git a/doc/snippets/PartialRedux_reverse.cpp b/doc/snippets/PartialRedux_reverse.cpp
new file mode 100644
index 0000000..57a0d6f
--- /dev/null
+++ b/doc/snippets/PartialRedux_reverse.cpp
@@ -0,0 +1,10 @@
+MatrixXi m = MatrixXi::Random(3,4);
+cout << "Here is the matrix m:" << endl << m << endl;
+cout << "Here is the rowwise reverse of m:" << endl << m.rowwise().reverse() << endl;
+cout << "Here is the colwise reverse of m:" << endl << m.colwise().reverse() << endl;
+
+cout << "Here is the coefficient (1,0) in the colwise reverse of m:" << endl
+<< m.colwise().reverse()(1,0) << endl;
+cout << "Let us overwrite this coefficient with the value 4." << endl;
+//m.colwise().reverse()(1,0) = 4;
+cout << "Now the matrix m is:" << endl << m << endl;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 01bb721..bd766ff 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -137,6 +137,7 @@ endif(QT4_FOUND)
ei_add_test(sparse_vector)
ei_add_test(sparse_basic)
ei_add_test(sparse_solvers " " "${SPARSE_LIBS}")
+ei_add_test(reverse)
# print a summary of the different options
message("************************************************************")
diff --git a/test/reverse.cpp b/test/reverse.cpp
new file mode 100644
index 0000000..104768a
--- /dev/null
+++ b/test/reverse.cpp
@@ -0,0 +1,131 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@xxxxxxxxx>
+// Copyright (C) 2009 Ricard Marxer <email@xxxxxxxxxxxxxxxx>
+//
+// 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"
+
+template<typename MatrixType> void reverse(const MatrixType& m)
+{
+ typedef typename MatrixType::Scalar Scalar;
+ typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
+
+ int rows = m.rows();
+ int cols = m.cols();
+
+ // this test relies a lot on Random.h, and there's not much more that we can do
+ // to test it, hence I consider that we will have tested Random.h
+ MatrixType m1 = MatrixType::Random(rows, cols);
+ VectorType v1 = VectorType::Random(rows);
+
+ MatrixType m1_r = m1.reverse();
+ // Verify that MatrixBase::reverse() works
+ for ( int i = 0; i < rows; i++ ) {
+ for ( int j = 0; j < cols; j++ ) {
+ VERIFY_IS_APPROX(m1_r(i, j), m1(rows - 1 - i, cols - 1 - j));
+ }
+ }
+
+ Reverse<MatrixType> m1_rd(m1);
+ // Verify that a Reverse default (in both directions) of an expression works
+ for ( int i = 0; i < rows; i++ ) {
+ for ( int j = 0; j < cols; j++ ) {
+ VERIFY_IS_APPROX(m1_rd(i, j), m1(rows - 1 - i, cols - 1 - j));
+ }
+ }
+
+ Reverse<MatrixType, BothDirections> m1_rb(m1);
+ // Verify that a Reverse in both directions of an expression works
+ for ( int i = 0; i < rows; i++ ) {
+ for ( int j = 0; j < cols; j++ ) {
+ VERIFY_IS_APPROX(m1_rb(i, j), m1(rows - 1 - i, cols - 1 - j));
+ }
+ }
+
+ Reverse<MatrixType, Vertical> m1_rv(m1);
+ // Verify that a Reverse in the vertical directions of an expression works
+ for ( int i = 0; i < rows; i++ ) {
+ for ( int j = 0; j < cols; j++ ) {
+ VERIFY_IS_APPROX(m1_rv(i, j), m1(rows - 1 - i, j));
+ }
+ }
+
+ Reverse<MatrixType, Horizontal> m1_rh(m1);
+ // Verify that a Reverse in the horizontal directions of an expression works
+ for ( int i = 0; i < rows; i++ ) {
+ for ( int j = 0; j < cols; j++ ) {
+ VERIFY_IS_APPROX(m1_rh(i, j), m1(i, cols - 1 - j));
+ }
+ }
+
+ VectorType v1_r = v1.reverse();
+ // Verify that a VectorType::reverse() of an expression works
+ for ( int i = 0; i < rows; i++ ) {
+ VERIFY_IS_APPROX(v1_r(i), v1(rows - 1 - i));
+ }
+
+ MatrixType m1_cr = m1.colwise().reverse();
+ // Verify that PartialRedux::reverse() works (for colwise())
+ for ( int i = 0; i < rows; i++ ) {
+ for ( int j = 0; j < cols; j++ ) {
+ VERIFY_IS_APPROX(m1_cr(i, j), m1(rows - 1 - i, j));
+ }
+ }
+
+ MatrixType m1_rr = m1.rowwise().reverse();
+ // Verify that PartialRedux::reverse() works (for rowwise())
+ for ( int i = 0; i < rows; i++ ) {
+ for ( int j = 0; j < cols; j++ ) {
+ VERIFY_IS_APPROX(m1_rr(i, j), m1(i, cols - 1 - j));
+ }
+ }
+
+ /*
+ Scalar x = ei_random<Scalar>();
+
+ int r = ei_random<int>(0, rows-1),
+ c = ei_random<int>(0, cols-1);
+
+ m1.reverse()(r, c) = x;
+ VERIFY_IS_APPROX(x, m1(rows - 1 - r, cols - 1 - c));
+
+ m1.colwise().reverse()(r, c) = x;
+ VERIFY_IS_APPROX(x, m1(rows - 1 - r, c));
+
+ m1.rowwise().reverse()(r, c) = x;
+ VERIFY_IS_APPROX(x, m1(r, cols - 1 - c));
+ */
+}
+
+void test_reverse()
+{
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST( reverse(Matrix<float, 1, 1>()) );
+ CALL_SUBTEST( reverse(Matrix4d()) );
+ CALL_SUBTEST( reverse(MatrixXcf(3, 3)) );
+ CALL_SUBTEST( reverse(MatrixXi(8, 12)) );
+ CALL_SUBTEST( reverse(MatrixXcd(20, 20)) );
+ CALL_SUBTEST( reverse(Matrix<float, 100, 100>()) );
+ CALL_SUBTEST( reverse(Matrix<long double,Dynamic,Dynamic>(10,10)) );
+ }
+}
--
1.5.6.3
From 552e0ed01258d593d83273c09f3275acfeeb13fa Mon Sep 17 00:00:00 2001
From: Ricard Marxer <email@xxxxxxxxxxxxxxxx>
Date: Thu, 5 Feb 2009 20:43:51 +0100
Subject: [PATCH] implement the index based coeff, coeffRef, packet and writePacket and small doc fix
---
Eigen/src/Core/Reverse.h | 68 ++++++++++++++++++++++++++++++---
doc/snippets/PartialRedux_reverse.cpp | 4 +-
test/reverse.cpp | 56 ++++++++++++++++++++++++++-
3 files changed, 119 insertions(+), 9 deletions(-)
diff --git a/Eigen/src/Core/Reverse.h b/Eigen/src/Core/Reverse.h
index a53eaed..e187b12 100644
--- a/Eigen/src/Core/Reverse.h
+++ b/Eigen/src/Core/Reverse.h
@@ -26,6 +26,9 @@
#ifndef EIGEN_REVERSE_H
#define EIGEN_REVERSE_H
+#include <iostream>
+using namespace std;
+
/** \class Reverse
*
* \brief Expression of the reverse of a vector
@@ -89,12 +92,39 @@ template<typename MatrixType, int Direction> class Reverse
inline const Scalar coeff(int index) const
{
- return m_matrix.coeff(m_matrix.rows() * m_matrix.cols() - index - 1);
+ switch ( Direction )
+ {
+ case Vertical:
+ return m_matrix.coeff( index + m_matrix.rows() - 2 * (index % m_matrix.rows()) - 1 );
+ break;
+
+ case Horizontal:
+ return m_matrix.coeff( (index % m_matrix.rows()) + (m_matrix.cols() - 1 - index/m_matrix.rows()) * m_matrix.rows() );
+ break;
+
+ case BothDirections:
+ return m_matrix.coeff((m_matrix.rows() * m_matrix.cols()) - index - 1);
+ break;
+ }
+
}
inline Scalar& coeffRef(int index)
{
- return m_matrix.const_cast_derived().coeffRef(m_matrix.rows() * m_matrix.cols() - index - 1);
+ switch ( Direction )
+ {
+ case Vertical:
+ return m_matrix.const_cast_derived().coeffRef( index + m_matrix.rows() - 2 * (index % m_matrix.rows()) - 1 );
+ break;
+
+ case Horizontal:
+ return m_matrix.const_cast_derived().coeffRef( (index % m_matrix.rows()) + (m_matrix.cols() - 1 - index/m_matrix.rows()) * m_matrix.rows() );
+ break;
+
+ case BothDirections:
+ return m_matrix.const_cast_derived().coeffRef( (m_matrix.rows() * m_matrix.cols()) - index - 1 );
+ break;
+ }
}
// TODO: We must reverse the packet reading and writing, which is currently not done here, I think
@@ -116,13 +146,39 @@ template<typename MatrixType, int Direction> class Reverse
template<int LoadMode>
inline const PacketScalar packet(int index) const
{
- return m_matrix.template packet<LoadMode>(m_matrix.rows() * m_matrix.cols() - index - 1);
+ switch ( Direction )
+ {
+ case Vertical:
+ return m_matrix.template packet<LoadMode>( index + m_matrix.rows() - 2 * (index % m_matrix.rows()) - 1 );
+ break;
+
+ case Horizontal:
+ return m_matrix.template packet<LoadMode>( (index % m_matrix.rows()) + (m_matrix.cols() - 1 - index/m_matrix.rows()) * m_matrix.rows() );
+ break;
+
+ case BothDirections:
+ return m_matrix.template packet<LoadMode>( (m_matrix.rows() * m_matrix.cols()) - index - 1 );
+ break;
+ }
}
template<int LoadMode>
inline void writePacket(int index, const PacketScalar& x)
- {
- m_matrix.const_cast_derived().template writePacket<LoadMode>(m_matrix.rows() * m_matrix.cols() - index - 1, x);
+ {
+ switch ( Direction )
+ {
+ case Vertical:
+ return m_matrix.const_cast_derived().template packet<LoadMode>( index + m_matrix.rows() - 2 * (index % m_matrix.rows()) - 1, x );
+ break;
+
+ case Horizontal:
+ return m_matrix.const_cast_derived().template packet<LoadMode>( (index % m_matrix.rows()) + (m_matrix.cols() - 1 - index/m_matrix.rows()) * m_matrix.rows(), x );
+ break;
+
+ case BothDirections:
+ return m_matrix.const_cast_derived().template packet<LoadMode>( (m_matrix.rows() * m_matrix.cols()) - index - 1, x );
+ break;
+ }
}
protected:
@@ -165,7 +221,7 @@ MatrixBase<Derived>::reverse() const
template<typename Derived>
inline void MatrixBase<Derived>::reverseInPlace()
{
- this = this.reverse().eval();
+ derived() = derived().reverse().eval();
}
diff --git a/doc/snippets/PartialRedux_reverse.cpp b/doc/snippets/PartialRedux_reverse.cpp
index 57a0d6f..2f6a350 100644
--- a/doc/snippets/PartialRedux_reverse.cpp
+++ b/doc/snippets/PartialRedux_reverse.cpp
@@ -3,8 +3,8 @@ cout << "Here is the matrix m:" << endl << m << endl;
cout << "Here is the rowwise reverse of m:" << endl << m.rowwise().reverse() << endl;
cout << "Here is the colwise reverse of m:" << endl << m.colwise().reverse() << endl;
-cout << "Here is the coefficient (1,0) in the colwise reverse of m:" << endl
-<< m.colwise().reverse()(1,0) << endl;
+cout << "Here is the coefficient (1,0) in the rowise reverse of m:" << endl
+<< m.rowwise().reverse()(1,0) << endl;
cout << "Let us overwrite this coefficient with the value 4." << endl;
//m.colwise().reverse()(1,0) = 4;
cout << "Now the matrix m is:" << endl << m << endl;
diff --git a/test/reverse.cpp b/test/reverse.cpp
index 104768a..471b273 100644
--- a/test/reverse.cpp
+++ b/test/reverse.cpp
@@ -24,6 +24,9 @@
// Eigen. If not, see <http://www.gnu.org/licenses/>.
#include "main.h"
+#include <iostream>
+
+using namespace std;
template<typename MatrixType> void reverse(const MatrixType& m)
{
@@ -99,7 +102,58 @@ template<typename MatrixType> void reverse(const MatrixType& m)
VERIFY_IS_APPROX(m1_rr(i, j), m1(i, cols - 1 - j));
}
}
-
+
+ int ind = ei_random<int>(0, (rows*cols) - 1);
+
+ MatrixType m1_reversed(m1.reverse());
+ VERIFY_IS_APPROX( m1_reversed.reverse().coeff( ind ), m1.coeff( ind ) );
+
+ MatrixType m1c_reversed = m1.colwise().reverse();
+ VERIFY_IS_APPROX( m1c_reversed.colwise().reverse().coeff( ind ), m1.coeff( ind ) );
+
+ MatrixType m1r_reversed = m1.rowwise().reverse();
+ VERIFY_IS_APPROX( m1r_reversed.rowwise().reverse().coeff( ind ), m1.coeff( ind ) );
+
+ /*
+ cout << "m1:" << endl << m1 << endl;
+ cout << "m1c_reversed:" << endl << m1c_reversed << endl;
+
+ cout << "----------------" << endl;
+
+ for ( int i=0; i< rows*cols; i++){
+ cout << m1c_reversed.coeff(i) << endl;
+ }
+
+ cout << "----------------" << endl;
+
+ for ( int i=0; i< rows*cols; i++){
+ cout << m1c_reversed.colwise().reverse().coeff(i) << endl;
+ }
+
+ cout << "================" << endl;
+
+ cout << "m1.coeff( ind ): " << m1.coeff( ind ) << endl;
+ cout << "m1c_reversed.colwise().reverse().coeff( ind ): " << m1c_reversed.colwise().reverse().coeff( ind ) << endl;
+ */
+
+ //MatrixType m1r_reversed = m1.rowwise().reverse();
+ //VERIFY_IS_APPROX( m1r_reversed.rowwise().reverse().coeff( ind ), m1.coeff( ind ) );
+
+ /*
+ cout << "m1" << endl << m1 << endl;
+ cout << "m1 using coeff(int index)" << endl;
+ for ( int i = 0; i < rows*cols; i++) {
+ cout << m1.coeff(i) << " ";
+ }
+ cout << endl;
+
+ cout << "m1.transpose()" << endl << m1.transpose() << endl;
+ cout << "m1.transpose() using coeff(int index)" << endl;
+ for ( int i = 0; i < rows*cols; i++) {
+ cout << m1.transpose().coeff(i) << " ";
+ }
+ cout << endl;
+ */
/*
Scalar x = ei_random<Scalar>();
--
1.5.6.3