• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
5 // Copyright (C) 2009 Ricard Marxer <email@ricardmarxer.com>
6 // Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
7 //
8 // This Source Code Form is subject to the terms of the Mozilla
9 // Public License v. 2.0. If a copy of the MPL was not distributed
10 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 
12 #ifndef EIGEN_REVERSE_H
13 #define EIGEN_REVERSE_H
14 
15 namespace Eigen {
16 
17 /** \class Reverse
18   * \ingroup Core_Module
19   *
20   * \brief Expression of the reverse of a vector or matrix
21   *
22   * \param MatrixType the type of the object of which we are taking the reverse
23   *
24   * This class represents an expression of the reverse of a vector.
25   * It is the return type of MatrixBase::reverse() and VectorwiseOp::reverse()
26   * and most of the time this is the only way it is used.
27   *
28   * \sa MatrixBase::reverse(), VectorwiseOp::reverse()
29   */
30 
31 namespace internal {
32 
33 template<typename MatrixType, int Direction>
34 struct traits<Reverse<MatrixType, Direction> >
35  : traits<MatrixType>
36 {
37   typedef typename MatrixType::Scalar Scalar;
38   typedef typename traits<MatrixType>::StorageKind StorageKind;
39   typedef typename traits<MatrixType>::XprKind XprKind;
40   typedef typename nested<MatrixType>::type MatrixTypeNested;
41   typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
42   enum {
43     RowsAtCompileTime = MatrixType::RowsAtCompileTime,
44     ColsAtCompileTime = MatrixType::ColsAtCompileTime,
45     MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
46     MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
47 
48     // let's enable LinearAccess only with vectorization because of the product overhead
49     LinearAccess = ( (Direction==BothDirections) && (int(_MatrixTypeNested::Flags)&PacketAccessBit) )
50                  ? LinearAccessBit : 0,
51 
52     Flags = int(_MatrixTypeNested::Flags) & (HereditaryBits | LvalueBit | PacketAccessBit | LinearAccess),
53 
54     CoeffReadCost = _MatrixTypeNested::CoeffReadCost
55   };
56 };
57 
58 template<typename PacketScalar, bool ReversePacket> struct reverse_packet_cond
59 {
60   static inline PacketScalar run(const PacketScalar& x) { return preverse(x); }
61 };
62 
63 template<typename PacketScalar> struct reverse_packet_cond<PacketScalar,false>
64 {
65   static inline PacketScalar run(const PacketScalar& x) { return x; }
66 };
67 
68 } // end namespace internal
69 
70 template<typename MatrixType, int Direction> class Reverse
71   : public internal::dense_xpr_base< Reverse<MatrixType, Direction> >::type
72 {
73   public:
74 
75     typedef typename internal::dense_xpr_base<Reverse>::type Base;
76     EIGEN_DENSE_PUBLIC_INTERFACE(Reverse)
77     using Base::IsRowMajor;
78 
79     // next line is necessary because otherwise const version of operator()
80     // is hidden by non-const version defined in this file
81     using Base::operator();
82 
83   protected:
84     enum {
85       PacketSize = internal::packet_traits<Scalar>::size,
86       IsColMajor = !IsRowMajor,
87       ReverseRow = (Direction == Vertical)   || (Direction == BothDirections),
88       ReverseCol = (Direction == Horizontal) || (Direction == BothDirections),
89       OffsetRow  = ReverseRow && IsColMajor ? PacketSize : 1,
90       OffsetCol  = ReverseCol && IsRowMajor ? PacketSize : 1,
91       ReversePacket = (Direction == BothDirections)
92                     || ((Direction == Vertical)   && IsColMajor)
93                     || ((Direction == Horizontal) && IsRowMajor)
94     };
95     typedef internal::reverse_packet_cond<PacketScalar,ReversePacket> reverse_packet;
96   public:
97 
98     inline Reverse(const MatrixType& matrix) : m_matrix(matrix) { }
99 
100     EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Reverse)
101 
102     inline Index rows() const { return m_matrix.rows(); }
103     inline Index cols() const { return m_matrix.cols(); }
104 
105     inline Index innerStride() const
106     {
107       return -m_matrix.innerStride();
108     }
109 
110     inline Scalar& operator()(Index row, Index col)
111     {
112       eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
113       return coeffRef(row, col);
114     }
115 
116     inline Scalar& coeffRef(Index row, Index col)
117     {
118       return m_matrix.const_cast_derived().coeffRef(ReverseRow ? m_matrix.rows() - row - 1 : row,
119                                                     ReverseCol ? m_matrix.cols() - col - 1 : col);
120     }
121 
122     inline CoeffReturnType coeff(Index row, Index col) const
123     {
124       return m_matrix.coeff(ReverseRow ? m_matrix.rows() - row - 1 : row,
125                             ReverseCol ? m_matrix.cols() - col - 1 : col);
126     }
127 
128     inline CoeffReturnType coeff(Index index) const
129     {
130       return m_matrix.coeff(m_matrix.size() - index - 1);
131     }
132 
133     inline Scalar& coeffRef(Index index)
134     {
135       return m_matrix.const_cast_derived().coeffRef(m_matrix.size() - index - 1);
136     }
137 
138     inline Scalar& operator()(Index index)
139     {
140       eigen_assert(index >= 0 && index < m_matrix.size());
141       return coeffRef(index);
142     }
143 
144     template<int LoadMode>
145     inline const PacketScalar packet(Index row, Index col) const
146     {
147       return reverse_packet::run(m_matrix.template packet<LoadMode>(
148                                     ReverseRow ? m_matrix.rows() - row - OffsetRow : row,
149                                     ReverseCol ? m_matrix.cols() - col - OffsetCol : col));
150     }
151 
152     template<int LoadMode>
153     inline void writePacket(Index row, Index col, const PacketScalar& x)
154     {
155       m_matrix.const_cast_derived().template writePacket<LoadMode>(
156                                       ReverseRow ? m_matrix.rows() - row - OffsetRow : row,
157                                       ReverseCol ? m_matrix.cols() - col - OffsetCol : col,
158                                       reverse_packet::run(x));
159     }
160 
161     template<int LoadMode>
162     inline const PacketScalar packet(Index index) const
163     {
164       return internal::preverse(m_matrix.template packet<LoadMode>( m_matrix.size() - index - PacketSize ));
165     }
166 
167     template<int LoadMode>
168     inline void writePacket(Index index, const PacketScalar& x)
169     {
170       m_matrix.const_cast_derived().template writePacket<LoadMode>(m_matrix.size() - index - PacketSize, internal::preverse(x));
171     }
172 
173     const typename internal::remove_all<typename MatrixType::Nested>::type&
174     nestedExpression() const
175     {
176       return m_matrix;
177     }
178 
179   protected:
180     typename MatrixType::Nested m_matrix;
181 };
182 
183 /** \returns an expression of the reverse of *this.
184   *
185   * Example: \include MatrixBase_reverse.cpp
186   * Output: \verbinclude MatrixBase_reverse.out
187   *
188   */
189 template<typename Derived>
190 inline typename DenseBase<Derived>::ReverseReturnType
191 DenseBase<Derived>::reverse()
192 {
193   return derived();
194 }
195 
196 /** This is the const version of reverse(). */
197 template<typename Derived>
198 inline const typename DenseBase<Derived>::ConstReverseReturnType
199 DenseBase<Derived>::reverse() const
200 {
201   return derived();
202 }
203 
204 /** This is the "in place" version of reverse: it reverses \c *this.
205   *
206   * In most cases it is probably better to simply use the reversed expression
207   * of a matrix. However, when reversing the matrix data itself is really needed,
208   * then this "in-place" version is probably the right choice because it provides
209   * the following additional features:
210   *  - less error prone: doing the same operation with .reverse() requires special care:
211   *    \code m = m.reverse().eval(); \endcode
212   *  - this API allows to avoid creating a temporary (the current implementation creates a temporary, but that could be avoided using swap)
213   *  - it allows future optimizations (cache friendliness, etc.)
214   *
215   * \sa reverse() */
216 template<typename Derived>
217 inline void DenseBase<Derived>::reverseInPlace()
218 {
219   derived() = derived().reverse().eval();
220 }
221 
222 } // end namespace Eigen
223 
224 #endif // EIGEN_REVERSE_H
225