Eigen  5.0.1
 
Loading...
Searching...
No Matches
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// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_SPARSE_REF_H
12#define EIGEN_SPARSE_REF_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
19enum {
20 StandardCompressedFormat =
21 2
22};
23
24namespace internal {
25
26template <typename Derived>
27class SparseRefBase;
28
29template <typename MatScalar, int MatOptions, typename MatIndex, int Options_, typename StrideType_>
30struct traits<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>>
31 : public traits<SparseMatrix<MatScalar, MatOptions, MatIndex>> {
32 using PlainObjectType = SparseMatrix<MatScalar, MatOptions, MatIndex>;
33 enum { Options = Options_, Flags = traits<PlainObjectType>::Flags | CompressedAccessBit | NestByRefBit };
34
35 template <typename Derived>
36 struct match {
37 enum {
38 StorageOrderMatch = PlainObjectType::IsVectorAtCompileTime || Derived::IsVectorAtCompileTime ||
39 ((PlainObjectType::Flags & RowMajorBit) == (Derived::Flags & RowMajorBit)),
40 MatchAtCompileTime = (Derived::Flags & CompressedAccessBit) && StorageOrderMatch
41 };
42 using type = bool_constant<MatchAtCompileTime>;
43 };
44};
45
46template <typename MatScalar, int MatOptions, typename MatIndex, int Options_, typename StrideType_>
47struct traits<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>>
48 : public traits<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>> {
49 enum {
50 Flags =
51 (traits<SparseMatrix<MatScalar, MatOptions, MatIndex>>::Flags | CompressedAccessBit | NestByRefBit) & ~LvalueBit
52 };
53};
54
55template <typename MatScalar, int MatOptions, typename MatIndex, int Options_, typename StrideType_>
56struct traits<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>>
57 : public traits<SparseVector<MatScalar, MatOptions, MatIndex>> {
58 using PlainObjectType = SparseVector<MatScalar, MatOptions, MatIndex>;
59 enum { Options = Options_, Flags = traits<PlainObjectType>::Flags | CompressedAccessBit | NestByRefBit };
60
61 template <typename Derived>
62 struct match {
63 enum { MatchAtCompileTime = (Derived::Flags & CompressedAccessBit) && Derived::IsVectorAtCompileTime };
64 using type = bool_constant<MatchAtCompileTime>;
65 };
66};
67
68template <typename MatScalar, int MatOptions, typename MatIndex, int Options_, typename StrideType_>
69struct traits<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>>
70 : public traits<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options_, StrideType_>> {
71 enum {
72 Flags =
73 (traits<SparseVector<MatScalar, MatOptions, MatIndex>>::Flags | CompressedAccessBit | NestByRefBit) & ~LvalueBit
74 };
75};
76
77template <typename Derived>
78struct traits<SparseRefBase<Derived>> : public traits<Derived> {};
79
80template <typename Derived>
81class SparseRefBase : public SparseMapBase<Derived> {
82 public:
83 using Base = SparseMapBase<Derived>;
84 EIGEN_SPARSE_PUBLIC_INTERFACE(SparseRefBase)
85
86 SparseRefBase()
87 : Base(RowsAtCompileTime == Dynamic ? 0 : RowsAtCompileTime, ColsAtCompileTime == Dynamic ? 0 : ColsAtCompileTime,
88 0, 0, 0, 0, 0) {}
89
90 protected:
91 template <typename Expression>
92 void construct(Expression& expr) {
93 EIGEN_IF_CONSTEXPR (Expression::IsVectorAtCompileTime) {
94 const Index offset = expr.outerIndexPtr() ? expr.outerIndexPtr()[0] : 0;
95 auto inner_index_ptr = expr.innerIndexPtr();
96 auto value_ptr = expr.valuePtr();
97 if (inner_index_ptr) inner_index_ptr += offset;
98 if (value_ptr) value_ptr += offset;
99 internal::construct_at<Base>(this, expr.size(), expr.nonZeros(), inner_index_ptr, value_ptr);
100 } else if (expr.outerIndexPtr() == 0) {
101 internal::construct_at<Base>(this, expr.size(), expr.nonZeros(), expr.innerIndexPtr(), expr.valuePtr());
102 } else {
103 internal::construct_at<Base>(this, expr.rows(), expr.cols(), expr.nonZeros(), expr.outerIndexPtr(),
104 expr.innerIndexPtr(), expr.valuePtr(), expr.innerNonZeroPtr());
105 }
106 }
107};
108
109} // namespace internal
110
122#ifndef EIGEN_PARSED_BY_DOXYGEN
123template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
124class Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>
125 : public internal::SparseRefBase<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
126#else
127template <typename SparseMatrixType, int Options>
128class Ref<SparseMatrixType, Options>
129 : public SparseMapBase<Derived, WriteAccessors> // Note: 'Derived' is used here intentionally; it resolves
130 // correctly via CRTP.
131#endif
132{
133 using Traits = internal::traits<Ref>;
134 template <int OtherOptions>
136 template <int OtherOptions>
138
139 public:
140 using Base = internal::SparseRefBase<Ref>;
141 EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)
142
143#ifndef EIGEN_PARSED_BY_DOXYGEN
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 <int OtherOptions>
155 EIGEN_STATIC_ASSERT(
156 bool(Traits::template match<SparseMatrix<MatScalar, OtherOptions, MatIndex>>::MatchAtCompileTime),
157 STORAGE_LAYOUT_DOES_NOT_MATCH);
158 eigen_assert(((Options & int(StandardCompressedFormat)) == 0) || (expr.isCompressed()));
159 Base::construct(expr.derived());
160 }
161
162 template <typename Derived>
163 inline Ref(const SparseCompressedBase<Derived>& expr)
164#else
166 template <typename Derived>
168#endif
169 {
170 EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
171 EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
172 eigen_assert(((Options & int(StandardCompressedFormat)) == 0) || (expr.isCompressed()));
173 Base::construct(expr.const_cast_derived());
174 }
175};
176
177// this is the const ref version
178template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
179class Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>
180 : public internal::SparseRefBase<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>> {
181 using TPlainObjectType = SparseMatrix<MatScalar, MatOptions, MatIndex>;
182 using Traits = internal::traits<Ref>;
183
184 public:
185 using Base = internal::SparseRefBase<Ref>;
186 EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)
187
188 template <typename Derived>
189 inline Ref(const SparseMatrixBase<Derived>& expr) : m_hasCopy(false) {
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 internal::destroy_at(reinterpret_cast<TPlainObjectType*>(&m_storage));
205 }
206 }
207
208 protected:
209 template <typename Expression>
210 void construct(const Expression& expr, std::true_type) {
211 EIGEN_IF_CONSTEXPR (Options & int(StandardCompressedFormat)) {
212 if (!expr.isCompressed()) {
213 TPlainObjectType* obj = internal::construct_at(reinterpret_cast<TPlainObjectType*>(&m_storage), expr);
214 m_hasCopy = true;
215 Base::construct(*obj);
216 return;
217 }
218 }
219 Base::construct(expr);
220 }
221
222 template <typename Expression>
223 void construct(const Expression& expr, std::false_type) {
224 TPlainObjectType* obj = internal::construct_at(reinterpret_cast<TPlainObjectType*>(&m_storage), expr);
225 m_hasCopy = true;
226 Base::construct(*obj);
227 }
228
229 typename internal::aligned_storage<sizeof(TPlainObjectType), EIGEN_ALIGNOF(TPlainObjectType)>::type m_storage;
230 bool m_hasCopy;
231};
232
243#ifndef EIGEN_PARSED_BY_DOXYGEN
244template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
245class Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>
246 : public internal::SparseRefBase<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
247#else
248template <typename SparseVectorType>
249class Ref<SparseVectorType> : public SparseMapBase<Derived, WriteAccessors>
250#endif
251{
252 using PlainObjectType = SparseVector<MatScalar, MatOptions, MatIndex>;
253 using Traits = internal::traits<Ref>;
254 template <int OtherOptions>
256
257 public:
258 using Base = internal::SparseRefBase<Ref>;
259 EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)
260
261#ifndef EIGEN_PARSED_BY_DOXYGEN
262 template <int OtherOptions>
264 EIGEN_STATIC_ASSERT(
265 bool(Traits::template match<SparseVector<MatScalar, OtherOptions, MatIndex>>::MatchAtCompileTime),
266 STORAGE_LAYOUT_DOES_NOT_MATCH);
267 Base::construct(expr.derived());
268 }
269
270 template <typename Derived>
271 inline Ref(const SparseCompressedBase<Derived>& expr)
272#else
274 template <typename Derived>
276#endif
277 {
278 EIGEN_STATIC_ASSERT(bool(internal::is_lvalue<Derived>::value), THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
279 EIGEN_STATIC_ASSERT(bool(Traits::template match<Derived>::MatchAtCompileTime), STORAGE_LAYOUT_DOES_NOT_MATCH);
280 EIGEN_STATIC_ASSERT((!std::is_same<Derived, PlainObjectType>::value),
281 THIS_EXPRESSION_IS_NOT_A_LVALUE__IT_IS_READ_ONLY);
282 Base::construct(expr.const_cast_derived());
283 }
284};
285
286// this is the const ref version
287template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
288class Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>
289 : public internal::SparseRefBase<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>> {
290 using TPlainObjectType = SparseVector<MatScalar, MatOptions, MatIndex>;
291 using Traits = internal::traits<Ref>;
292
293 public:
294 using Base = internal::SparseRefBase<Ref>;
295 EIGEN_SPARSE_PUBLIC_INTERFACE(Ref)
296
297 template <typename Derived>
298 inline Ref(const SparseMatrixBase<Derived>& expr) : m_hasCopy(false) {
299 construct(expr.derived(), typename Traits::template match<Derived>::type());
300 }
301
302 inline Ref(const Ref& other) : Base(other), m_hasCopy(false) {
303 // copy constructor shall not copy the m_object, to avoid unnecessary malloc and copy
304 }
305
306 template <typename OtherRef>
307 inline Ref(const RefBase<OtherRef>& other) : m_hasCopy(false) {
308 construct(other.derived(), typename Traits::template match<OtherRef>::type());
309 }
310
311 ~Ref() {
312 if (m_hasCopy) {
313 internal::destroy_at(reinterpret_cast<TPlainObjectType*>(&m_storage));
314 }
315 }
316
317 protected:
318 template <typename Expression>
319 void construct(const Expression& expr, std::true_type) {
320 Base::construct(expr);
321 }
322
323 template <typename Expression>
324 void construct(const Expression& expr, std::false_type) {
325 TPlainObjectType* obj = internal::construct_at(reinterpret_cast<TPlainObjectType*>(&m_storage), expr);
326 m_hasCopy = true;
327 Base::construct(*obj);
328 }
329
330 typename internal::aligned_storage<sizeof(TPlainObjectType), EIGEN_ALIGNOF(TPlainObjectType)>::type m_storage;
331 bool m_hasCopy;
332};
333
334namespace internal {
335
336// FIXME: consider introducing a general evaluator_ref that we can specialize for any sparse object once, and thus
337// remove this copy-pasta thing...
338
339template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
340struct evaluator<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
341 : evaluator<SparseCompressedBase<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> {
342 using Base = evaluator<SparseCompressedBase<Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>>;
343 using XprType = Ref<SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>;
344 evaluator() = default;
345 explicit evaluator(const XprType& mat) : Base(mat) {}
346};
347
348template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
349struct evaluator<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
350 : evaluator<SparseCompressedBase<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> {
351 using Base =
352 evaluator<SparseCompressedBase<Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>>>;
353 using XprType = Ref<const SparseMatrix<MatScalar, MatOptions, MatIndex>, Options, StrideType>;
354 evaluator() = default;
355 explicit evaluator(const XprType& mat) : Base(mat) {}
356};
357
358template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
359struct evaluator<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
360 : evaluator<SparseCompressedBase<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> {
361 using Base = evaluator<SparseCompressedBase<Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>>;
362 using XprType = Ref<SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>;
363 evaluator() = default;
364 explicit evaluator(const XprType& mat) : Base(mat) {}
365};
366
367template <typename MatScalar, int MatOptions, typename MatIndex, int Options, typename StrideType>
368struct evaluator<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>
369 : evaluator<SparseCompressedBase<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>> {
370 using Base =
371 evaluator<SparseCompressedBase<Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>>>;
372 using XprType = Ref<const SparseVector<MatScalar, MatOptions, MatIndex>, Options, StrideType>;
373 evaluator() = default;
374 explicit evaluator(const XprType& mat) : Base(mat) {}
375};
376
377} // namespace internal
378
379} // end namespace Eigen
380
381#endif // EIGEN_SPARSE_REF_H
A matrix or vector expression mapping an existing array of data.
Definition Map.h:97
Ref(SparseCompressedBase< Derived > &expr)
Definition SparseRef.h:167
Ref(SparseCompressedBase< Derived > &expr)
Definition SparseRef.h:275
A matrix or vector expression mapping an existing expression.
Definition Ref.h:262
Common base class for sparse [compressed]-{row|column}-storage format.
Definition SparseCompressedBase.h:44
bool isCompressed() const
Definition SparseCompressedBase.h:115
A versatile sparse matrix representation.
Definition SparseMatrix.h:122
bool isCompressed() const
Definition SparseCompressedBase.h:115
a sparse vector class
Definition SparseVector.h:63
constexpr unsigned int LvalueBit
Definition Constants.h:149
constexpr unsigned int RowMajorBit
Definition Constants.h:71
constexpr unsigned int CompressedAccessBit
Definition Constants.h:196
constexpr Derived & derived()
Definition EigenBase.h:50