SparseMap.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  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@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. #ifndef EIGEN_SPARSE_MAP_H
  10. #define EIGEN_SPARSE_MAP_H
  11. namespace Eigen {
  12. namespace internal {
  13. template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
  14. struct traits<Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
  15. : public traits<SparseMatrix<MatScalar,MatOptions,MatIndex> >
  16. {
  17. typedef SparseMatrix<MatScalar,MatOptions,MatIndex> PlainObjectType;
  18. typedef traits<PlainObjectType> TraitsBase;
  19. enum {
  20. Flags = TraitsBase::Flags & (~NestByRefBit)
  21. };
  22. };
  23. template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
  24. struct traits<Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
  25. : public traits<SparseMatrix<MatScalar,MatOptions,MatIndex> >
  26. {
  27. typedef SparseMatrix<MatScalar,MatOptions,MatIndex> PlainObjectType;
  28. typedef traits<PlainObjectType> TraitsBase;
  29. enum {
  30. Flags = TraitsBase::Flags & (~ (NestByRefBit | LvalueBit))
  31. };
  32. };
  33. } // end namespace internal
  34. template<typename Derived,
  35. int Level = internal::accessors_level<Derived>::has_write_access ? WriteAccessors : ReadOnlyAccessors
  36. > class SparseMapBase;
  37. /** \ingroup SparseCore_Module
  38. * class SparseMapBase
  39. * \brief Common base class for Map and Ref instance of sparse matrix and vector.
  40. */
  41. template<typename Derived>
  42. class SparseMapBase<Derived,ReadOnlyAccessors>
  43. : public SparseCompressedBase<Derived>
  44. {
  45. public:
  46. typedef SparseCompressedBase<Derived> Base;
  47. typedef typename Base::Scalar Scalar;
  48. typedef typename Base::StorageIndex StorageIndex;
  49. enum { IsRowMajor = Base::IsRowMajor };
  50. using Base::operator=;
  51. protected:
  52. typedef typename internal::conditional<
  53. bool(internal::is_lvalue<Derived>::value),
  54. Scalar *, const Scalar *>::type ScalarPointer;
  55. typedef typename internal::conditional<
  56. bool(internal::is_lvalue<Derived>::value),
  57. StorageIndex *, const StorageIndex *>::type IndexPointer;
  58. Index m_outerSize;
  59. Index m_innerSize;
  60. Array<StorageIndex,2,1> m_zero_nnz;
  61. IndexPointer m_outerIndex;
  62. IndexPointer m_innerIndices;
  63. ScalarPointer m_values;
  64. IndexPointer m_innerNonZeros;
  65. public:
  66. /** \copydoc SparseMatrixBase::rows() */
  67. inline Index rows() const { return IsRowMajor ? m_outerSize : m_innerSize; }
  68. /** \copydoc SparseMatrixBase::cols() */
  69. inline Index cols() const { return IsRowMajor ? m_innerSize : m_outerSize; }
  70. /** \copydoc SparseMatrixBase::innerSize() */
  71. inline Index innerSize() const { return m_innerSize; }
  72. /** \copydoc SparseMatrixBase::outerSize() */
  73. inline Index outerSize() const { return m_outerSize; }
  74. /** \copydoc SparseCompressedBase::nonZeros */
  75. inline Index nonZeros() const { return m_zero_nnz[1]; }
  76. /** \copydoc SparseCompressedBase::isCompressed */
  77. bool isCompressed() const { return m_innerNonZeros==0; }
  78. //----------------------------------------
  79. // direct access interface
  80. /** \copydoc SparseMatrix::valuePtr */
  81. inline const Scalar* valuePtr() const { return m_values; }
  82. /** \copydoc SparseMatrix::innerIndexPtr */
  83. inline const StorageIndex* innerIndexPtr() const { return m_innerIndices; }
  84. /** \copydoc SparseMatrix::outerIndexPtr */
  85. inline const StorageIndex* outerIndexPtr() const { return m_outerIndex; }
  86. /** \copydoc SparseMatrix::innerNonZeroPtr */
  87. inline const StorageIndex* innerNonZeroPtr() const { return m_innerNonZeros; }
  88. //----------------------------------------
  89. /** \copydoc SparseMatrix::coeff */
  90. inline Scalar coeff(Index row, Index col) const
  91. {
  92. const Index outer = IsRowMajor ? row : col;
  93. const Index inner = IsRowMajor ? col : row;
  94. Index start = m_outerIndex[outer];
  95. Index end = isCompressed() ? m_outerIndex[outer+1] : start + m_innerNonZeros[outer];
  96. if (start==end)
  97. return Scalar(0);
  98. else if (end>0 && inner==m_innerIndices[end-1])
  99. return m_values[end-1];
  100. // ^^ optimization: let's first check if it is the last coefficient
  101. // (very common in high level algorithms)
  102. const StorageIndex* r = std::lower_bound(&m_innerIndices[start],&m_innerIndices[end-1],inner);
  103. const Index id = r-&m_innerIndices[0];
  104. return ((*r==inner) && (id<end)) ? m_values[id] : Scalar(0);
  105. }
  106. inline SparseMapBase(Index rows, Index cols, Index nnz, IndexPointer outerIndexPtr, IndexPointer innerIndexPtr,
  107. ScalarPointer valuePtr, IndexPointer innerNonZerosPtr = 0)
  108. : m_outerSize(IsRowMajor?rows:cols), m_innerSize(IsRowMajor?cols:rows), m_zero_nnz(0,internal::convert_index<StorageIndex>(nnz)), m_outerIndex(outerIndexPtr),
  109. m_innerIndices(innerIndexPtr), m_values(valuePtr), m_innerNonZeros(innerNonZerosPtr)
  110. {}
  111. // for vectors
  112. inline SparseMapBase(Index size, Index nnz, IndexPointer innerIndexPtr, ScalarPointer valuePtr)
  113. : m_outerSize(1), m_innerSize(size), m_zero_nnz(0,internal::convert_index<StorageIndex>(nnz)), m_outerIndex(m_zero_nnz.data()),
  114. m_innerIndices(innerIndexPtr), m_values(valuePtr), m_innerNonZeros(0)
  115. {}
  116. /** Empty destructor */
  117. inline ~SparseMapBase() {}
  118. protected:
  119. inline SparseMapBase() {}
  120. };
  121. /** \ingroup SparseCore_Module
  122. * class SparseMapBase
  123. * \brief Common base class for writable Map and Ref instance of sparse matrix and vector.
  124. */
  125. template<typename Derived>
  126. class SparseMapBase<Derived,WriteAccessors>
  127. : public SparseMapBase<Derived,ReadOnlyAccessors>
  128. {
  129. typedef MapBase<Derived, ReadOnlyAccessors> ReadOnlyMapBase;
  130. public:
  131. typedef SparseMapBase<Derived, ReadOnlyAccessors> Base;
  132. typedef typename Base::Scalar Scalar;
  133. typedef typename Base::StorageIndex StorageIndex;
  134. enum { IsRowMajor = Base::IsRowMajor };
  135. using Base::operator=;
  136. public:
  137. //----------------------------------------
  138. // direct access interface
  139. using Base::valuePtr;
  140. using Base::innerIndexPtr;
  141. using Base::outerIndexPtr;
  142. using Base::innerNonZeroPtr;
  143. /** \copydoc SparseMatrix::valuePtr */
  144. inline Scalar* valuePtr() { return Base::m_values; }
  145. /** \copydoc SparseMatrix::innerIndexPtr */
  146. inline StorageIndex* innerIndexPtr() { return Base::m_innerIndices; }
  147. /** \copydoc SparseMatrix::outerIndexPtr */
  148. inline StorageIndex* outerIndexPtr() { return Base::m_outerIndex; }
  149. /** \copydoc SparseMatrix::innerNonZeroPtr */
  150. inline StorageIndex* innerNonZeroPtr() { return Base::m_innerNonZeros; }
  151. //----------------------------------------
  152. /** \copydoc SparseMatrix::coeffRef */
  153. inline Scalar& coeffRef(Index row, Index col)
  154. {
  155. const Index outer = IsRowMajor ? row : col;
  156. const Index inner = IsRowMajor ? col : row;
  157. Index start = Base::m_outerIndex[outer];
  158. Index end = Base::isCompressed() ? Base::m_outerIndex[outer+1] : start + Base::m_innerNonZeros[outer];
  159. eigen_assert(end>=start && "you probably called coeffRef on a non finalized matrix");
  160. eigen_assert(end>start && "coeffRef cannot be called on a zero coefficient");
  161. StorageIndex* r = std::lower_bound(&Base::m_innerIndices[start],&Base::m_innerIndices[end],inner);
  162. const Index id = r - &Base::m_innerIndices[0];
  163. eigen_assert((*r==inner) && (id<end) && "coeffRef cannot be called on a zero coefficient");
  164. return const_cast<Scalar*>(Base::m_values)[id];
  165. }
  166. inline SparseMapBase(Index rows, Index cols, Index nnz, StorageIndex* outerIndexPtr, StorageIndex* innerIndexPtr,
  167. Scalar* valuePtr, StorageIndex* innerNonZerosPtr = 0)
  168. : Base(rows, cols, nnz, outerIndexPtr, innerIndexPtr, valuePtr, innerNonZerosPtr)
  169. {}
  170. // for vectors
  171. inline SparseMapBase(Index size, Index nnz, StorageIndex* innerIndexPtr, Scalar* valuePtr)
  172. : Base(size, nnz, innerIndexPtr, valuePtr)
  173. {}
  174. /** Empty destructor */
  175. inline ~SparseMapBase() {}
  176. protected:
  177. inline SparseMapBase() {}
  178. };
  179. /** \ingroup SparseCore_Module
  180. *
  181. * \brief Specialization of class Map for SparseMatrix-like storage.
  182. *
  183. * \tparam SparseMatrixType the equivalent sparse matrix type of the referenced data, it must be a template instance of class SparseMatrix.
  184. *
  185. * \sa class Map, class SparseMatrix, class Ref<SparseMatrixType,Options>
  186. */
  187. #ifndef EIGEN_PARSED_BY_DOXYGEN
  188. template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
  189. class Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType>
  190. : public SparseMapBase<Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
  191. #else
  192. template<typename SparseMatrixType>
  193. class Map<SparseMatrixType>
  194. : public SparseMapBase<Derived,WriteAccessors>
  195. #endif
  196. {
  197. public:
  198. typedef SparseMapBase<Map> Base;
  199. EIGEN_SPARSE_PUBLIC_INTERFACE(Map)
  200. enum { IsRowMajor = Base::IsRowMajor };
  201. public:
  202. /** Constructs a read-write Map to a sparse matrix of size \a rows x \a cols, containing \a nnz non-zero coefficients,
  203. * stored as a sparse format as defined by the pointers \a outerIndexPtr, \a innerIndexPtr, and \a valuePtr.
  204. * If the optional parameter \a innerNonZerosPtr is the null pointer, then a standard compressed format is assumed.
  205. *
  206. * This constructor is available only if \c SparseMatrixType is non-const.
  207. *
  208. * More details on the expected storage schemes are given in the \ref TutorialSparse "manual pages".
  209. */
  210. inline Map(Index rows, Index cols, Index nnz, StorageIndex* outerIndexPtr,
  211. StorageIndex* innerIndexPtr, Scalar* valuePtr, StorageIndex* innerNonZerosPtr = 0)
  212. : Base(rows, cols, nnz, outerIndexPtr, innerIndexPtr, valuePtr, innerNonZerosPtr)
  213. {}
  214. #ifndef EIGEN_PARSED_BY_DOXYGEN
  215. /** Empty destructor */
  216. inline ~Map() {}
  217. };
  218. template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
  219. class Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType>
  220. : public SparseMapBase<Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
  221. {
  222. public:
  223. typedef SparseMapBase<Map> Base;
  224. EIGEN_SPARSE_PUBLIC_INTERFACE(Map)
  225. enum { IsRowMajor = Base::IsRowMajor };
  226. public:
  227. #endif
  228. /** This is the const version of the above constructor.
  229. *
  230. * This constructor is available only if \c SparseMatrixType is const, e.g.:
  231. * \code Map<const SparseMatrix<double> > \endcode
  232. */
  233. inline Map(Index rows, Index cols, Index nnz, const StorageIndex* outerIndexPtr,
  234. const StorageIndex* innerIndexPtr, const Scalar* valuePtr, const StorageIndex* innerNonZerosPtr = 0)
  235. : Base(rows, cols, nnz, outerIndexPtr, innerIndexPtr, valuePtr, innerNonZerosPtr)
  236. {}
  237. /** Empty destructor */
  238. inline ~Map() {}
  239. };
  240. namespace internal {
  241. template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
  242. struct evaluator<Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
  243. : evaluator<SparseCompressedBase<Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > >
  244. {
  245. typedef evaluator<SparseCompressedBase<Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base;
  246. typedef Map<SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType;
  247. evaluator() : Base() {}
  248. explicit evaluator(const XprType &mat) : Base(mat) {}
  249. };
  250. template<typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
  251. struct evaluator<Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> >
  252. : evaluator<SparseCompressedBase<Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > >
  253. {
  254. typedef evaluator<SparseCompressedBase<Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> > > Base;
  255. typedef Map<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType> XprType;
  256. evaluator() : Base() {}
  257. explicit evaluator(const XprType &mat) : Base(mat) {}
  258. };
  259. }
  260. } // end namespace Eigen
  261. #endif // EIGEN_SPARSE_MAP_H