Home | History | Annotate | Download | only in Core
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2007-2010 Benoit Jacob <jacob.benoit.1 (at) gmail.com>
      5 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud (at) inria.fr>
      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::traits<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 /** \class MapBase
     21   * \ingroup Core_Module
     22   *
     23   * \brief Base class for Map and Block expression with direct access
     24   *
     25   * \sa class Map, class Block
     26   */
     27 template<typename Derived> class MapBase<Derived, ReadOnlyAccessors>
     28   : public internal::dense_xpr_base<Derived>::type
     29 {
     30   public:
     31 
     32     typedef typename internal::dense_xpr_base<Derived>::type Base;
     33     enum {
     34       RowsAtCompileTime = internal::traits<Derived>::RowsAtCompileTime,
     35       ColsAtCompileTime = internal::traits<Derived>::ColsAtCompileTime,
     36       SizeAtCompileTime = Base::SizeAtCompileTime
     37     };
     38 
     39     typedef typename internal::traits<Derived>::StorageKind StorageKind;
     40     typedef typename internal::traits<Derived>::Index Index;
     41     typedef typename internal::traits<Derived>::Scalar Scalar;
     42     typedef typename internal::packet_traits<Scalar>::type PacketScalar;
     43     typedef typename NumTraits<Scalar>::Real RealScalar;
     44     typedef typename internal::conditional<
     45                          bool(internal::is_lvalue<Derived>::value),
     46                          Scalar *,
     47                          const Scalar *>::type
     48                      PointerType;
     49 
     50     using Base::derived;
     51 //    using Base::RowsAtCompileTime;
     52 //    using Base::ColsAtCompileTime;
     53 //    using Base::SizeAtCompileTime;
     54     using Base::MaxRowsAtCompileTime;
     55     using Base::MaxColsAtCompileTime;
     56     using Base::MaxSizeAtCompileTime;
     57     using Base::IsVectorAtCompileTime;
     58     using Base::Flags;
     59     using Base::IsRowMajor;
     60 
     61     using Base::rows;
     62     using Base::cols;
     63     using Base::size;
     64     using Base::coeff;
     65     using Base::coeffRef;
     66     using Base::lazyAssign;
     67     using Base::eval;
     68 
     69     using Base::innerStride;
     70     using Base::outerStride;
     71     using Base::rowStride;
     72     using Base::colStride;
     73 
     74     // bug 217 - compile error on ICC 11.1
     75     using Base::operator=;
     76 
     77     typedef typename Base::CoeffReturnType CoeffReturnType;
     78 
     79     inline Index rows() const { return m_rows.value(); }
     80     inline Index cols() const { return m_cols.value(); }
     81 
     82     /** Returns a pointer to the first coefficient of the matrix or vector.
     83       *
     84       * \note When addressing this data, make sure to honor the strides returned by innerStride() and outerStride().
     85       *
     86       * \sa innerStride(), outerStride()
     87       */
     88     inline const Scalar* data() const { return m_data; }
     89 
     90     inline const Scalar& coeff(Index rowId, Index colId) const
     91     {
     92       return m_data[colId * colStride() + rowId * rowStride()];
     93     }
     94 
     95     inline const Scalar& coeff(Index index) const
     96     {
     97       EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
     98       return m_data[index * innerStride()];
     99     }
    100 
    101     inline const Scalar& coeffRef(Index rowId, Index colId) const
    102     {
    103       return this->m_data[colId * colStride() + rowId * rowStride()];
    104     }
    105 
    106     inline const Scalar& coeffRef(Index index) const
    107     {
    108       EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
    109       return this->m_data[index * innerStride()];
    110     }
    111 
    112     template<int LoadMode>
    113     inline PacketScalar packet(Index rowId, Index colId) const
    114     {
    115       return internal::ploadt<PacketScalar, LoadMode>
    116                (m_data + (colId * colStride() + rowId * rowStride()));
    117     }
    118 
    119     template<int LoadMode>
    120     inline PacketScalar packet(Index index) const
    121     {
    122       EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
    123       return internal::ploadt<PacketScalar, LoadMode>(m_data + index * innerStride());
    124     }
    125 
    126     inline MapBase(PointerType dataPtr) : m_data(dataPtr), m_rows(RowsAtCompileTime), m_cols(ColsAtCompileTime)
    127     {
    128       EIGEN_STATIC_ASSERT_FIXED_SIZE(Derived)
    129       checkSanity();
    130     }
    131 
    132     inline MapBase(PointerType dataPtr, Index vecSize)
    133             : m_data(dataPtr),
    134               m_rows(RowsAtCompileTime == Dynamic ? vecSize : Index(RowsAtCompileTime)),
    135               m_cols(ColsAtCompileTime == Dynamic ? vecSize : Index(ColsAtCompileTime))
    136     {
    137       EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
    138       eigen_assert(vecSize >= 0);
    139       eigen_assert(dataPtr == 0 || SizeAtCompileTime == Dynamic || SizeAtCompileTime == vecSize);
    140       checkSanity();
    141     }
    142 
    143     inline MapBase(PointerType dataPtr, Index nbRows, Index nbCols)
    144             : m_data(dataPtr), m_rows(nbRows), m_cols(nbCols)
    145     {
    146       eigen_assert( (dataPtr == 0)
    147               || (   nbRows >= 0 && (RowsAtCompileTime == Dynamic || RowsAtCompileTime == nbRows)
    148                   && nbCols >= 0 && (ColsAtCompileTime == Dynamic || ColsAtCompileTime == nbCols)));
    149       checkSanity();
    150     }
    151 
    152   protected:
    153 
    154     void checkSanity() const
    155     {
    156       EIGEN_STATIC_ASSERT(EIGEN_IMPLIES(internal::traits<Derived>::Flags&PacketAccessBit,
    157                                         internal::inner_stride_at_compile_time<Derived>::ret==1),
    158                           PACKET_ACCESS_REQUIRES_TO_HAVE_INNER_STRIDE_FIXED_TO_1);
    159       eigen_assert(EIGEN_IMPLIES(internal::traits<Derived>::Flags&AlignedBit, (size_t(m_data) % 16) == 0)
    160                    && "input pointer is not aligned on a 16 byte boundary");
    161     }
    162 
    163     PointerType m_data;
    164     const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_rows;
    165     const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_cols;
    166 };
    167 
    168 template<typename Derived> class MapBase<Derived, WriteAccessors>
    169   : public MapBase<Derived, ReadOnlyAccessors>
    170 {
    171     typedef MapBase<Derived, ReadOnlyAccessors> ReadOnlyMapBase;
    172   public:
    173 
    174     typedef MapBase<Derived, ReadOnlyAccessors> Base;
    175 
    176     typedef typename Base::Scalar Scalar;
    177     typedef typename Base::PacketScalar PacketScalar;
    178     typedef typename Base::Index Index;
    179     typedef typename Base::PointerType PointerType;
    180 
    181     using Base::derived;
    182     using Base::rows;
    183     using Base::cols;
    184     using Base::size;
    185     using Base::coeff;
    186     using Base::coeffRef;
    187 
    188     using Base::innerStride;
    189     using Base::outerStride;
    190     using Base::rowStride;
    191     using Base::colStride;
    192 
    193     typedef typename internal::conditional<
    194                     internal::is_lvalue<Derived>::value,
    195                     Scalar,
    196                     const Scalar
    197                   >::type ScalarWithConstIfNotLvalue;
    198 
    199     inline const Scalar* data() const { return this->m_data; }
    200     inline ScalarWithConstIfNotLvalue* data() { return this->m_data; } // no const-cast here so non-const-correct code will give a compile error
    201 
    202     inline ScalarWithConstIfNotLvalue& coeffRef(Index row, Index col)
    203     {
    204       return this->m_data[col * colStride() + row * rowStride()];
    205     }
    206 
    207     inline ScalarWithConstIfNotLvalue& coeffRef(Index index)
    208     {
    209       EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
    210       return this->m_data[index * innerStride()];
    211     }
    212 
    213     template<int StoreMode>
    214     inline void writePacket(Index row, Index col, const PacketScalar& val)
    215     {
    216       internal::pstoret<Scalar, PacketScalar, StoreMode>
    217                (this->m_data + (col * colStride() + row * rowStride()), val);
    218     }
    219 
    220     template<int StoreMode>
    221     inline void writePacket(Index index, const PacketScalar& val)
    222     {
    223       EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS(Derived)
    224       internal::pstoret<Scalar, PacketScalar, StoreMode>
    225                 (this->m_data + index * innerStride(), val);
    226     }
    227 
    228     explicit inline MapBase(PointerType dataPtr) : Base(dataPtr) {}
    229     inline MapBase(PointerType dataPtr, Index vecSize) : Base(dataPtr, vecSize) {}
    230     inline MapBase(PointerType dataPtr, Index nbRows, Index nbCols) : Base(dataPtr, nbRows, nbCols) {}
    231 
    232     Derived& operator=(const MapBase& other)
    233     {
    234       ReadOnlyMapBase::Base::operator=(other);
    235       return derived();
    236     }
    237 
    238     // In theory we could simply refer to Base:Base::operator=, but MSVC does not like Base::Base,
    239     // see bugs 821 and 920.
    240     using ReadOnlyMapBase::Base::operator=;
    241 };
    242 
    243 #undef EIGEN_STATIC_ASSERT_INDEX_BASED_ACCESS
    244 
    245 } // end namespace Eigen
    246 
    247 #endif // EIGEN_MAPBASE_H
    248