Home | History | Annotate | Download | only in SparseCore
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2015 Gael Guennebaud <gael.guennebaud (at) inria.fr>
      5 //
      6 // This Source Code Form is subject to the terms of the Mozilla
      7 // Public License v. 2.0. If a copy of the MPL was not distributed
      8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9 
     10 #ifndef EIGEN_SPARSE_REF_H
     11 #define EIGEN_SPARSE_REF_H
     12 
     13 namespace Eigen {
     14 
     15 enum {
     16   StandardCompressedFormat = 2 /**< used by Ref<SparseMatrix> to specify whether the input storage must be in standard compressed form */
     17 };
     18 
     19 namespace internal {
     20 
     21 template<typename Derived> class SparseRefBase;
     22 
     23 template<typename MatScalar, int MatOptions, typename MatIndex, int _Options, typename _StrideType>
     24 struct traits<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> >
     25   : public traits<SparseMatrix<MatScalar,MatOptions,MatIndex> >
     26 {
     27   typedef SparseMatrix<MatScalar,MatOptions,MatIndex> PlainObjectType;
     28   enum {
     29     Options = _Options,
     30     Flags = traits<PlainObjectType>::Flags | CompressedAccessBit | NestByRefBit
     31   };
     32 
     33   template<typename Derived> struct match {
     34     enum {
     35       StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime || ((PlainObjectType::Flags&RowMajorBit)==(Derived::Flags&RowMajorBit)),
     36       MatchAtCompileTime = (Derived::Flags&CompressedAccessBit) && StorageOrderMatch
     37     };
     38     typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type;
     39   };
     40 
     41 };
     42 
     43 template<typename MatScalar, int MatOptions, typename MatIndex, int _Options, typename _StrideType>
     44 struct traits<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> >
     45   : public traits<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> >
     46 {
     47   enum {
     48     Flags = (traits<SparseMatrix<MatScalar,MatOptions,MatIndex> >::Flags | CompressedAccessBit | NestByRefBit) & ~LvalueBit
     49   };
     50 };
     51 
     52 template<typename MatScalar, int MatOptions, typename MatIndex, int _Options, typename _StrideType>
     53 struct traits<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> >
     54   : public traits<SparseVector<MatScalar,MatOptions,MatIndex> >
     55 {
     56   typedef SparseVector<MatScalar,MatOptions,MatIndex> PlainObjectType;
     57   enum {
     58     Options = _Options,
     59     Flags = traits<PlainObjectType>::Flags | CompressedAccessBit | NestByRefBit
     60   };
     61 
     62   template<typename Derived> struct match {
     63     enum {
     64       MatchAtCompileTime = (Derived::Flags&CompressedAccessBit) && Derived::IsVectorAtCompileTime
     65     };
     66     typedef typename internal::conditional<MatchAtCompileTime,internal::true_type,internal::false_type>::type type;
     67   };
     68 
     69 };
     70 
     71 template<typename MatScalar, int MatOptions, typename MatIndex, int _Options, typename _StrideType>
     72 struct traits<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> >
     73   : public traits<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, _Options, _StrideType> >
     74 {
     75   enum {
     76     Flags = (traits<SparseVector<MatScalar,MatOptions,MatIndex> >::Flags | CompressedAccessBit | NestByRefBit) & ~LvalueBit
     77   };
     78 };
     79 
     80 template<typename Derived>
     81 struct traits<SparseRefBase<Derived> > : public traits<Derived> {};
     82 
     83 template<typename Derived> class SparseRefBase
     84   : public SparseMapBase<Derived>
     85 {
     86 public:
     87 
     88   typedef SparseMapBase<Derived> Base;
     89   EIGEN_SPARSE_PUBLIC_INTERFACE(SparseRefBase)
     90 
     91   SparseRefBase()
     92     : Base(RowsAtCompileTime==Dynamic?0:RowsAtCompileTime,ColsAtCompileTime==Dynamic?0:ColsAtCompileTime, 0, 0, 0, 0, 0)
     93   {}
     94 
     95 protected:
     96 
     97   template<typename Expression>
     98   void construct(Expression& expr)
     99   {
    100     if(expr.outerIndexPtr()==0)
    101       ::new (static_cast<Base*>(this)) Base(expr.size(), expr.nonZeros(), expr.innerIndexPtr(), expr.valuePtr());
    102     else
    103       ::new (static_cast<Base*>(this)) Base(expr.rows(), expr.cols(), expr.nonZeros(), expr.outerIndexPtr(), expr.innerIndexPtr(), expr.valuePtr(), expr.innerNonZeroPtr());
    104   }
    105 };
    106 
    107 } // namespace internal
    108 
    109 
    110 /**
    111   * \ingroup SparseCore_Module
    112   *
    113   * \brief A sparse matrix expression referencing an existing sparse expression
    114   *
    115   * \tparam SparseMatrixType the equivalent sparse matrix type of the referenced data, it must be a template instance of class SparseMatrix.
    116   * \tparam Options specifies whether the a standard compressed format is required \c Options is  \c #StandardCompressedFormat, or \c 0.
    117   *                The default is \c 0.
    118   *
    119   * \sa class Ref
    120   */
    121 #ifndef EIGEN_PARSED_BY_DOXYGEN
    122 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
    123 class Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType >
    124   : public internal::SparseRefBase<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType > >
    125 #else
    126 template<typename SparseMatrixType, int Options>
    127 class Ref<SparseMatrixType, Options>
    128   : public SparseMapBase<Derived,WriteAccessors> // yes, that's weird to use Derived here, but that works!
    129 #endif
    130 {
    131     typedef SparseMatrix<MatScalar,MatOptions,MatIndex> PlainObjectType;
    132     typedef internal::traits<Ref> Traits;
    133     template<int OtherOptions>
    134     inline Ref(const SparseMatrix<MatScalar,OtherOptions,MatIndex>& expr);
    135     template<int OtherOptions>
    136     inline Ref(const MappedSparseMatrix<MatScalar,OtherOptions,MatIndex>& expr);
    137   public:
    138 
    139     typedef internal::SparseRefBase<Ref> Base;
    140     EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)
    141 
    142 
    143     #ifndef EIGEN_PARSED_BY_DOXYGEN
    144     template<int OtherOptions>
    145     inline Ref(SparseMatrix<MatScalar,OtherOptions,MatIndex>& expr)
    146     {
    147       EIGEN_STATIC_ASSERT(bool(Traits::template match<SparseMatrix<MatScalar,OtherOptions,MatIndex> >::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
    148       eigen_assert( ((Options & int(StandardCompressedFormat))==0) || (expr.isCompressed()) );
    149       Base::construct(expr.derived());
    150     }
    151 
    152     template<int OtherOptions>
    153     inline Ref(MappedSparseMatrix<MatScalar,OtherOptions,MatIndex>& expr)
    154     {
    155       EIGEN_STATIC_ASSERT(bool(Traits::template match<SparseMatrix<MatScalar,OtherOptions,MatIndex> >::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
    156       eigen_assert( ((Options & int(StandardCompressedFormat))==0) || (expr.isCompressed()) );
    157       Base::construct(expr.derived());
    158     }
    159 
    160     template<typename Derived>
    161     inline Ref(const SparseCompressedBase<Derived>& expr)
    162     #else
    163     /** Implicit constructor from any sparse expression (2D matrix or 1D vector) */
    164     template<typename Derived>
    165     inline Ref(SparseCompressedBase<Derived>& expr)
    166     #endif
    167     {
    168       EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
    169       EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
    170       eigen_assert( ((Options & int(StandardCompressedFormat))==0) || (expr.isCompressed()) );
    171       Base::construct(expr.const_cast_derived());
    172     }
    173 };
    174 
    175 // this is the const ref version
    176 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
    177 class Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType>
    178   : public internal::SparseRefBase<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
    179 {
    180     typedef SparseMatrix<MatScalar,MatOptions,MatIndex> TPlainObjectType;
    181     typedef internal::traits<Ref> Traits;
    182   public:
    183 
    184     typedef internal::SparseRefBase<Ref> Base;
    185     EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)
    186 
    187     template<typename Derived>
    188     inline Ref(const SparseMatrixBase<Derived>& expr) : m_hasCopy(false)
    189     {
    190       construct(expr.derived(), typename Traits::template match<Derived>::type());
    191     }
    192 
    193     inline Ref(const Ref& other) : Base(other), m_hasCopy(false) {
    194       // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
    195     }
    196 
    197     template<typename OtherRef>
    198     inline Ref(const RefBase<OtherRef>& other) : m_hasCopy(false) {
    199       construct(other.derived(), typename Traits::template match<OtherRef>::type());
    200     }
    201 
    202     ~Ref() {
    203       if(m_hasCopy) {
    204         TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes);
    205         obj->~TPlainObjectType();
    206       }
    207     }
    208 
    209   protected:
    210 
    211     template<typename Expression>
    212     void construct(const Expression& expr,internal::true_type)
    213     {
    214       if((Options & int(StandardCompressedFormat)) && (!expr.isCompressed()))
    215       {
    216         TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes);
    217         ::new (obj) TPlainObjectType(expr);
    218         m_hasCopy = true;
    219         Base::construct(*obj);
    220       }
    221       else
    222       {
    223         Base::construct(expr);
    224       }
    225     }
    226 
    227     template<typename Expression>
    228     void construct(const Expression& expr, internal::false_type)
    229     {
    230       TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes);
    231       ::new (obj) TPlainObjectType(expr);
    232       m_hasCopy = true;
    233       Base::construct(*obj);
    234     }
    235 
    236   protected:
    237     char m_object_bytes[sizeof(TPlainObjectType)];
    238     bool m_hasCopy;
    239 };
    240 
    241 
    242 
    243 /**
    244   * \ingroup SparseCore_Module
    245   *
    246   * \brief A sparse vector expression referencing an existing sparse vector expression
    247   *
    248   * \tparam SparseVectorType the equivalent sparse vector type of the referenced data, it must be a template instance of class SparseVector.
    249   *
    250   * \sa class Ref
    251   */
    252 #ifndef EIGEN_PARSED_BY_DOXYGEN
    253 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
    254 class Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType >
    255   : public internal::SparseRefBase<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType > >
    256 #else
    257 template<typename SparseVectorType>
    258 class Ref<SparseVectorType>
    259   : public SparseMapBase<Derived,WriteAccessors>
    260 #endif
    261 {
    262     typedef SparseVector<MatScalar,MatOptions,MatIndex> PlainObjectType;
    263     typedef internal::traits<Ref> Traits;
    264     template<int OtherOptions>
    265     inline Ref(const SparseVector<MatScalar,OtherOptions,MatIndex>& expr);
    266   public:
    267 
    268     typedef internal::SparseRefBase<Ref> Base;
    269     EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)
    270 
    271     #ifndef EIGEN_PARSED_BY_DOXYGEN
    272     template<int OtherOptions>
    273     inline Ref(SparseVector<MatScalar,OtherOptions,MatIndex>& expr)
    274     {
    275       EIGEN_STATIC_ASSERT(bool(Traits::template match<SparseVector<MatScalar,OtherOptions,MatIndex> >::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
    276       Base::construct(expr.derived());
    277     }
    278 
    279     template<typename Derived>
    280     inline Ref(const SparseCompressedBase<Derived>& expr)
    281     #else
    282     /** Implicit constructor from any 1D sparse vector expression */
    283     template<typename Derived>
    284     inline Ref(SparseCompressedBase<Derived>& expr)
    285     #endif
    286     {
    287       EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
    288       EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
    289       Base::construct(expr.const_cast_derived());
    290     }
    291 };
    292 
    293 // this is the const ref version
    294 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
    295 class Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType>
    296   : public internal::SparseRefBase<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
    297 {
    298     typedef SparseVector<MatScalar,MatOptions,MatIndex> TPlainObjectType;
    299     typedef internal::traits<Ref> Traits;
    300   public:
    301 
    302     typedef internal::SparseRefBase<Ref> Base;
    303     EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)
    304 
    305     template<typename Derived>
    306     inline Ref(const SparseMatrixBase<Derived>& expr) : m_hasCopy(false)
    307     {
    308       construct(expr.derived(), typename Traits::template match<Derived>::type());
    309     }
    310 
    311     inline Ref(const Ref& other) : Base(other), m_hasCopy(false) {
    312       // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
    313     }
    314 
    315     template<typename OtherRef>
    316     inline Ref(const RefBase<OtherRef>& other) : m_hasCopy(false) {
    317       construct(other.derived(), typename Traits::template match<OtherRef>::type());
    318     }
    319 
    320     ~Ref() {
    321       if(m_hasCopy) {
    322         TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes);
    323         obj->~TPlainObjectType();
    324       }
    325     }
    326 
    327   protected:
    328 
    329     template<typename Expression>
    330     void construct(const Expression& expr,internal::true_type)
    331     {
    332       Base::construct(expr);
    333     }
    334 
    335     template<typename Expression>
    336     void construct(const Expression& expr, internal::false_type)
    337     {
    338       TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(m_object_bytes);
    339       ::new (obj) TPlainObjectType(expr);
    340       m_hasCopy = true;
    341       Base::construct(*obj);
    342     }
    343 
    344   protected:
    345     char m_object_bytes[sizeof(TPlainObjectType)];
    346     bool m_hasCopy;
    347 };
    348 
    349 namespace internal {
    350 
    351 // FIXME shall we introduce a general evaluatior_ref that we can specialize for any sparse object once, and thus remove this copy-pasta thing...
    352 
    353 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
    354 struct evaluator<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
    355   : evaluator<SparseCompressedBase<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > >
    356 {
    357   typedef evaluator<SparseCompressedBase<Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base;
    358   typedef Ref<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType;
    359   evaluator() : Base() {}
    360   explicit evaluator(const XprType &mat) : Base(mat) {}
    361 };
    362 
    363 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
    364 struct evaluator<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
    365   : evaluator<SparseCompressedBase<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > >
    366 {
    367   typedef evaluator<SparseCompressedBase<Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base;
    368   typedef Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType;
    369   evaluator() : Base() {}
    370   explicit evaluator(const XprType &mat) : Base(mat) {}
    371 };
    372 
    373 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
    374 struct evaluator<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
    375   : evaluator<SparseCompressedBase<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > >
    376 {
    377   typedef evaluator<SparseCompressedBase<Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base;
    378   typedef Ref<SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType;
    379   evaluator() : Base() {}
    380   explicit evaluator(const XprType &mat) : Base(mat) {}
    381 };
    382 
    383 template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
    384 struct evaluator<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
    385   : evaluator<SparseCompressedBase<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > >
    386 {
    387   typedef evaluator<SparseCompressedBase<Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base;
    388   typedef Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType;
    389   evaluator() : Base() {}
    390   explicit evaluator(const XprType &mat) : Base(mat) {}
    391 };
    392 
    393 }
    394 
    395 } // end namespace Eigen
    396 
    397 #endif // EIGEN_SPARSE_REF_H
    398