Eigen  5.0.1
 
Loading...
Searching...
No Matches
SparseVector.h
1// This file is part of Eigen, a lightweight C++ template library
2// for linear algebra.
3//
4// Copyright (C) 2008-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_SPARSEVECTOR_H
12#define EIGEN_SPARSEVECTOR_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
31
32namespace internal {
33template <typename Scalar_, int Options_, typename StorageIndex_>
34struct traits<SparseVector<Scalar_, Options_, StorageIndex_> > {
35 using Scalar = Scalar_;
36 using StorageIndex = StorageIndex_;
37 using StorageKind = Sparse;
38 using XprKind = MatrixXpr;
39 enum {
40 IsColVector = (Options_ & RowMajorBit) ? 0 : 1,
41
42 RowsAtCompileTime = IsColVector ? Dynamic : 1,
43 ColsAtCompileTime = IsColVector ? 1 : Dynamic,
44 MaxRowsAtCompileTime = RowsAtCompileTime,
45 MaxColsAtCompileTime = ColsAtCompileTime,
46 Flags = Options_ | NestByRefBit | LvalueBit | (IsColVector ? 0 : RowMajorBit) | CompressedAccessBit,
47 SupportedAccessPatterns = InnerRandomAccessPattern
48 };
49};
50
51// Sparse-Vector-Assignment kinds:
52enum { SVA_RuntimeSwitch, SVA_Inner, SVA_Outer };
53
54template <typename Dest, typename Src,
55 int AssignmentKind = !bool(Src::IsVectorAtCompileTime) ? SVA_RuntimeSwitch
56 : Src::InnerSizeAtCompileTime == 1 ? SVA_Outer
57 : SVA_Inner>
58struct sparse_vector_assign_selector;
59
60} // namespace internal
61
62template <typename Scalar_, int Options_, typename StorageIndex_>
63class SparseVector : public SparseCompressedBase<SparseVector<Scalar_, Options_, StorageIndex_> > {
65 using Base::convert_index;
66
67 public:
68 EIGEN_SPARSE_PUBLIC_INTERFACE(SparseVector)
69 EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, +=)
70 EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseVector, -=)
71
72 using Storage = internal::CompressedStorage<Scalar, StorageIndex>;
73 enum { IsColVector = internal::traits<SparseVector>::IsColVector };
74
75 enum { Options = Options_ };
76
77 EIGEN_STRONG_INLINE Index rows() const { return IsColVector ? m_size : 1; }
78 EIGEN_STRONG_INLINE Index cols() const { return IsColVector ? 1 : m_size; }
79 EIGEN_STRONG_INLINE Index innerSize() const { return m_size; }
80 EIGEN_STRONG_INLINE Index outerSize() const { return 1; }
81
82 EIGEN_STRONG_INLINE const Scalar* valuePtr() const { return m_data.valuePtr(); }
83 EIGEN_STRONG_INLINE Scalar* valuePtr() { return m_data.valuePtr(); }
84
85 EIGEN_STRONG_INLINE const StorageIndex* innerIndexPtr() const { return m_data.indexPtr(); }
86 EIGEN_STRONG_INLINE StorageIndex* innerIndexPtr() { return m_data.indexPtr(); }
87
88 inline const StorageIndex* outerIndexPtr() const { return 0; }
89 inline StorageIndex* outerIndexPtr() { return 0; }
90 inline const StorageIndex* innerNonZeroPtr() const { return 0; }
91 inline StorageIndex* innerNonZeroPtr() { return 0; }
92
94 constexpr Storage& data() { return m_data; }
96 constexpr const Storage& data() const { return m_data; }
97
98 inline Scalar coeff(Index row, Index col) const {
99 eigen_assert(IsColVector ? (col == 0 && row >= 0 && row < m_size) : (row == 0 && col >= 0 && col < m_size));
100 return coeff(IsColVector ? row : col);
101 }
102 inline Scalar coeff(Index i) const {
103 eigen_assert(i >= 0 && i < m_size);
104 return m_data.at(StorageIndex(i));
105 }
106
107 inline Scalar& coeffRef(Index row, Index col) {
108 eigen_assert(IsColVector ? (col == 0 && row >= 0 && row < m_size) : (row == 0 && col >= 0 && col < m_size));
109 return coeffRef(IsColVector ? row : col);
110 }
111
118 inline Scalar& coeffRef(Index i) {
119 eigen_assert(i >= 0 && i < m_size);
120
121 return m_data.atWithInsertion(StorageIndex(i));
122 }
123
124 public:
125 using InnerIterator = typename Base::InnerIterator;
126 using ReverseInnerIterator = typename Base::ReverseInnerIterator;
127
128 inline void setZero() { m_data.clear(); }
129
131 inline Index nonZeros() const { return m_data.size(); }
132
133 inline void startVec(Index outer) {
134 EIGEN_UNUSED_VARIABLE(outer);
135 eigen_assert(outer == 0);
136 }
137
138 inline Scalar& insertBackByOuterInner(Index outer, Index inner) {
139 EIGEN_UNUSED_VARIABLE(outer);
140 eigen_assert(outer == 0);
141 return insertBack(inner);
142 }
143 inline Scalar& insertBack(Index i) {
144 m_data.append(Scalar(0), i);
145 return m_data.value(m_data.size() - 1);
146 }
147
148 Scalar& insertBackByOuterInnerUnordered(Index outer, Index inner) {
149 EIGEN_UNUSED_VARIABLE(outer);
150 eigen_assert(outer == 0);
151 return insertBackUnordered(inner);
152 }
153 inline Scalar& insertBackUnordered(Index i) {
154 m_data.append(Scalar(0), i);
155 return m_data.value(m_data.size() - 1);
156 }
157
158 inline Scalar& insert(Index row, Index col) {
159 eigen_assert(IsColVector ? (col == 0 && row >= 0 && row < m_size) : (row == 0 && col >= 0 && col < m_size));
160
161 Index inner = IsColVector ? row : col;
162 Index outer = IsColVector ? col : row;
163 EIGEN_ONLY_USED_FOR_DEBUG(outer);
164 eigen_assert(outer == 0);
165 return insert(inner);
166 }
167 Scalar& insert(Index i) {
168 eigen_assert(i >= 0 && i < m_size);
169
170 Index startId = 0;
171 Index p = Index(m_data.size()) - 1;
172 // TODO: implement smart reallocation.
173 m_data.resize(p + 2, 1);
174
175 while ((p >= startId) && (m_data.index(p) > i)) {
176 m_data.index(p + 1) = m_data.index(p);
177 m_data.value(p + 1) = m_data.value(p);
178 --p;
179 }
180 m_data.index(p + 1) = convert_index(i);
181 m_data.value(p + 1) = Scalar(0);
182 return m_data.value(p + 1);
183 }
184
185 inline void reserve(Index reserveSize) { m_data.reserve(reserveSize); }
186
187 inline void finalize() {}
188
190 Index prune(const Scalar& reference, const RealScalar& epsilon = NumTraits<RealScalar>::dummy_precision()) {
191 return prune([&](const Scalar& val) { return !internal::isMuchSmallerThan(val, reference, epsilon); });
192 }
193
201 template <class F>
202 Index prune(F&& keep_predicate) {
203 Index k = 0;
204 Index n = m_data.size();
205 for (Index i = 0; i < n; ++i) {
206 if (keep_predicate(m_data.value(i))) {
207 m_data.value(k) = std::move(m_data.value(i));
208 m_data.index(k) = m_data.index(i);
209 ++k;
210 }
211 }
212 m_data.resize(k);
213 return k;
214 }
215
224 void resize(Index rows, Index cols) {
225 eigen_assert((IsColVector ? cols : rows) == 1 && "Outer dimension must equal 1");
226 resize(IsColVector ? rows : cols);
227 }
228
230 void resize(NoChange_t, Index cols) { resize(rows(), cols); }
231
233 void resize(Index rows, NoChange_t) { resize(rows, cols()); }
234
239 void resize(Index newSize) {
240 m_size = newSize;
241 m_data.clear();
242 }
243
251 void conservativeResize(Index newSize) {
252 if (newSize < m_size) {
253 Index i = 0;
254 while (i < m_data.size() && m_data.index(i) < newSize) ++i;
255 m_data.resize(i);
256 }
257 m_size = newSize;
258 }
259
260 void resizeNonZeros(Index size) { m_data.resize(size); }
261
262 inline SparseVector() : m_size(0) { resize(0); }
263
264 explicit inline SparseVector(Index size) : m_size(0) { resize(size); }
265
266 inline SparseVector(Index rows, Index cols) : m_size(0) { resize(rows, cols); }
267
268 template <typename OtherDerived>
269 inline SparseVector(const SparseMatrixBase<OtherDerived>& other) : m_size(0) {
270#ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
271 EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
272#endif
273 *this = other.derived();
274 }
275
276 inline SparseVector(const SparseVector& other) : Base(other), m_size(0) { *this = other.derived(); }
277
282 inline void swap(SparseVector& other) {
283 std::swap(m_size, other.m_size);
284 m_data.swap(other.m_data);
285 }
286 friend EIGEN_DEVICE_FUNC void swap(SparseVector& a, SparseVector& b) { a.swap(b); }
287
288 template <int OtherOptions>
289 inline void swap(SparseMatrix<Scalar, OtherOptions, StorageIndex>& other) {
290 eigen_assert(other.outerSize() == 1);
291 std::swap(m_size, other.m_innerSize);
292 m_data.swap(other.m_data);
293 }
294 template <int OtherOptions>
295 friend EIGEN_DEVICE_FUNC void swap(SparseVector& a, SparseMatrix<Scalar, OtherOptions, StorageIndex>& b) {
296 a.swap(b);
297 }
298 template <int OtherOptions>
299 friend EIGEN_DEVICE_FUNC void swap(SparseMatrix<Scalar, OtherOptions, StorageIndex>& a, SparseVector& b) {
300 b.swap(a);
301 }
302
303 inline SparseVector& operator=(const SparseVector& other) {
304 if (other.isRValue()) {
305 swap(other.const_cast_derived());
306 } else {
307 resize(other.size());
308 m_data = other.m_data;
309 }
310 return *this;
311 }
312
313 template <typename OtherDerived>
314 inline SparseVector& operator=(const SparseMatrixBase<OtherDerived>& other) {
315 SparseVector tmp(other.size());
316 internal::sparse_vector_assign_selector<SparseVector, OtherDerived>::run(tmp, other.derived());
317 this->swap(tmp);
318 return *this;
319 }
320
321 inline SparseVector(SparseVector&& other) : SparseVector() { this->swap(other); }
322
323 template <typename OtherDerived>
324 inline SparseVector(SparseCompressedBase<OtherDerived>&& other) : SparseVector() {
325 *this = other.derived().markAsRValue();
326 }
327
328 inline SparseVector& operator=(SparseVector&& other) {
329 this->swap(other);
330 return *this;
331 }
332
333 template <typename OtherDerived>
334 inline SparseVector& operator=(SparseCompressedBase<OtherDerived>&& other) {
335 *this = other.derived().markAsRValue();
336 return *this;
337 }
338
339#ifndef EIGEN_NO_IO
340 friend std::ostream& operator<<(std::ostream& s, const SparseVector& m) {
341 for (Index i = 0; i < m.nonZeros(); ++i) s << "(" << m.m_data.value(i) << "," << m.m_data.index(i) << ") ";
342 s << std::endl;
343 return s;
344 }
345#endif
346
348 Scalar sum() const;
349
350 public:
352 EIGEN_DEPRECATED_WITH_REASON("Use .setZero() and .reserve() instead.") void startFill(Index reserve) {
353 setZero();
354 m_data.reserve(reserve);
355 }
356
358 EIGEN_DEPRECATED_WITH_REASON("Use .insertBack() instead.") Scalar& fill(Index r, Index c) {
359 eigen_assert(r == 0 || c == 0);
360 return fill(IsColVector ? r : c);
361 }
362
364 EIGEN_DEPRECATED_WITH_REASON("Use .insertBack() instead.") Scalar& fill(Index i) {
365 m_data.append(Scalar(0), i);
366 return m_data.value(m_data.size() - 1);
367 }
368
370 EIGEN_DEPRECATED_WITH_REASON("Use .insert() instead.") Scalar& fillrand(Index r, Index c) {
371 eigen_assert(r == 0 || c == 0);
372 return fillrand(IsColVector ? r : c);
373 }
374
376 EIGEN_DEPRECATED_WITH_REASON("Use .insert() instead.") Scalar& fillrand(Index i) { return insert(i); }
377
379 EIGEN_DEPRECATED_WITH_REASON("Use .finalize() instead.") void endFill() {}
380
381 // These two functions were here in the 3.1 release, so let's keep them in case some code relies on them.
383 EIGEN_DEPRECATED_WITH_REASON("Use .data() instead.") Storage& _data() { return m_data; }
385 EIGEN_DEPRECATED_WITH_REASON("Use .data() instead.") const Storage& _data() const { return m_data; }
386
387#ifdef EIGEN_SPARSEVECTOR_PLUGIN
388#include EIGEN_SPARSEVECTOR_PLUGIN
389#endif
390
391 protected:
392 EIGEN_STATIC_ASSERT(NumTraits<StorageIndex>::IsSigned, THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE)
393 EIGEN_STATIC_ASSERT((Options_ & (ColMajor | RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)
394
395 Storage m_data;
396 Index m_size;
397};
398
399namespace internal {
400
401template <typename Scalar_, int Options_, typename Index_>
402struct evaluator<SparseVector<Scalar_, Options_, Index_> > : evaluator_base<SparseVector<Scalar_, Options_, Index_> > {
403 using SparseVectorType = SparseVector<Scalar_, Options_, Index_>;
404 using Base = evaluator_base<SparseVectorType>;
405 using InnerIterator = typename SparseVectorType::InnerIterator;
406 using ReverseInnerIterator = typename SparseVectorType::ReverseInnerIterator;
407
408 enum { CoeffReadCost = NumTraits<Scalar_>::ReadCost, Flags = SparseVectorType::Flags };
409
410 evaluator() : Base() {}
411
412 explicit evaluator(const SparseVectorType& mat) : m_matrix(&mat) { EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); }
413
414 inline Index nonZerosEstimate() const { return m_matrix->nonZeros(); }
415
416 operator SparseVectorType&() { return m_matrix->const_cast_derived(); }
417 operator const SparseVectorType&() const { return *m_matrix; }
418
419 const SparseVectorType* m_matrix;
420};
421
422template <typename Dest, typename Src>
423struct sparse_vector_assign_selector<Dest, Src, SVA_Inner> {
424 static void run(Dest& dst, const Src& src) {
425 eigen_internal_assert(src.innerSize() == src.size());
426 using SrcEvaluatorType = internal::evaluator<Src>;
427 SrcEvaluatorType srcEval(src);
428 for (typename SrcEvaluatorType::InnerIterator it(srcEval, 0); it; ++it) dst.insert(it.index()) = it.value();
429 }
430};
431
432template <typename Dest, typename Src>
433struct sparse_vector_assign_selector<Dest, Src, SVA_Outer> {
434 static void run(Dest& dst, const Src& src) {
435 eigen_internal_assert(src.outerSize() == src.size());
436 using SrcEvaluatorType = internal::evaluator<Src>;
437 SrcEvaluatorType srcEval(src);
438 for (Index i = 0; i < src.size(); ++i) {
439 typename SrcEvaluatorType::InnerIterator it(srcEval, i);
440 if (it) dst.insert(i) = it.value();
441 }
442 }
443};
444
445template <typename Dest, typename Src>
446struct sparse_vector_assign_selector<Dest, Src, SVA_RuntimeSwitch> {
447 static void run(Dest& dst, const Src& src) {
448 if (src.outerSize() == 1)
449 sparse_vector_assign_selector<Dest, Src, SVA_Inner>::run(dst, src);
450 else
451 sparse_vector_assign_selector<Dest, Src, SVA_Outer>::run(dst, src);
452 }
453};
454
455} // namespace internal
456
457// Specialization for SparseVector.
458// Serializes [size, numNonZeros, innerIndices, values].
459template <typename Scalar, int Options, typename StorageIndex>
460class Serializer<SparseVector<Scalar, Options, StorageIndex>, void> {
461 public:
462 using SparseMat = SparseVector<Scalar, Options, StorageIndex>;
463
464 struct Header {
465 typename SparseMat::Index size;
466 Index num_non_zeros;
467 };
468
469 EIGEN_DEVICE_FUNC size_t size(const SparseMat& value) const {
470 return sizeof(Header) + (sizeof(Scalar) + sizeof(StorageIndex)) * value.nonZeros();
471 }
472
473 EIGEN_DEVICE_FUNC uint8_t* serialize(uint8_t* dest, uint8_t* end, const SparseMat& value) {
474 if (EIGEN_PREDICT_FALSE(dest == nullptr)) return nullptr;
475 if (EIGEN_PREDICT_FALSE(dest + size(value) > end)) return nullptr;
476
477 const size_t header_bytes = sizeof(Header);
478 Header header = {value.innerSize(), value.nonZeros()};
479 EIGEN_USING_STD(memcpy)
480 memcpy(dest, &header, header_bytes);
481 dest += header_bytes;
482
483 // Inner indices.
484 std::size_t data_bytes = sizeof(StorageIndex) * header.num_non_zeros;
485 if (data_bytes != 0) {
486 memcpy(dest, value.innerIndexPtr(), data_bytes);
487 }
488 dest += data_bytes;
489
490 // Values.
491 data_bytes = sizeof(Scalar) * header.num_non_zeros;
492 if (data_bytes != 0) {
493 memcpy(dest, value.valuePtr(), data_bytes);
494 }
495 dest += data_bytes;
496
497 return dest;
498 }
499
500 EIGEN_DEVICE_FUNC const uint8_t* deserialize(const uint8_t* src, const uint8_t* end, SparseMat& value) const {
501 if (EIGEN_PREDICT_FALSE(src == nullptr)) return nullptr;
502 if (EIGEN_PREDICT_FALSE(src + sizeof(Header) > end)) return nullptr;
503
504 const size_t header_bytes = sizeof(Header);
505 Header header;
506 EIGEN_USING_STD(memcpy)
507 memcpy(&header, src, header_bytes);
508 src += header_bytes;
509
510 value.setZero();
511 value.resize(header.size);
512 value.resizeNonZeros(header.num_non_zeros);
513
514 // Inner indices.
515 std::size_t data_bytes = sizeof(StorageIndex) * header.num_non_zeros;
516 if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr;
517 if (data_bytes != 0) {
518 memcpy(value.innerIndexPtr(), src, data_bytes);
519 }
520 src += data_bytes;
521
522 // Values.
523 data_bytes = sizeof(Scalar) * header.num_non_zeros;
524 if (EIGEN_PREDICT_FALSE(src + data_bytes > end)) return nullptr;
525 if (data_bytes != 0) {
526 memcpy(value.valuePtr(), src, data_bytes);
527 }
528 src += data_bytes;
529 return src;
530 }
531};
532
533} // end namespace Eigen
534
535#endif // EIGEN_SPARSEVECTOR_H
An InnerIterator allows to loop over the element of any matrix expression.
Definition CoreIterators.h:38
typename NumTraits< Scalar >::Real RealScalar
Definition SparseMatrixBase.h:128
constexpr RowXpr row(Index i)
Definition SparseMatrixBase.h:1094
typename internal::traits< SparseVector< Scalar_, Options_, StorageIndex_ > >::StorageIndex StorageIndex
Definition SparseMatrixBase.h:45
constexpr ColXpr col(Index i)
Definition SparseMatrixBase.h:1081
a sparse vector class
Definition SparseVector.h:63
void resize(NoChange_t, Index cols)
Definition SparseVector.h:230
void resize(Index rows, NoChange_t)
Definition SparseVector.h:233
void conservativeResize(Index newSize)
Definition SparseVector.h:251
Scalar & coeffRef(Index i)
Definition SparseVector.h:118
Index prune(const Scalar &reference, const RealScalar &epsilon=NumTraits< RealScalar >::dummy_precision())
Definition SparseVector.h:190
void resize(Index rows, Index cols)
Definition SparseVector.h:224
void swap(SparseVector &other)
Definition SparseVector.h:282
Index prune(F &&keep_predicate)
Prunes the entries of the vector based on a predicate
Definition SparseVector.h:202
Index nonZeros() const
Definition SparseVector.h:131
void resize(Index newSize)
Definition SparseVector.h:239
Scalar sum() const
Definition SparseRedux.h:41
constexpr unsigned int LvalueBit
Definition Constants.h:149
constexpr unsigned int RowMajorBit
Definition Constants.h:71
constexpr unsigned int CompressedAccessBit
Definition Constants.h:196