MapBase.h 10.7 KB
Newer Older
LM's avatar
LM committed
1 2 3 4 5 6
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//
Don Gagne's avatar
Don Gagne committed
7 8 9
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
LM's avatar
LM committed
10 11 12 13 14

#ifndef EIGEN_MAPBASE_H
#define EIGEN_MAPBASE_H

#define EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived) \
15
      EIGEN_STATIC_ASSERT((int(internal::evaluator<Derived>::Flags) & LinearAccessBit) || Derived::IsVectorAtCompileTime, \
LM's avatar
LM committed
16 17
                          YOU_ARE_TRYING_TO_USE_AN_INDEX_BASED_ACCESSOR_ON_AN_EXPRESSION_THAT_DOES_NOT_SUPPORT_THAT)

Don Gagne's avatar
Don Gagne committed
18
namespace Eigen { 
LM's avatar
LM committed
19

20
/** \ingroup Core_Module
LM's avatar
LM committed
21
  *
22 23 24 25 26 27 28 29 30 31 32 33
  * \brief Base class for dense Map and Block expression with direct access
  *
  * This base class provides the const low-level accessors (e.g. coeff, coeffRef) of dense
  * Map and Block objects with direct access.
  * Typical users do not have to directly deal with this class.
  *
  * This class can be extended by through the macro plugin \c EIGEN_MAPBASE_PLUGIN.
  * See \link TopicCustomizing_Plugins customizing Eigen \endlink for details.
  *
  * The \c Derived class has to provide the following two methods describing the memory layout:
  *  \code Index innerStride() const; \endcode
  *  \code Index outerStride() const; \endcode
LM's avatar
LM committed
34 35 36 37 38 39 40 41 42 43 44 45
  *
  * \sa class Map, class Block
  */
template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
  : public internal::dense_xpr_base<Derived>::type
{
  public:

    typedef typename internal::dense_xpr_base<Derived>::type Base;
    enum {
      RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
      ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
46
      InnerStrideAtCompileTime = internal::traits<Derived>::InnerStrideAtCompileTime,
LM's avatar
LM committed
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
      SizeAtCompileTime = Base::SizeAtCompileTime
    };

    typedef typename internal::traits<Derived>::StorageKind StorageKind;
    typedef typename internal::traits<Derived>::Scalar Scalar;
    typedef typename internal::packet_traits<Scalar>::type PacketScalar;
    typedef typename NumTraits<Scalar>::Real RealScalar;
    typedef typename internal::conditional<
                         bool(internal::is_lvalue<Derived>::value),
                         Scalar *,
                         const Scalar *>::type
                     PointerType;

    using Base::derived;
//    using Base::RowsAtCompileTime;
//    using Base::ColsAtCompileTime;
//    using Base::SizeAtCompileTime;
    using Base::MaxRowsAtCompileTime;
    using Base::MaxColsAtCompileTime;
    using Base::MaxSizeAtCompileTime;
    using Base::IsVectorAtCompileTime;
    using Base::Flags;
    using Base::IsRowMajor;

    using Base::rows;
    using Base::cols;
    using Base::size;
    using Base::coeff;
    using Base::coeffRef;
    using Base::lazyAssign;
    using Base::eval;

    using Base::innerStride;
    using Base::outerStride;
    using Base::rowStride;
    using Base::colStride;

    // bug 217 - compile error on ICC 11.1
    using Base::operator=;

    typedef typename Base::CoeffReturnType CoeffReturnType;

89 90 91 92
    /** \copydoc DenseBase::rows() */
    EIGEN_DEVICE_FUNC inline Index rows() const { return m_rows.value(); }
    /** \copydoc DenseBase::cols() */
    EIGEN_DEVICE_FUNC inline Index cols() const { return m_cols.value(); }
LM's avatar
LM committed
93 94 95 96 97 98 99

    /** Returns a pointer to the first coefficient of the matrix or vector.
      *
      * \note When addressing this data, make sure to honor the strides returned by innerStride() and outerStride().
      *
      * \sa innerStride(), outerStride()
      */
100
    EIGEN_DEVICE_FUNC inline const Scalar* data() const { return m_data; }
LM's avatar
LM committed
101

102 103
    /** \copydoc PlainObjectBase::coeff(Index,Index) const */
    EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
104
    inline const Scalar& coeff(Index rowId, Index colId) const
LM's avatar
LM committed
105
    {
Don Gagne's avatar
Don Gagne committed
106
      return m_data[colId * colStride() + rowId * rowStride()];
LM's avatar
LM committed
107 108
    }

109 110
    /** \copydoc PlainObjectBase::coeff(Index) const */
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
111 112 113 114 115 116
    inline const Scalar& coeff(Index index) const
    {
      EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
      return m_data[index * innerStride()];
    }

117 118
    /** \copydoc PlainObjectBase::coeffRef(Index,Index) const */
    EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
119
    inline const Scalar& coeffRef(Index rowId, Index colId) const
LM's avatar
LM committed
120
    {
Don Gagne's avatar
Don Gagne committed
121
      return this->m_data[colId * colStride() + rowId * rowStride()];
LM's avatar
LM committed
122 123
    }

124 125
    /** \copydoc PlainObjectBase::coeffRef(Index) const */
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
126 127 128 129 130 131
    inline const Scalar& coeffRef(Index index) const
    {
      EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
      return this->m_data[index * innerStride()];
    }

132
    /** \internal */
LM's avatar
LM committed
133
    template<int LoadMode>
Don Gagne's avatar
Don Gagne committed
134
    inline PacketScalar packet(Index rowId, Index colId) const
LM's avatar
LM committed
135 136
    {
      return internal::ploadt<PacketScalar, LoadMode>
Don Gagne's avatar
Don Gagne committed
137
               (m_data + (colId * colStride() + rowId * rowStride()));
LM's avatar
LM committed
138 139
    }

140
    /** \internal */
LM's avatar
LM committed
141 142 143 144 145 146 147
    template<int LoadMode>
    inline PacketScalar packet(Index index) const
    {
      EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
      return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride());
    }

148 149
    /** \internal Constructor for fixed size matrices or vectors */
    EIGEN_DEVICE_FUNC
150
    explicit inline MapBase(PointerType dataPtr) : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
LM's avatar
LM committed
151 152
    {
      EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
153
      checkSanity<Derived>();
LM's avatar
LM committed
154 155
    }

156 157
    /** \internal Constructor for dynamically sized vectors */
    EIGEN_DEVICE_FUNC
Don Gagne's avatar
Don Gagne committed
158 159 160 161
    inline MapBase(PointerType dataPtr, Index vecSize)
            : m_data(dataPtr),
              m_rows(RowsAtCompileTime == Dynamic ? vecSize : Index(RowsAtCompileTime)),
              m_cols(ColsAtCompileTime == Dynamic ? vecSize : Index(ColsAtCompileTime))
LM's avatar
LM committed
162 163
    {
      EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
Don Gagne's avatar
Don Gagne committed
164 165
      eigen_assert(vecSize >= 0);
      eigen_assert(dataPtr == 0 || SizeAtCompileTime == Dynamic || SizeAtCompileTime == vecSize);
166
      checkSanity<Derived>();
LM's avatar
LM committed
167 168
    }

169 170 171 172
    /** \internal Constructor for dynamically sized matrices */
    EIGEN_DEVICE_FUNC
    inline MapBase(PointerType dataPtr, Index rows, Index cols)
            : m_data(dataPtr), m_rows(rows), m_cols(cols)
LM's avatar
LM committed
173
    {
Don Gagne's avatar
Don Gagne committed
174
      eigen_assert( (dataPtr == 0)
175 176 177
              || (   rows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == rows)
                  && cols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == cols)));
      checkSanity<Derived>();
LM's avatar
LM committed
178 179
    }

180 181 182 183
    #ifdef EIGEN_MAPBASE_PLUGIN
    #include EIGEN_MAPBASE_PLUGIN
    #endif

LM's avatar
LM committed
184 185
  protected:

186 187 188
    template<typename T>
    EIGEN_DEVICE_FUNC
    void checkSanity(typename internal::enable_if<(internal::traits<T>::Alignment>0),void*>::type = 0) const
LM's avatar
LM committed
189
    {
190 191 192 193 194 195 196
#if EIGEN_MAX_ALIGN_BYTES>0
      // innerStride() is not set yet when this function is called, so we optimistically assume the lowest plausible value:
      const Index minInnerStride = InnerStrideAtCompileTime == Dynamic ? 1 : Index(InnerStrideAtCompileTime);
      EIGEN_ONLY_USED_FOR_DEBUG(minInnerStride);
      eigen_assert((   ((internal::UIntPtr(m_data) % internal::traits<Derived>::Alignment) == 0)
                    || (cols() * rows() * minInnerStride * sizeof(Scalar)) < internal::traits<Derived>::Alignment ) && "data is not aligned");
#endif
LM's avatar
LM committed
197 198
    }

199 200 201 202 203
    template<typename T>
    EIGEN_DEVICE_FUNC
    void checkSanity(typename internal::enable_if<internal::traits<T>::Alignment==0,void*>::type = 0) const
    {}

LM's avatar
LM committed
204 205 206 207 208
    PointerType m_data;
    const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_rows;
    const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_cols;
};

209 210 211 212 213 214 215 216 217 218
/** \ingroup Core_Module
  *
  * \brief Base class for non-const dense Map and Block expression with direct access
  *
  * This base class provides the non-const low-level accessors (e.g. coeff and coeffRef) of
  * dense Map and Block objects with direct access.
  * It inherits MapBase<Derived, ReadOnlyAccessors> which defines the const variant for reading specific entries.
  *
  * \sa class Map, class Block
  */
LM's avatar
LM committed
219 220 221
template<typename Derived> class MapBase<Derived, WriteAccessors>
  : public MapBase<Derived, ReadOnlyAccessors>
{
222
    typedef MapBase<Derived, ReadOnlyAccessors> ReadOnlyMapBase;
LM's avatar
LM committed
223 224 225 226 227 228
  public:

    typedef MapBase<Derived, ReadOnlyAccessors> Base;

    typedef typename Base::Scalar Scalar;
    typedef typename Base::PacketScalar PacketScalar;
229
    typedef typename Base::StorageIndex StorageIndex;
LM's avatar
LM committed
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
    typedef typename Base::PointerType PointerType;

    using Base::derived;
    using Base::rows;
    using Base::cols;
    using Base::size;
    using Base::coeff;
    using Base::coeffRef;

    using Base::innerStride;
    using Base::outerStride;
    using Base::rowStride;
    using Base::colStride;

    typedef typename internal::conditional<
                    internal::is_lvalue<Derived>::value,
                    Scalar,
                    const Scalar
                  >::type ScalarWithConstIfNotLvalue;

250
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
251
    inline const Scalar* data() const { return this->m_data; }
252
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
253 254
    inline ScalarWithConstIfNotLvalue* data() { return this->m_data; } // no const-cast here so non-const-correct code will give a compile error

255
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
256 257 258 259 260
    inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col)
    {
      return this->m_data[col * colStride() + row * rowStride()];
    }

261
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
262 263 264 265 266 267 268
    inline ScalarWithConstIfNotLvalue& coeffRef(Index index)
    {
      EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
      return this->m_data[index * innerStride()];
    }

    template<int StoreMode>
Don Gagne's avatar
Don Gagne committed
269
    inline void writePacket(Index row, Index col, const PacketScalar& val)
LM's avatar
LM committed
270 271
    {
      internal::pstoret<Scalar, PacketScalar, StoreMode>
Don Gagne's avatar
Don Gagne committed
272
               (this->m_data + (col * colStride() + row * rowStride()), val);
LM's avatar
LM committed
273 274 275
    }

    template<int StoreMode>
Don Gagne's avatar
Don Gagne committed
276
    inline void writePacket(Index index, const PacketScalar& val)
LM's avatar
LM committed
277 278 279
    {
      EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
      internal::pstoret<Scalar, PacketScalar, StoreMode>
Don Gagne's avatar
Don Gagne committed
280
                (this->m_data + index * innerStride(), val);
LM's avatar
LM committed
281 282
    }

283 284 285
    EIGEN_DEVICE_FUNC explicit inline MapBase(PointerType dataPtr) : Base(dataPtr) {}
    EIGEN_DEVICE_FUNC inline MapBase(PointerType dataPtr, Index vecSize) : Base(dataPtr, vecSize) {}
    EIGEN_DEVICE_FUNC inline MapBase(PointerType dataPtr, Index rows, Index cols) : Base(dataPtr, rows, cols) {}
LM's avatar
LM committed
286

287
    EIGEN_DEVICE_FUNC
LM's avatar
LM committed
288 289
    Derived& operator=(const MapBase& other)
    {
290
      ReadOnlyMapBase::Base::operator=(other);
LM's avatar
LM committed
291 292 293
      return derived();
    }

294 295 296
    // In theory we could simply refer to Base:Base::operator=, but MSVC does not like Base::Base,
    // see bugs 821 and 920.
    using ReadOnlyMapBase::Base::operator=;
LM's avatar
LM committed
297 298
};

299 300
#undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS

Don Gagne's avatar
Don Gagne committed
301
} // end namespace Eigen
LM's avatar
LM committed
302 303

#endif // EIGEN_MAPBASE_H