Reverse.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
00005 // Copyright (C) 2009 Ricard Marxer <email@ricardmarxer.com>
00006 // Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
00007 //
00008 // Eigen is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU Lesser General Public
00010 // License as published by the Free Software Foundation; either
00011 // version 3 of the License, or (at your option) any later version.
00012 //
00013 // Alternatively, you can redistribute it and/or
00014 // modify it under the terms of the GNU General Public License as
00015 // published by the Free Software Foundation; either version 2 of
00016 // the License, or (at your option) any later version.
00017 //
00018 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00019 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00020 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00021 // GNU General Public License for more details.
00022 //
00023 // You should have received a copy of the GNU Lesser General Public
00024 // License and a copy of the GNU General Public License along with
00025 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 #ifndef EIGEN_REVERSE_H
00028 #define EIGEN_REVERSE_H
00029 
00030 namespace Eigen { 
00031 
00046 namespace internal {
00047 
00048 template<typename MatrixType, int Direction>
00049 struct traits<Reverse<MatrixType, Direction> >
00050  : traits<MatrixType>
00051 {
00052   typedef typename MatrixType::Scalar Scalar;
00053   typedef typename traits<MatrixType>::StorageKind StorageKind;
00054   typedef typename traits<MatrixType>::XprKind XprKind;
00055   typedef typename nested<MatrixType>::type MatrixTypeNested;
00056   typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
00057   enum {
00058     RowsAtCompileTime = MatrixType::RowsAtCompileTime,
00059     ColsAtCompileTime = MatrixType::ColsAtCompileTime,
00060     MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime,
00061     MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime,
00062 
00063     // let's enable LinearAccess only with vectorization because of the product overhead
00064     LinearAccess = ( (Direction==BothDirections) && (int(_MatrixTypeNested::Flags)&PacketAccessBit) )
00065                  ? LinearAccessBit : 0,
00066 
00067     Flags = int(_MatrixTypeNested::Flags) & (HereditaryBits | LvalueBit | PacketAccessBit | LinearAccess),
00068 
00069     CoeffReadCost = _MatrixTypeNested::CoeffReadCost
00070   };
00071 };
00072 
00073 template<typename PacketScalar, bool ReversePacket> struct reverse_packet_cond
00074 {
00075   static inline PacketScalar run(const PacketScalar& x) { return preverse(x); }
00076 };
00077 
00078 template<typename PacketScalar> struct reverse_packet_cond<PacketScalar,false>
00079 {
00080   static inline PacketScalar run(const PacketScalar& x) { return x; }
00081 };
00082 
00083 } // end namespace internal 
00084 
00085 template<typename MatrixType, int Direction> class Reverse
00086   : public internal::dense_xpr_base< Reverse<MatrixType, Direction> >::type
00087 {
00088   public:
00089 
00090     typedef typename internal::dense_xpr_base<Reverse>::type Base;
00091     EIGEN_DENSE_PUBLIC_INTERFACE(Reverse)
00092     using Base::IsRowMajor;
00093 
00094     // next line is necessary because otherwise const version of operator()
00095     // is hidden by non-const version defined in this file
00096     using Base::operator(); 
00097 
00098   protected:
00099     enum {
00100       PacketSize = internal::packet_traits<Scalar>::size,
00101       IsColMajor = !IsRowMajor,
00102       ReverseRow = (Direction == Vertical)   || (Direction == BothDirections),
00103       ReverseCol = (Direction == Horizontal) || (Direction == BothDirections),
00104       OffsetRow  = ReverseRow && IsColMajor ? PacketSize : 1,
00105       OffsetCol  = ReverseCol && IsRowMajor ? PacketSize : 1,
00106       ReversePacket = (Direction == BothDirections)
00107                     || ((Direction == Vertical)   && IsColMajor)
00108                     || ((Direction == Horizontal) && IsRowMajor)
00109     };
00110     typedef internal::reverse_packet_cond<PacketScalar,ReversePacket> reverse_packet;
00111   public:
00112 
00113     inline Reverse(const MatrixType& matrix) : m_matrix(matrix) { }
00114 
00115     EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Reverse)
00116 
00117     inline Index rows() const { return m_matrix.rows(); }
00118     inline Index cols() const { return m_matrix.cols(); }
00119 
00120     inline Index innerStride() const
00121     {
00122       return -m_matrix.innerStride();
00123     }
00124 
00125     inline Scalar& operator()(Index row, Index col)
00126     {
00127       eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols());
00128       return coeffRef(row, col);
00129     }
00130 
00131     inline Scalar& coeffRef(Index row, Index col)
00132     {
00133       return m_matrix.const_cast_derived().coeffRef(ReverseRow ? m_matrix.rows() - row - 1 : row,
00134                                                     ReverseCol ? m_matrix.cols() - col - 1 : col);
00135     }
00136 
00137     inline CoeffReturnType coeff(Index row, Index col) const
00138     {
00139       return m_matrix.coeff(ReverseRow ? m_matrix.rows() - row - 1 : row,
00140                             ReverseCol ? m_matrix.cols() - col - 1 : col);
00141     }
00142 
00143     inline CoeffReturnType coeff(Index index) const
00144     {
00145       return m_matrix.coeff(m_matrix.size() - index - 1);
00146     }
00147 
00148     inline Scalar& coeffRef(Index index)
00149     {
00150       return m_matrix.const_cast_derived().coeffRef(m_matrix.size() - index - 1);
00151     }
00152 
00153     inline Scalar& operator()(Index index)
00154     {
00155       eigen_assert(index >= 0 && index < m_matrix.size());
00156       return coeffRef(index);
00157     }
00158 
00159     template<int LoadMode>
00160     inline const PacketScalar packet(Index row, Index col) const
00161     {
00162       return reverse_packet::run(m_matrix.template packet<LoadMode>(
00163                                     ReverseRow ? m_matrix.rows() - row - OffsetRow : row,
00164                                     ReverseCol ? m_matrix.cols() - col - OffsetCol : col));
00165     }
00166 
00167     template<int LoadMode>
00168     inline void writePacket(Index row, Index col, const PacketScalar& x)
00169     {
00170       m_matrix.const_cast_derived().template writePacket<LoadMode>(
00171                                       ReverseRow ? m_matrix.rows() - row - OffsetRow : row,
00172                                       ReverseCol ? m_matrix.cols() - col - OffsetCol : col,
00173                                       reverse_packet::run(x));
00174     }
00175 
00176     template<int LoadMode>
00177     inline const PacketScalar packet(Index index) const
00178     {
00179       return internal::preverse(m_matrix.template packet<LoadMode>( m_matrix.size() - index - PacketSize ));
00180     }
00181 
00182     template<int LoadMode>
00183     inline void writePacket(Index index, const PacketScalar& x)
00184     {
00185       m_matrix.const_cast_derived().template writePacket<LoadMode>(m_matrix.size() - index - PacketSize, internal::preverse(x));
00186     }
00187 
00188     const typename internal::remove_all<typename MatrixType::Nested>::type& 
00189     nestedExpression() const 
00190     {
00191       return m_matrix;
00192     }
00193 
00194   protected:
00195     typename MatrixType::Nested m_matrix;
00196 };
00197 
00204 template<typename Derived>
00205 inline typename DenseBase<Derived>::ReverseReturnType
00206 DenseBase<Derived>::reverse()
00207 {
00208   return derived();
00209 }
00210 
00212 template<typename Derived>
00213 inline const typename DenseBase<Derived>::ConstReverseReturnType
00214 DenseBase<Derived>::reverse() const
00215 {
00216   return derived();
00217 }
00218 
00231 template<typename Derived>
00232 inline void DenseBase<Derived>::reverseInPlace()
00233 {
00234   derived() = derived().reverse().eval();
00235 }
00236 
00237 } // end namespace Eigen
00238 
00239 #endif // EIGEN_REVERSE_H