/src/Geometry_Eigen/Eigen/src/Core/Reverse.h
C Header | 230 lines | 136 code | 34 blank | 60 comment | 20 complexity | d558fa0acdb9d059178b263a5b103ada MD5 | raw file
Possible License(s): AGPL-3.0, LGPL-2.1, LGPL-3.0, GPL-2.0
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// Eigen is free software; you can redistribute it and/or 9// modify it under the terms of the GNU Lesser General Public 10// License as published by the Free Software Foundation; either 11// version 3 of the License, or (at your option) any later version. 12// 13// Alternatively, you can redistribute it and/or 14// modify it under the terms of the GNU General Public License as 15// published by the Free Software Foundation; either version 2 of 16// the License, or (at your option) any later version. 17// 18// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY 19// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 20// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the 21// GNU General Public License for more details. 22// 23// You should have received a copy of the GNU Lesser General Public 24// License and a copy of the GNU General Public License along with 25// Eigen. If not, see <http://www.gnu.org/licenses/>. 26 27#ifndef EIGEN_REVERSE_H 28#define EIGEN_REVERSE_H 29 30/** \class Reverse 31 * \ingroup Core_Module 32 * 33 * \brief Expression of the reverse of a vector or matrix 34 * 35 * \param MatrixType the type of the object of which we are taking the reverse 36 * 37 * This class represents an expression of the reverse of a vector. 38 * It is the return type of MatrixBase::reverse() and VectorwiseOp::reverse() 39 * and most of the time this is the only way it is used. 40 * 41 * \sa MatrixBase::reverse(), VectorwiseOp::reverse() 42 */ 43 44namespace internal { 45 46template<typename MatrixType, int Direction> 47struct traits<Reverse<MatrixType, Direction> > 48 : traits<MatrixType> 49{ 50 typedef typename MatrixType::Scalar Scalar; 51 typedef typename traits<MatrixType>::StorageKind StorageKind; 52 typedef typename traits<MatrixType>::XprKind XprKind; 53 typedef typename nested<MatrixType>::type MatrixTypeNested; 54 typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested; 55 enum { 56 RowsAtCompileTime = MatrixType::RowsAtCompileTime, 57 ColsAtCompileTime = MatrixType::ColsAtCompileTime, 58 MaxRowsAtCompileTime = MatrixType::MaxRowsAtCompileTime, 59 MaxColsAtCompileTime = MatrixType::MaxColsAtCompileTime, 60 61 // let's enable LinearAccess only with vectorization because of the product overhead 62 LinearAccess = ( (Direction==BothDirections) && (int(_MatrixTypeNested::Flags)&PacketAccessBit) ) 63 ? LinearAccessBit : 0, 64 65 Flags = int(_MatrixTypeNested::Flags) & (HereditaryBits | LvalueBit | PacketAccessBit | LinearAccess), 66 67 CoeffReadCost = _MatrixTypeNested::CoeffReadCost 68 }; 69}; 70 71template<typename PacketScalar, bool ReversePacket> struct reverse_packet_cond 72{ 73 static inline PacketScalar run(const PacketScalar& x) { return preverse(x); } 74}; 75 76template<typename PacketScalar> struct reverse_packet_cond<PacketScalar,false> 77{ 78 static inline PacketScalar run(const PacketScalar& x) { return x; } 79}; 80 81} // end namespace internal 82 83template<typename MatrixType, int Direction> class Reverse 84 : public internal::dense_xpr_base< Reverse<MatrixType, Direction> >::type 85{ 86 public: 87 88 typedef typename internal::dense_xpr_base<Reverse>::type Base; 89 EIGEN_DENSE_PUBLIC_INTERFACE(Reverse) 90 using Base::IsRowMajor; 91 92 // next line is necessary because otherwise const version of operator() 93 // is hidden by non-const version defined in this file 94 using Base::operator(); 95 96 protected: 97 enum { 98 PacketSize = internal::packet_traits<Scalar>::size, 99 IsColMajor = !IsRowMajor, 100 ReverseRow = (Direction == Vertical) || (Direction == BothDirections), 101 ReverseCol = (Direction == Horizontal) || (Direction == BothDirections), 102 OffsetRow = ReverseRow && IsColMajor ? PacketSize : 1, 103 OffsetCol = ReverseCol && IsRowMajor ? PacketSize : 1, 104 ReversePacket = (Direction == BothDirections) 105 || ((Direction == Vertical) && IsColMajor) 106 || ((Direction == Horizontal) && IsRowMajor) 107 }; 108 typedef internal::reverse_packet_cond<PacketScalar,ReversePacket> reverse_packet; 109 public: 110 111 inline Reverse(const MatrixType& matrix) : m_matrix(matrix) { } 112 113 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Reverse) 114 115 inline Index rows() const { return m_matrix.rows(); } 116 inline Index cols() const { return m_matrix.cols(); } 117 118 inline Index innerStride() const 119 { 120 return -m_matrix.innerStride(); 121 } 122 123 inline Scalar& operator()(Index row, Index col) 124 { 125 eigen_assert(row >= 0 && row < rows() && col >= 0 && col < cols()); 126 return coeffRef(row, col); 127 } 128 129 inline Scalar& coeffRef(Index row, Index col) 130 { 131 return m_matrix.const_cast_derived().coeffRef(ReverseRow ? m_matrix.rows() - row - 1 : row, 132 ReverseCol ? m_matrix.cols() - col - 1 : col); 133 } 134 135 inline CoeffReturnType coeff(Index row, Index col) const 136 { 137 return m_matrix.coeff(ReverseRow ? m_matrix.rows() - row - 1 : row, 138 ReverseCol ? m_matrix.cols() - col - 1 : col); 139 } 140 141 inline CoeffReturnType coeff(Index index) const 142 { 143 return m_matrix.coeff(m_matrix.size() - index - 1); 144 } 145 146 inline Scalar& coeffRef(Index index) 147 { 148 return m_matrix.const_cast_derived().coeffRef(m_matrix.size() - index - 1); 149 } 150 151 inline Scalar& operator()(Index index) 152 { 153 eigen_assert(index >= 0 && index < m_matrix.size()); 154 return coeffRef(index); 155 } 156 157 template<int LoadMode> 158 inline const PacketScalar packet(Index row, Index col) const 159 { 160 return reverse_packet::run(m_matrix.template packet<LoadMode>( 161 ReverseRow ? m_matrix.rows() - row - OffsetRow : row, 162 ReverseCol ? m_matrix.cols() - col - OffsetCol : col)); 163 } 164 165 template<int LoadMode> 166 inline void writePacket(Index row, Index col, const PacketScalar& x) 167 { 168 m_matrix.const_cast_derived().template writePacket<LoadMode>( 169 ReverseRow ? m_matrix.rows() - row - OffsetRow : row, 170 ReverseCol ? m_matrix.cols() - col - OffsetCol : col, 171 reverse_packet::run(x)); 172 } 173 174 template<int LoadMode> 175 inline const PacketScalar packet(Index index) const 176 { 177 return internal::preverse(m_matrix.template packet<LoadMode>( m_matrix.size() - index - PacketSize )); 178 } 179 180 template<int LoadMode> 181 inline void writePacket(Index index, const PacketScalar& x) 182 { 183 m_matrix.const_cast_derived().template writePacket<LoadMode>(m_matrix.size() - index - PacketSize, internal::preverse(x)); 184 } 185 186 protected: 187 const typename MatrixType::Nested m_matrix; 188}; 189 190/** \returns an expression of the reverse of *this. 191 * 192 * Example: \include MatrixBase_reverse.cpp 193 * Output: \verbinclude MatrixBase_reverse.out 194 * 195 */ 196template<typename Derived> 197inline typename DenseBase<Derived>::ReverseReturnType 198DenseBase<Derived>::reverse() 199{ 200 return derived(); 201} 202 203/** This is the const version of reverse(). */ 204template<typename Derived> 205inline const typename DenseBase<Derived>::ConstReverseReturnType 206DenseBase<Derived>::reverse() const 207{ 208 return derived(); 209} 210 211/** This is the "in place" version of reverse: it reverses \c *this. 212 * 213 * In most cases it is probably better to simply use the reversed expression 214 * of a matrix. However, when reversing the matrix data itself is really needed, 215 * then this "in-place" version is probably the right choice because it provides 216 * the following additional features: 217 * - less error prone: doing the same operation with .reverse() requires special care: 218 * \code m = m.reverse().eval(); \endcode 219 * - this API allows to avoid creating a temporary (the current implementation creates a temporary, but that could be avoided using swap) 220 * - it allows future optimizations (cache friendliness, etc.) 221 * 222 * \sa reverse() */ 223template<typename Derived> 224inline void DenseBase<Derived>::reverseInPlace() 225{ 226 derived() = derived().reverse().eval(); 227} 228 229 230#endif // EIGEN_REVERSE_H