$darkmode
Eigen  5.0.1-dev
SparseRef.h
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 
10 #ifndef EIGEN_SPARSE_REF_H
11 #define EIGEN_SPARSE_REF_H
12 
13 // IWYU pragma: private
14 #include "./InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 
18 enum {
20  2
21 };
22 
23 namespace internal {
24 
25 template <typename Derived>
26 class SparseRefBase;
27 
28 template <typename MatScalar, int MatOptions, typename MatIndex, int Options_, typename StrideType_>
29 struct traits<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>>
30  : public traits<SparseMatrix<MatScalar, MatOptions, MatIndex>> {
31  typedef SparseMatrix<MatScalar, MatOptions, MatIndex> PlainObjectType;
32  enum { Options = Options_, Flags = traits<PlainObjectType>::Flags | CompressedAccessBit | NestByRefBit };
33 
34  template <typename Derived>
35  struct match {
36  enum {
37  StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime ||
38  ((PlainObjectType::Flags & RowMajorBit) == (Derived::Flags & RowMajorBit)),
39  MatchAtCompileTime = (Derived::Flags & CompressedAccessBit) && StorageOrderMatch
40  };
41  typedef std::conditional_t<MatchAtCompileTime, internal::true_type, internal::false_type> type;
42  };
43 };
44 
45 template <typename MatScalar, int MatOptions, typename MatIndex, int Options_, typename StrideType_>
46 struct traits<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>>
47  : public traits<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>> {
48  enum {
49  Flags =
50  (traits<SparseMatrix<MatScalar, MatOptions, MatIndex>>::Flags | CompressedAccessBit | NestByRefBit) & ~LvalueBit
51  };
52 };
53 
54 template <typename MatScalar, int MatOptions, typename MatIndex, int Options_, typename StrideType_>
55 struct traits<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>>
56  : public traits<SparseVector<MatScalar, MatOptions, MatIndex>> {
57  typedef SparseVector<MatScalar, MatOptions, MatIndex> PlainObjectType;
58  enum { Options = Options_, Flags = traits<PlainObjectType>::Flags | CompressedAccessBit | NestByRefBit };
59 
60  template <typename Derived>
61  struct match {
62  enum { MatchAtCompileTime = (Derived::Flags & CompressedAccessBit) && Derived::IsVectorAtCompileTime };
63  typedef std::conditional_t<MatchAtCompileTime, internal::true_type, internal::false_type> type;
64  };
65 };
66 
67 template <typename MatScalar, int MatOptions, typename MatIndex, int Options_, typename StrideType_>
68 struct traits<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>>
69  : public traits<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>> {
70  enum {
71  Flags =
72  (traits<SparseVector<MatScalar, MatOptions, MatIndex>>::Flags | CompressedAccessBit | NestByRefBit) & ~LvalueBit
73  };
74 };
75 
76 template <typename Derived>
77 struct traits<SparseRefBase<Derived>> : public traits<Derived> {};
78 
79 template <typename Derived>
80 class SparseRefBase : public SparseMapBase<Derived> {
81  public:
82  typedef SparseMapBase<Derived> Base;
83  EIGEN_SPARSE_PUBLIC_INTERFACE(SparseRefBase)
84 
85  SparseRefBase()
86  : Base(RowsAtCompileTime == Dynamic ? 0 : RowsAtCompileTime, ColsAtCompileTime == Dynamic ? 0 : ColsAtCompileTime,
87  0, 0, 0, 0, 0) {}
88 
89  protected:
90  template <typename Expression>
91  void construct(Expression& expr) {
92  if (expr.outerIndexPtr() == 0)
93  internal::construct_at<Base>(this, expr.size(), expr.nonZeros(), expr.innerIndexPtr(), expr.valuePtr());
94  else
95  internal::construct_at<Base>(this, expr.rows(), expr.cols(), expr.nonZeros(), expr.outerIndexPtr(),
96  expr.innerIndexPtr(), expr.valuePtr(), expr.innerNonZeroPtr());
97  }
98 };
99 
100 } // namespace internal
101 
113 #ifndef EIGEN_PARSED_BY_DOXYGEN
114 template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
115 class Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>
116  : public internal::SparseRefBase<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
117 #else
118 template <typename SparseMatrixType, int Options>
119 class Ref<SparseMatrixType, Options>
120  : public SparseMapBase<Derived, WriteAccessors> // yes, that's weird to use Derived here, but that works!
121 #endif
122 {
124  typedef internal::traits<Ref> Traits;
125  template <int OtherOptions>
127  template <int OtherOptions>
129 
130  public:
131  typedef internal::SparseRefBase<Ref> Base;
132  EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)
133 
134 #ifndef EIGEN_PARSED_BY_DOXYGEN
135  template <int OtherOptions>
137  EIGEN_STATIC_ASSERT(
138  bool(Traits::template match<SparseMatrix<MatScalar, OtherOptions, MatIndex>>::MatchAtCompileTime),
139  STORAGE_LAYOUT_DOES_NOT_MATCH);
140  eigen_assert(((Options & int(StandardCompressedFormat)) == 0) || (expr.isCompressed()));
141  Base::construct(expr.derived());
142  }
143 
144  template <int OtherOptions>
146  EIGEN_STATIC_ASSERT(
147  bool(Traits::template match<SparseMatrix<MatScalar, OtherOptions, MatIndex>>::MatchAtCompileTime),
148  STORAGE_LAYOUT_DOES_NOT_MATCH);
149  eigen_assert(((Options & int(StandardCompressedFormat)) == 0) || (expr.isCompressed()));
150  Base::construct(expr.derived());
151  }
152 
153  template <typename Derived>
154  inline Ref(const SparseCompressedBase<Derived>& expr)
155 #else
156 
157  template <typename Derived>
159 #endif
160  {
161  EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
162  EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
163  eigen_assert(((Options & int(StandardCompressedFormat)) == 0) || (expr.isCompressed()));
164  Base::construct(expr.const_cast_derived());
165  }
166 };
167 
168 // this is the const ref version
169 template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
170 class Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>
171  : public internal::SparseRefBase<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>> {
172  typedef SparseMatrix<MatScalar, MatOptions, MatIndex> TPlainObjectType;
173  typedef internal::traits<Ref> Traits;
174 
175  public:
176  typedef internal::SparseRefBase<Ref> Base;
177  EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)
178 
179  template <typename Derived>
180  inline Ref(const SparseMatrixBase<Derived>& expr) : m_hasCopy(false) {
181  construct(expr.derived(), typename Traits::template match<Derived>::type());
182  }
183 
184  inline Ref(const Ref& other) : Base(other), m_hasCopy(false) {
185  // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
186  }
187 
188  template <typename OtherRef>
189  inline Ref(const RefBase<OtherRef>& other) : m_hasCopy(false) {
190  construct(other.derived(), typename Traits::template match<OtherRef>::type());
191  }
192 
193  ~Ref() {
194  if (m_hasCopy) {
195  internal::destroy_at(reinterpret_cast<TPlainObjectType*>(&m_storage));
196  }
197  }
198 
199  protected:
200  template <typename Expression>
201  void construct(const Expression& expr, internal::true_type) {
202  if ((Options & int(StandardCompressedFormat)) && (!expr.isCompressed())) {
203  TPlainObjectType* obj = internal::construct_at(reinterpret_cast<TPlainObjectType*>(&m_storage), expr);
204  m_hasCopy = true;
205  Base::construct(*obj);
206  } else {
207  Base::construct(expr);
208  }
209  }
210 
211  template <typename Expression>
212  void construct(const Expression& expr, internal::false_type) {
213  TPlainObjectType* obj = internal::construct_at(reinterpret_cast<TPlainObjectType*>(&m_storage), expr);
214  m_hasCopy = true;
215  Base::construct(*obj);
216  }
217 
218  protected:
219  typename internal::aligned_storage<sizeof(TPlainObjectType), EIGEN_ALIGNOF(TPlainObjectType)>::type m_storage;
220  bool m_hasCopy;
221 };
222 
233 #ifndef EIGEN_PARSED_BY_DOXYGEN
234 template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
235 class Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>
236  : public internal::SparseRefBase<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
237 #else
238 template <typename SparseVectorType>
239 class Ref<SparseVectorType> : public SparseMapBase<Derived, WriteAccessors>
240 #endif
241 {
243  typedef internal::traits<Ref> Traits;
244  template <int OtherOptions>
246 
247  public:
248  typedef internal::SparseRefBase<Ref> Base;
249  EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)
250 
251 #ifndef EIGEN_PARSED_BY_DOXYGEN
252  template <int OtherOptions>
254  EIGEN_STATIC_ASSERT(
255  bool(Traits::template match<SparseVector<MatScalar, OtherOptions, MatIndex>>::MatchAtCompileTime),
256  STORAGE_LAYOUT_DOES_NOT_MATCH);
257  Base::construct(expr.derived());
258  }
259 
260  template <typename Derived>
261  inline Ref(const SparseCompressedBase<Derived>& expr)
262 #else
263 
264  template <typename Derived>
266 #endif
267  {
268  EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
269  EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
270  Base::construct(expr.const_cast_derived());
271  }
272 };
273 
274 // this is the const ref version
275 template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
276 class Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>
277  : public internal::SparseRefBase<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>> {
278  typedef SparseVector<MatScalar, MatOptions, MatIndex> TPlainObjectType;
279  typedef internal::traits<Ref> Traits;
280 
281  public:
282  typedef internal::SparseRefBase<Ref> Base;
283  EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)
284 
285  template <typename Derived>
286  inline Ref(const SparseMatrixBase<Derived>& expr) : m_hasCopy(false) {
287  construct(expr.derived(), typename Traits::template match<Derived>::type());
288  }
289 
290  inline Ref(const Ref& other) : Base(other), m_hasCopy(false) {
291  // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
292  }
293 
294  template <typename OtherRef>
295  inline Ref(const RefBase<OtherRef>& other) : m_hasCopy(false) {
296  construct(other.derived(), typename Traits::template match<OtherRef>::type());
297  }
298 
299  ~Ref() {
300  if (m_hasCopy) {
301  internal::destroy_at(reinterpret_cast<TPlainObjectType*>(&m_storage));
302  }
303  }
304 
305  protected:
306  template <typename Expression>
307  void construct(const Expression& expr, internal::true_type) {
308  Base::construct(expr);
309  }
310 
311  template <typename Expression>
312  void construct(const Expression& expr, internal::false_type) {
313  TPlainObjectType* obj = internal::construct_at(reinterpret_cast<TPlainObjectType*>(&m_storage), expr);
314  m_hasCopy = true;
315  Base::construct(*obj);
316  }
317 
318  protected:
319  typename internal::aligned_storage<sizeof(TPlainObjectType), EIGEN_ALIGNOF(TPlainObjectType)>::type m_storage;
320  bool m_hasCopy;
321 };
322 
323 namespace internal {
324 
325 // FIXME shall we introduce a general evaluatior_ref that we can specialize for any sparse object once, and thus remove
326 // this copy-pasta thing...
327 
328 template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
329 struct evaluator<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
330  : evaluator<SparseCompressedBase<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> {
331  typedef evaluator<SparseCompressedBase<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> Base;
332  typedef Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType> XprType;
333  evaluator() : Base() {}
334  explicit evaluator(const XprType& mat) : Base(mat) {}
335 };
336 
337 template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
338 struct evaluator<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
339  : evaluator<SparseCompressedBase<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> {
340  typedef evaluator<SparseCompressedBase<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>>
341  Base;
342  typedef Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType> XprType;
343  evaluator() : Base() {}
344  explicit evaluator(const XprType& mat) : Base(mat) {}
345 };
346 
347 template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
348 struct evaluator<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
349  : evaluator<SparseCompressedBase<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> {
350  typedef evaluator<SparseCompressedBase<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> Base;
351  typedef Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType> XprType;
352  evaluator() : Base() {}
353  explicit evaluator(const XprType& mat) : Base(mat) {}
354 };
355 
356 template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
357 struct evaluator<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
358  : evaluator<SparseCompressedBase<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> {
359  typedef evaluator<SparseCompressedBase<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>>
360  Base;
361  typedef Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType> XprType;
362  evaluator() : Base() {}
363  explicit evaluator(const XprType& mat) : Base(mat) {}
364 };
365 
366 } // namespace internal
367 
368 } // end namespace Eigen
369 
370 #endif // EIGEN_SPARSE_REF_H
bool isCompressed() const
Definition: SparseCompressedBase.h:114
const unsigned int CompressedAccessBit
Definition: Constants.h:195
A versatible sparse matrix representation.
Definition: SparseMatrix.h:121
A matrix or vector expression mapping an existing array of data.
Definition: Map.h:96
const unsigned int LvalueBit
Definition: Constants.h:148
Namespace containing all symbols from the Eigen library.
Definition: B01_Experimental.dox:1
const unsigned int RowMajorBit
Definition: Constants.h:70
Base class of any sparse matrices or sparse expressions.
Definition: ForwardDeclarations.h:481
a sparse vector class
Definition: SparseUtil.h:49
constexpr SparseMatrix< Scalar_, Options_, StorageIndex_ > & derived()
Definition: EigenBase.h:49
A matrix or vector expression mapping an existing expression.
Definition: Ref.h:264
Ref(SparseCompressedBase< Derived > &expr)
Definition: SparseRef.h:158
Definition: SparseRef.h:19
const int Dynamic
Definition: Constants.h:25
bool isCompressed() const
Definition: SparseCompressedBase.h:114
Common base class for sparse [compressed]-{row|column}-storage format.
Definition: SparseCompressedBase.h:19
Ref(SparseCompressedBase< Derived > &expr)
Definition: SparseRef.h:265