1 // This file is part of Eigen, a lightweight C++ template library 2 // for linear algebra. 3 // 4 // Copyright (C) 2007-2010 Benoit Jacob <[email protected]> 5 // Copyright (C) 2008 Gael Guennebaud <[email protected]> 6 // 7 // This Source Code Form is subject to the terms of the Mozilla 8 // Public License v. 2.0. If a copy of the MPL was not distributed 9 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10 11 #ifndef EIGEN_MAPBASE_H 12 #define EIGEN_MAPBASE_H 13 14 #define EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) \ 15 EIGEN_STATIC_ASSERT((int(internal::evaluator<Derived>::Flags) & LinearAccessBit) || Derived::IsVectorAtCompileTime, \ 16 YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT) 17 18 namespace Eigen { 19 20 /** \ingroup Core_Module 21 * 22 * \brief Base class for dense Map and Block expression with direct access 23 * 24 * This base class provides the const low-level accessors (e.g. coeff, coeffRef) of dense 25 * Map and Block objects with direct access. 26 * Typical users do not have to directly deal with this class. 27 * 28 * This class can be extended by through the macro plugin \c EIGEN_MAPBASE_PLUGIN. 29 * See \link TopicCustomizing_Plugins customizing Eigen \endlink for details. 30 * 31 * The \c Derived class has to provide the following two methods describing the memory layout: 32 * \code Index innerStride() const; \endcode 33 * \code Index outerStride() const; \endcode 34 * 35 * \sa class Map, class Block 36 */ 37 template<typename Derived> class MapBase<Derived, ReadOnlyAccessors> 38 : public internal::dense_xpr_base<Derived>::type 39 { 40 public: 41 42 typedef typename internal::dense_xpr_base<Derived>::type Base; 43 enum { 44 RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime, 45 ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime, 46 InnerStrideAtCompileTime = internal::traits<Derived>::InnerStrideAtCompileTime, 47 SizeAtCompileTime = Base::SizeAtCompileTime 48 }; 49 50 typedef typename internal::traits<Derived>::StorageKind StorageKind; 51 typedef typename internal::traits<Derived>::Scalar Scalar; 52 typedef typename internal::packet_traits<Scalar>::type PacketScalar; 53 typedef typename NumTraits<Scalar>::Real RealScalar; 54 typedef typename internal::conditional< 55 bool(internal::is_lvalue<Derived>::value), 56 Scalar *, 57 const Scalar *>::type 58 PointerType; 59 60 using Base::derived; 61 // using Base::RowsAtCompileTime; 62 // using Base::ColsAtCompileTime; 63 // using Base::SizeAtCompileTime; 64 using Base::MaxRowsAtCompileTime; 65 using Base::MaxColsAtCompileTime; 66 using Base::MaxSizeAtCompileTime; 67 using Base::IsVectorAtCompileTime; 68 using Base::Flags; 69 using Base::IsRowMajor; 70 71 using Base::rows; 72 using Base::cols; 73 using Base::size; 74 using Base::coeff; 75 using Base::coeffRef; 76 using Base::lazyAssign; 77 using Base::eval; 78 79 using Base::innerStride; 80 using Base::outerStride; 81 using Base::rowStride; 82 using Base::colStride; 83 84 // bug 217 - compile error on ICC 11.1 85 using Base::operator=; 86 87 typedef typename Base::CoeffReturnType CoeffReturnType; 88 89 /** \copydoc DenseBase::rows() */ 90 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR rows()91 inline Index rows() const EIGEN_NOEXCEPT { return m_rows.value(); } 92 /** \copydoc DenseBase::cols() */ 93 EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR cols()94 inline Index cols() const EIGEN_NOEXCEPT { return m_cols.value(); } 95 96 /** Returns a pointer to the first coefficient of the matrix or vector. 97 * 98 * \note When addressing this data, make sure to honor the strides returned by innerStride() and outerStride(). 99 * 100 * \sa innerStride(), outerStride() 101 */ data()102 EIGEN_DEVICE_FUNC inline const Scalar* data() const { return m_data; } 103 104 /** \copydoc PlainObjectBase::coeff(Index,Index) const */ 105 EIGEN_DEVICE_FUNC coeff(Index rowId,Index colId)106 inline const Scalar& coeff(Index rowId, Index colId) const 107 { 108 return m_data[colId * colStride() + rowId * rowStride()]; 109 } 110 111 /** \copydoc PlainObjectBase::coeff(Index) const */ 112 EIGEN_DEVICE_FUNC coeff(Index index)113 inline const Scalar& coeff(Index index) const 114 { 115 EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) 116 return m_data[index * innerStride()]; 117 } 118 119 /** \copydoc PlainObjectBase::coeffRef(Index,Index) const */ 120 EIGEN_DEVICE_FUNC coeffRef(Index rowId,Index colId)121 inline const Scalar& coeffRef(Index rowId, Index colId) const 122 { 123 return this->m_data[colId * colStride() + rowId * rowStride()]; 124 } 125 126 /** \copydoc PlainObjectBase::coeffRef(Index) const */ 127 EIGEN_DEVICE_FUNC coeffRef(Index index)128 inline const Scalar& coeffRef(Index index) const 129 { 130 EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) 131 return this->m_data[index * innerStride()]; 132 } 133 134 /** \internal */ 135 template<int LoadMode> packet(Index rowId,Index colId)136 inline PacketScalar packet(Index rowId, Index colId) const 137 { 138 return internal::ploadt<PacketScalar, LoadMode> 139 (m_data + (colId * colStride() + rowId * rowStride())); 140 } 141 142 /** \internal */ 143 template<int LoadMode> packet(Index index)144 inline PacketScalar packet(Index index) const 145 { 146 EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) 147 return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride()); 148 } 149 150 /** \internal Constructor for fixed size matrices or vectors */ 151 EIGEN_DEVICE_FUNC MapBase(PointerType dataPtr)152 explicit inline MapBase(PointerType dataPtr) : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime) 153 { 154 EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived) 155 checkSanity<Derived>(); 156 } 157 158 /** \internal Constructor for dynamically sized vectors */ 159 EIGEN_DEVICE_FUNC MapBase(PointerType dataPtr,Index vecSize)160 inline MapBase(PointerType dataPtr, Index vecSize) 161 : m_data(dataPtr), 162 m_rows(RowsAtCompileTime == Dynamic ? vecSize : Index(RowsAtCompileTime)), 163 m_cols(ColsAtCompileTime == Dynamic ? vecSize : Index(ColsAtCompileTime)) 164 { 165 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) 166 eigen_assert(vecSize >= 0); 167 eigen_assert(dataPtr == 0 || SizeAtCompileTime == Dynamic || SizeAtCompileTime == vecSize); 168 checkSanity<Derived>(); 169 } 170 171 /** \internal Constructor for dynamically sized matrices */ 172 EIGEN_DEVICE_FUNC MapBase(PointerType dataPtr,Index rows,Index cols)173 inline MapBase(PointerType dataPtr, Index rows, Index cols) 174 : m_data(dataPtr), m_rows(rows), m_cols(cols) 175 { 176 eigen_assert( (dataPtr == 0) 177 || ( rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows) 178 && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols))); 179 checkSanity<Derived>(); 180 } 181 182 #ifdef EIGEN_MAPBASE_PLUGIN 183 #include EIGEN_MAPBASE_PLUGIN 184 #endif 185 186 protected: EIGEN_DEFAULT_COPY_CONSTRUCTOR(MapBase)187 EIGEN_DEFAULT_COPY_CONSTRUCTOR(MapBase) 188 EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MapBase) 189 190 template<typename T> 191 EIGEN_DEVICE_FUNC 192 void checkSanity(typename internal::enable_if<(internal::traits<T>::Alignment>0),void*>::type = 0) const 193 { 194 #if EIGEN_MAX_ALIGN_BYTES>0 195 // innerStride() is not set yet when this function is called, so we optimistically assume the lowest plausible value: 196 const Index minInnerStride = InnerStrideAtCompileTime == Dynamic ? 1 : Index(InnerStrideAtCompileTime); 197 EIGEN_ONLY_USED_FOR_DEBUG(minInnerStride); 198 eigen_assert(( ((internal::UIntPtr(m_data) % internal::traits<Derived>::Alignment) == 0) 199 || (cols() * rows() * minInnerStride * sizeof(Scalar)) < internal::traits<Derived>::Alignment ) && "data is not aligned"); 200 #endif 201 } 202 203 template<typename T> 204 EIGEN_DEVICE_FUNC 205 void checkSanity(typename internal::enable_if<internal::traits<T>::Alignment==0,void*>::type = 0) const 206 {} 207 208 PointerType m_data; 209 const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_rows; 210 const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_cols; 211 }; 212 213 /** \ingroup Core_Module 214 * 215 * \brief Base class for non-const dense Map and Block expression with direct access 216 * 217 * This base class provides the non-const low-level accessors (e.g. coeff and coeffRef) of 218 * dense Map and Block objects with direct access. 219 * It inherits MapBase<Derived, ReadOnlyAccessors> which defines the const variant for reading specific entries. 220 * 221 * \sa class Map, class Block 222 */ 223 template<typename Derived> class MapBase<Derived, WriteAccessors> 224 : public MapBase<Derived, ReadOnlyAccessors> 225 { 226 typedef MapBase<Derived, ReadOnlyAccessors> ReadOnlyMapBase; 227 public: 228 229 typedef MapBase<Derived, ReadOnlyAccessors> Base; 230 231 typedef typename Base::Scalar Scalar; 232 typedef typename Base::PacketScalar PacketScalar; 233 typedef typename Base::StorageIndex StorageIndex; 234 typedef typename Base::PointerType PointerType; 235 236 using Base::derived; 237 using Base::rows; 238 using Base::cols; 239 using Base::size; 240 using Base::coeff; 241 using Base::coeffRef; 242 243 using Base::innerStride; 244 using Base::outerStride; 245 using Base::rowStride; 246 using Base::colStride; 247 248 typedef typename internal::conditional< 249 internal::is_lvalue<Derived>::value, 250 Scalar, 251 const Scalar 252 >::type ScalarWithConstIfNotLvalue; 253 254 EIGEN_DEVICE_FUNC data()255 inline const Scalar* data() const { return this->m_data; } 256 EIGEN_DEVICE_FUNC data()257 inline ScalarWithConstIfNotLvalue* data() { return this->m_data; } // no const-cast here so non-const-correct code will give a compile error 258 259 EIGEN_DEVICE_FUNC coeffRef(Index row,Index col)260 inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col) 261 { 262 return this->m_data[col * colStride() + row * rowStride()]; 263 } 264 265 EIGEN_DEVICE_FUNC coeffRef(Index index)266 inline ScalarWithConstIfNotLvalue& coeffRef(Index index) 267 { 268 EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) 269 return this->m_data[index * innerStride()]; 270 } 271 272 template<int StoreMode> writePacket(Index row,Index col,const PacketScalar & val)273 inline void writePacket(Index row, Index col, const PacketScalar& val) 274 { 275 internal::pstoret<Scalar, PacketScalar, StoreMode> 276 (this->m_data + (col * colStride() + row * rowStride()), val); 277 } 278 279 template<int StoreMode> writePacket(Index index,const PacketScalar & val)280 inline void writePacket(Index index, const PacketScalar& val) 281 { 282 EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) 283 internal::pstoret<Scalar, PacketScalar, StoreMode> 284 (this->m_data + index * innerStride(), val); 285 } 286 MapBase(PointerType dataPtr)287 EIGEN_DEVICE_FUNC explicit inline MapBase(PointerType dataPtr) : Base(dataPtr) {} MapBase(PointerType dataPtr,Index vecSize)288 EIGEN_DEVICE_FUNC inline MapBase(PointerType dataPtr, Index vecSize) : Base(dataPtr, vecSize) {} MapBase(PointerType dataPtr,Index rows,Index cols)289 EIGEN_DEVICE_FUNC inline MapBase(PointerType dataPtr, Index rows, Index cols) : Base(dataPtr, rows, cols) {} 290 291 EIGEN_DEVICE_FUNC 292 Derived& operator=(const MapBase& other) 293 { 294 ReadOnlyMapBase::Base::operator=(other); 295 return derived(); 296 } 297 298 // In theory we could simply refer to Base:Base::operator=, but MSVC does not like Base::Base, 299 // see bugs 821 and 920. 300 using ReadOnlyMapBase::Base::operator=; 301 protected: 302 EIGEN_DEFAULT_COPY_CONSTRUCTOR(MapBase) 303 EIGEN_DEFAULT_EMPTY_CONSTRUCTOR_AND_DESTRUCTOR(MapBase) 304 }; 305 306 #undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS 307 308 } // end namespace Eigen 309 310 #endif // EIGEN_MAPBASE_H 311