11#ifndef EIGEN_SPARSEMATRIX_H
12#define EIGEN_SPARSEMATRIX_H
15#include "./InternalHeaderCheck.h"
51template <
typename Scalar_,
int Options_,
typename StorageIndex_>
52struct traits<SparseMatrix<Scalar_, Options_, StorageIndex_>> {
53 using Scalar = Scalar_;
54 using StorageIndex = StorageIndex_;
55 using StorageKind = Sparse;
56 using XprKind = MatrixXpr;
58 RowsAtCompileTime = Dynamic,
59 ColsAtCompileTime = Dynamic,
60 MaxRowsAtCompileTime = Dynamic,
61 MaxColsAtCompileTime = Dynamic,
64 SupportedAccessPatterns = InnerRandomAccessPattern
68template <
typename Scalar_,
int Options_,
typename StorageIndex_,
int DiagIndex>
69struct traits<Diagonal<SparseMatrix<Scalar_, Options_, StorageIndex_>, DiagIndex>> {
70 using MatrixType = SparseMatrix<Scalar_, Options_, StorageIndex_>;
71 using MatrixTypeNested =
typename ref_selector<MatrixType>::type;
72 using MatrixTypeNested_ = std::remove_reference_t<MatrixTypeNested>;
74 using Scalar = Scalar_;
75 using StorageKind = Dense;
76 using StorageIndex = StorageIndex_;
77 using XprKind = MatrixXpr;
80 RowsAtCompileTime = Dynamic,
81 ColsAtCompileTime = 1,
82 MaxRowsAtCompileTime = Dynamic,
83 MaxColsAtCompileTime = 1,
88template <
typename Scalar_,
int Options_,
typename StorageIndex_,
int DiagIndex>
89struct traits<Diagonal<const SparseMatrix<Scalar_, Options_, StorageIndex_>, DiagIndex>>
90 :
public traits<Diagonal<SparseMatrix<Scalar_, Options_, StorageIndex_>, DiagIndex>> {
94template <
typename StorageIndex>
95struct sparse_reserve_op {
96 EIGEN_DEVICE_FUNC sparse_reserve_op(Index begin, Index end, Index size) {
97 Index range = numext::mini(end - begin, size);
99 m_end = begin + range;
100 m_val = StorageIndex(size / range);
101 m_remainder = StorageIndex(size % range);
103 template <
typename IndexType>
104 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE StorageIndex operator()(IndexType i)
const {
105 if ((i >= m_begin) && (i < m_end))
106 return m_val + ((i - m_begin) < m_remainder ? 1 : 0);
110 StorageIndex m_val, m_remainder;
111 Index m_begin, m_end;
114template <
typename Scalar>
115struct functor_traits<sparse_reserve_op<Scalar>> {
116 enum { Cost = 1, PacketAccess =
false, IsRepeatable =
true };
121template <
typename Scalar_,
int Options_,
typename StorageIndex_>
124 using Base::convert_index;
126 template <
typename,
typename,
typename,
typename,
typename>
127 friend struct internal::Assignment;
133 using Base::operator+=;
134 using Base::operator-=;
139 using InnerIterator =
typename Base::InnerIterator;
140 using ReverseInnerIterator =
typename Base::ReverseInnerIterator;
142 using Base::IsRowMajor;
143 using Storage = internal::CompressedStorage<Scalar, StorageIndex>;
144 enum { Options = Options_ };
146 using IndexVector =
typename Base::IndexVector;
147 using ScalarVector =
typename Base::ScalarVector;
160 inline Index
rows()
const {
return IsRowMajor ? m_outerSize : m_innerSize; }
162 inline Index
cols()
const {
return IsRowMajor ? m_innerSize : m_outerSize; }
172 inline const Scalar*
valuePtr()
const {
return m_data.valuePtr(); }
176 inline Scalar*
valuePtr() {
return m_data.valuePtr(); }
206 constexpr Storage& data() {
return m_data; }
208 constexpr const Storage& data()
const {
return m_data; }
215 const Index outer = IsRowMajor ?
row :
col;
216 const Index inner = IsRowMajor ?
col :
row;
217 Index end = m_innerNonZeros ? m_outerIndex[outer] + m_innerNonZeros[outer] : m_outerIndex[outer + 1];
218 return m_data.atInRange(m_outerIndex[outer], end, inner);
234 const Index outer = IsRowMajor ?
row :
col;
235 const Index inner = IsRowMajor ?
col :
row;
236 Index start = m_outerIndex[outer];
237 Index end =
isCompressed() ? m_outerIndex[outer + 1] : m_outerIndex[outer] + m_innerNonZeros[outer];
238 eigen_assert(end >= start &&
"you probably called coeffRef on a non finalized matrix");
239 Index dst = start == end ? end : m_data.searchLowerIndex(start, end, inner);
241 Index capacity = m_outerIndex[outer + 1] - end;
244 m_innerNonZeros[outer]++;
246 m_data.value(end) = Scalar(0);
247 if (inserted !=
nullptr) {
250 return m_data.value(end);
253 if ((dst < end) && (m_data.index(dst) == inner)) {
255 if (inserted !=
nullptr) {
258 return m_data.value(dst);
260 if (inserted !=
nullptr) {
264 return insertAtByOuterInner(outer, inner, dst);
309 if (m_innerNonZeros) {
318 eigen_assert(
isCompressed() &&
"This function does not make sense in non compressed mode.");
319 m_data.reserve(reserveSize);
322#ifdef EIGEN_PARSED_BY_DOXYGEN
335 template <
class SizesType>
336 inline void reserve(
const SizesType& reserveSizes);
338 template <
class SizesType>
339 inline void reserve(
const SizesType& reserveSizes,
340 const typename SizesType::value_type& enableif =
typename SizesType::value_type()) {
341 EIGEN_UNUSED_VARIABLE(enableif);
342 reserveInnerVectors(reserveSizes);
346 template <
class SizesType>
347 inline void reserveInnerVectors(
const SizesType& reserveSizes) {
349 Index totalReserveSize = 0;
350 for (Index j = 0; j < m_outerSize; ++j) totalReserveSize += internal::convert_index<Index>(reserveSizes[j]);
353 if (totalReserveSize == 0)
return;
356 m_innerNonZeros = internal::conditional_aligned_new_auto<StorageIndex, true>(m_outerSize);
359 StorageIndex* newOuterIndex = m_innerNonZeros;
362 for (Index j = 0; j < m_outerSize; ++j) {
363 newOuterIndex[j] = internal::convert_index<StorageIndex>(count);
364 Index reserveSize = internal::convert_index<Index>(reserveSizes[j]);
365 count += reserveSize + internal::convert_index<Index>(m_outerIndex[j + 1] - m_outerIndex[j]);
368 m_data.reserve(totalReserveSize);
369 StorageIndex previousOuterIndex = m_outerIndex[m_outerSize];
370 for (Index j = m_outerSize - 1; j >= 0; --j) {
371 StorageIndex innerNNZ = previousOuterIndex - m_outerIndex[j];
372 StorageIndex begin = m_outerIndex[j];
373 StorageIndex end = begin + innerNNZ;
374 StorageIndex target = newOuterIndex[j];
377 previousOuterIndex = m_outerIndex[j];
378 m_outerIndex[j] = newOuterIndex[j];
379 m_innerNonZeros[j] = innerNNZ;
382 m_outerIndex[m_outerSize] = m_outerIndex[m_outerSize - 1] + m_innerNonZeros[m_outerSize - 1] +
383 internal::convert_index<StorageIndex>(reserveSizes[m_outerSize - 1]);
385 m_data.resize(m_outerIndex[m_outerSize]);
387 StorageIndex* newOuterIndex = internal::conditional_aligned_new_auto<StorageIndex, true>(m_outerSize + 1);
390 for (
Index j = 0; j < m_outerSize; ++j) {
391 newOuterIndex[j] = internal::convert_index<StorageIndex>(count);
392 Index alreadyReserved =
393 internal::convert_index<Index>(m_outerIndex[j + 1] - m_outerIndex[j] - m_innerNonZeros[j]);
394 Index reserveSize = internal::convert_index<Index>(reserveSizes[j]);
395 Index toReserve = numext::maxi(reserveSize, alreadyReserved);
396 count += toReserve + internal::convert_index<Index>(m_innerNonZeros[j]);
398 newOuterIndex[m_outerSize] = internal::convert_index<StorageIndex>(count);
400 m_data.resize(count);
401 for (
Index j = m_outerSize - 1; j >= 0; --j) {
405 m_data.moveChunk(begin, target, innerNNZ);
408 std::swap(m_outerIndex, newOuterIndex);
409 internal::conditional_aligned_delete_auto<StorageIndex, true>(newOuterIndex, m_outerSize + 1);
427 return insertBackByOuterInner(IsRowMajor ?
row :
col, IsRowMajor ?
col :
row);
432 inline Scalar& insertBackByOuterInner(
Index outer,
Index inner) {
433 eigen_assert(
Index(m_outerIndex[outer + 1]) == m_data.size() &&
"Invalid ordered insertion (invalid outer index)");
434 eigen_assert((m_outerIndex[outer + 1] - m_outerIndex[outer] == 0 || m_data.index(m_data.size() - 1) < inner) &&
435 "Invalid ordered insertion (invalid inner index)");
437 ++m_outerIndex[outer + 1];
438 m_data.append(Scalar(0), inner);
439 return m_data.value(p);
444 inline Scalar& insertBackByOuterInnerUnordered(
Index outer,
Index inner) {
446 ++m_outerIndex[outer + 1];
447 m_data.append(Scalar(0), inner);
448 return m_data.value(p);
453 inline void startVec(
Index outer) {
454 eigen_assert(m_outerIndex[outer] ==
Index(m_data.size()) &&
455 "You must call startVec for each inner vector sequentially");
456 eigen_assert(m_outerIndex[outer + 1] == 0 &&
"You must call startVec for each inner vector sequentially");
457 m_outerIndex[outer + 1] = m_outerIndex[outer];
463 inline void finalize() {
466 Index i = m_outerSize;
468 while (i >= 0 && m_outerIndex[i] == 0) --i;
470 while (i <= m_outerSize) {
471 m_outerIndex[i] =
size;
478 void removeOuterVectors(
Index j,
Index num = 1) {
479 eigen_assert(num >= 0 && j >= 0 && j + num <= m_outerSize &&
"Invalid parameters");
481 const Index newRows = IsRowMajor ? m_outerSize - num :
rows();
482 const Index newCols = IsRowMajor ?
cols() : m_outerSize - num;
484 const Index begin = j + num;
485 const Index end = m_outerSize;
486 const Index target = j;
489 if (m_outerIndex[j + num] > m_outerIndex[j])
uncompress();
492 internal::smart_memmove(m_outerIndex + begin, m_outerIndex + end + 1, m_outerIndex + target);
494 internal::smart_memmove(m_innerNonZeros + begin, m_innerNonZeros + end, m_innerNonZeros + target);
499 const Index from = internal::convert_index<Index>(m_outerIndex[0]);
501 const Index chunkSize = internal::convert_index<Index>(m_innerNonZeros[0]);
502 m_data.moveChunk(from, to, chunkSize);
511 void insertEmptyOuterVectors(
Index j,
Index num = 1) {
513 eigen_assert(num >= 0 && j >= 0 && j < m_outerSize &&
"Invalid parameters");
515 const Index newRows = IsRowMajor ? m_outerSize + num :
rows();
516 const Index newCols = IsRowMajor ?
cols() : m_outerSize + num;
518 const Index begin = j;
519 const Index end = m_outerSize;
520 const Index target = j + num;
526 internal::smart_memmove(m_outerIndex + begin, m_outerIndex + end + 1, m_outerIndex + target);
528 fill_n(m_outerIndex + begin, num, m_outerIndex[begin]);
531 internal::smart_memmove(m_innerNonZeros + begin, m_innerNonZeros + end, m_innerNonZeros + target);
537 template <
typename InputIterators>
540 template <
typename InputIterators,
typename DupFunctor>
541 void setFromTriplets(
const InputIterators& begin,
const InputIterators& end, DupFunctor dup_func);
543 template <
typename Derived,
typename DupFunctor>
546 template <
typename InputIterators>
549 template <
typename InputIterators,
typename DupFunctor>
552 template <
typename InputIterators>
555 template <
typename InputIterators,
typename DupFunctor>
556 void insertFromTriplets(
const InputIterators& begin,
const InputIterators& end, DupFunctor dup_func);
558 template <
typename InputIterators>
561 template <
typename InputIterators,
typename DupFunctor>
568 Scalar& insertByOuterInner(Index j, Index i) {
569 eigen_assert(j >= 0 && j < m_outerSize &&
"invalid outer index");
570 eigen_assert(i >= 0 && i < m_innerSize &&
"invalid inner index");
571 Index start = m_outerIndex[j];
572 Index end =
isCompressed() ? m_outerIndex[j + 1] : start + m_innerNonZeros[j];
573 Index dst = start == end ? end : m_data.searchLowerIndex(start, end, i);
575 Index capacity = m_outerIndex[j + 1] - end;
578 m_innerNonZeros[j]++;
580 m_data.value(end) = Scalar(0);
581 return m_data.value(end);
584 eigen_assert((dst == end || m_data.index(dst) != i) &&
585 "you cannot insert an element that already exists, you must call coeffRef to this end");
586 return insertAtByOuterInner(j, i, dst);
594 eigen_internal_assert(m_outerIndex != 0 && m_outerSize > 0);
597 m_outerIndex[1] = m_innerNonZeros[0];
599 Index copyStart = start;
600 Index copyTarget = m_innerNonZeros[0];
601 for (Index j = 1; j < m_outerSize; j++) {
605 bool breakUpCopy = (end != nextStart) || (j == m_outerSize - 1);
607 Index chunkSize = end - copyStart;
608 if (chunkSize > 0) m_data.moveChunk(copyStart, copyTarget, chunkSize);
609 copyStart = nextStart;
610 copyTarget += chunkSize;
613 m_outerIndex[j + 1] = m_outerIndex[j] + m_innerNonZeros[j];
615 m_data.resize(m_outerIndex[m_outerSize]);
618 internal::conditional_aligned_delete_auto<StorageIndex, true>(m_innerNonZeros, m_outerSize);
626 m_innerNonZeros = internal::conditional_aligned_new_auto<StorageIndex, true>(m_outerSize);
627 if (m_outerIndex[m_outerSize] == 0) {
631 for (Index j = 0; j < m_outerSize; j++) m_innerNonZeros[j] = m_outerIndex[j + 1] - m_outerIndex[j];
636 void prune(
const Scalar& reference,
const RealScalar& epsilon = NumTraits<RealScalar>::dummy_precision()) {
637 prune(default_prunning_func(reference, epsilon));
648 template <
typename KeepFunc>
649 void prune(
const KeepFunc& keep = KeepFunc()) {
651 for (Index j = 0; j < m_outerSize; ++j) {
661 bool keepEntry = keep(
row,
col, m_data.value(i));
663 m_data.value(k) = m_data.value(i);
664 m_data.index(k) = m_data.index(i);
667 m_innerNonZeros[j]--;
671 m_outerIndex[m_outerSize] = k;
688 Index newOuterSize = IsRowMajor ?
rows :
cols;
689 Index newInnerSize = IsRowMajor ?
cols :
rows;
691 Index innerChange = newInnerSize - m_innerSize;
692 Index outerChange = newOuterSize - m_outerSize;
694 if (outerChange != 0) {
695 m_outerIndex = internal::conditional_aligned_realloc_new_auto<StorageIndex, true>(m_outerIndex, newOuterSize + 1,
699 m_innerNonZeros = internal::conditional_aligned_realloc_new_auto<StorageIndex, true>(m_innerNonZeros,
700 newOuterSize, m_outerSize);
702 if (outerChange > 0) {
705 fill_n(m_outerIndex + m_outerSize, outerChange + 1, lastIdx);
710 m_outerSize = newOuterSize;
712 if (innerChange < 0) {
713 for (Index j = 0; j < m_outerSize; j++) {
714 Index start = m_outerIndex[j];
715 Index end =
isCompressed() ? m_outerIndex[j + 1] : start + m_innerNonZeros[j];
716 Index lb = m_data.searchLowerIndex(start, end, newInnerSize);
723 m_innerSize = newInnerSize;
725 Index newSize = m_outerIndex[m_outerSize];
726 eigen_assert(newSize <= m_data.size());
727 m_data.resize(newSize);
745 m_innerSize = IsRowMajor ?
cols :
rows;
748 if ((m_outerIndex == 0) || (m_outerSize !=
outerSize)) {
749 m_outerIndex = internal::conditional_aligned_realloc_new_auto<StorageIndex, true>(m_outerIndex,
outerSize + 1,
754 internal::conditional_aligned_delete_auto<StorageIndex, true>(m_innerNonZeros, m_outerSize);
769 void resizeNonZeros(Index
size) { m_data.resize(
size); }
772 const ConstDiagonalReturnType
diagonal()
const {
return ConstDiagonalReturnType(*
this); }
778 DiagonalReturnType
diagonal() {
return DiagonalReturnType(*
this); }
781 inline SparseMatrix() : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) {
resize(0, 0); }
784 inline SparseMatrix(Index
rows, Index
cols) : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) {
789 template <
typename OtherDerived>
791 : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) {
793 (std::is_same<Scalar, typename OtherDerived::Scalar>::value),
794 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
799#ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
800 EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
802 internal::call_assignment_no_alias(*
this, other.
derived());
807 template <
typename OtherDerived,
unsigned int UpLo>
809 : m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) {
810 Base::operator=(other);
816 template <
typename OtherDerived>
818 *
this = other.
derived().markAsRValue();
823 : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) {
828 template <
typename OtherDerived>
830 : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) {
831 initAssignment(other);
836 template <
typename OtherDerived>
838 : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) {
845 std::swap(m_outerIndex, other.m_outerIndex);
846 std::swap(m_innerSize, other.m_innerSize);
847 std::swap(m_outerSize, other.m_outerSize);
848 std::swap(m_innerNonZeros, other.m_innerNonZeros);
849 m_data.swap(other.m_data);
857 eigen_assert(m_outerSize == m_innerSize &&
"ONLY FOR SQUARED MATRICES");
858 internal::conditional_aligned_delete_auto<StorageIndex, true>(m_innerNonZeros, m_outerSize);
860 m_data.resize(m_outerSize);
863 std::iota(m_outerIndex, m_outerIndex + m_outerSize + 1,
StorageIndex(0));
866 fill_n(
valuePtr(), m_outerSize, Scalar(1));
870 if (other.isRValue()) {
871 swap(other.const_cast_derived());
872 }
else if (
this != &other) {
873#ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
874 EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
876 initAssignment(other);
878 internal::smart_copy(other.m_outerIndex, other.m_outerIndex + m_outerSize + 1, m_outerIndex);
879 m_data = other.m_data;
881 Base::operator=(other);
892 template <
typename OtherDerived>
893 inline SparseMatrix& operator=(
const EigenBase<OtherDerived>& other) {
894 return Base::operator=(other.derived());
897 template <
typename Lhs,
typename Rhs>
898 inline SparseMatrix& operator=(
const Product<Lhs, Rhs, AliasFreeProduct>& other);
900 template <
typename OtherDerived>
901 EIGEN_DONT_INLINE
SparseMatrix& operator=(
const SparseMatrixBase<OtherDerived>& other);
903 template <
typename OtherDerived>
905 *
this = other.
derived().markAsRValue();
910 friend std::ostream& operator<<(std::ostream& s,
const SparseMatrix& m) {
912 s <<
"Nonzero entries:\n";
if (m.isCompressed()) {
913 for (Index i = 0; i < m.nonZeros(); ++i) s <<
"(" << m.m_data.value(i) <<
"," << m.m_data.index(i) <<
") ";
915 for (Index i = 0; i < m.outerSize(); ++i) {
916 Index p = m.m_outerIndex[i];
917 Index pe = m.m_outerIndex[i] + m.m_innerNonZeros[i];
919 for (; k < pe; ++k) {
920 s <<
"(" << m.m_data.value(k) <<
"," << m.m_data.index(k) <<
") ";
922 for (; k < m.m_outerIndex[i + 1]; ++k) {
927 s << std::endl; s <<
"Outer pointers:\n";
928 for (
Index i = 0; i < m.outerSize(); ++i) { s << m.m_outerIndex[i] <<
" "; } s <<
" $" << std::endl;
929 if (!m.isCompressed()) {
930 s <<
"Inner non zeros:\n";
931 for (Index i = 0; i < m.outerSize(); ++i) {
932 s << m.m_innerNonZeros[i] <<
" ";
934 s <<
" $" << std::endl;
937 s << static_cast<const SparseMatrixBase<SparseMatrix>&>(m);
944 internal::conditional_aligned_delete_auto<StorageIndex, true>(m_outerIndex, m_outerSize + 1);
945 internal::conditional_aligned_delete_auto<StorageIndex, true>(m_innerNonZeros, m_outerSize);
951#ifdef EIGEN_SPARSEMATRIX_PLUGIN
952#include EIGEN_SPARSEMATRIX_PLUGIN
956 template <
typename Other>
957 void initAssignment(
const Other& other) {
958 resize(other.rows(), other.cols());
959 internal::conditional_aligned_delete_auto<StorageIndex, true>(m_innerNonZeros, m_outerSize);
965 EIGEN_DEPRECATED EIGEN_DONT_INLINE Scalar& insertCompressed(Index row, Index col);
969 EIGEN_DEPRECATED EIGEN_DONT_INLINE Scalar& insertUncompressed(Index row, Index col);
974 EIGEN_STRONG_INLINE Scalar& insertBackUncompressed(Index row, Index col) {
975 const Index outer = IsRowMajor ? row : col;
976 const Index inner = IsRowMajor ? col : row;
978 eigen_assert(!isCompressed());
979 eigen_assert(m_innerNonZeros[outer] <= (m_outerIndex[outer + 1] - m_outerIndex[outer]));
981 Index p = m_outerIndex[outer] + m_innerNonZeros[outer]++;
982 m_data.index(p) = StorageIndex(inner);
983 m_data.value(p) = Scalar(0);
984 return m_data.value(p);
988 struct IndexPosPair {
989 IndexPosPair(Index a_i, Index a_p) : i(a_i), p(a_p) {}
1003 template <
typename DiagXpr,
typename Func>
1004 void assignDiagonal(
const DiagXpr diagXpr,
const Func& assignFunc) {
1005 constexpr StorageIndex kEmptyIndexVal(-1);
1006 typedef typename ScalarVector::AlignedMapType ValueMap;
1008 Index n = diagXpr.size();
1010 const bool overwrite = std::is_same<Func, internal::assign_op<Scalar, Scalar>>::value;
1012 if ((m_outerSize != n) || (m_innerSize != n) || (n == 0)) resize(n, n);
1015 if (m_data.size() == 0 || overwrite) {
1016 internal::conditional_aligned_delete_auto<StorageIndex, true>(m_innerNonZeros, m_outerSize);
1017 m_innerNonZeros = 0;
1019 ValueMap valueMap(valuePtr(), n);
1020 std::iota(m_outerIndex, m_outerIndex + n + 1, StorageIndex(0));
1021 std::iota(innerIndexPtr(), innerIndexPtr() + n, StorageIndex(0));
1023 internal::call_assignment_no_alias(valueMap, diagXpr, assignFunc);
1025 internal::evaluator<DiagXpr> diaEval(diagXpr);
1027 ei_declare_aligned_stack_constructed_variable(StorageIndex, tmp, n, 0);
1028 typename IndexVector::AlignedMapType insertionLocations(tmp, n);
1029 insertionLocations.setConstant(kEmptyIndexVal);
1031 Index deferredInsertions = 0;
1034 for (Index j = 0; j < n; j++) {
1035 Index begin = m_outerIndex[j];
1036 Index end = isCompressed() ? m_outerIndex[j + 1] : begin + m_innerNonZeros[j];
1037 Index capacity = m_outerIndex[j + 1] - end;
1038 Index dst = m_data.searchLowerIndex(begin, end, j);
1040 if (dst != end && m_data.index(dst) == StorageIndex(j))
1041 assignFunc.assignCoeff(m_data.value(dst), diaEval.coeff(j));
1043 else if (dst == end && capacity > 0)
1044 assignFunc.assignCoeff(insertBackUncompressed(j, j), diaEval.coeff(j));
1047 insertionLocations.coeffRef(j) = StorageIndex(dst);
1048 deferredInsertions++;
1050 if (capacity == 0) shift++;
1054 if (deferredInsertions > 0) {
1055 m_data.resize(m_data.size() + shift);
1056 Index copyEnd = isCompressed() ? m_outerIndex[m_outerSize]
1057 : m_outerIndex[m_outerSize - 1] + m_innerNonZeros[m_outerSize - 1];
1058 for (Index j = m_outerSize - 1; deferredInsertions > 0; j--) {
1059 Index begin = m_outerIndex[j];
1060 Index end = isCompressed() ? m_outerIndex[j + 1] : begin + m_innerNonZeros[j];
1061 Index capacity = m_outerIndex[j + 1] - end;
1063 bool doInsertion = insertionLocations(j) >= 0;
1064 bool breakUpCopy = doInsertion && (capacity > 0);
1070 Index copyBegin = m_outerIndex[j + 1];
1071 Index to = copyBegin + shift;
1072 Index chunkSize = copyEnd - copyBegin;
1073 m_data.moveChunk(copyBegin, to, chunkSize);
1077 m_outerIndex[j + 1] += shift;
1081 if (capacity > 0) shift++;
1082 Index copyBegin = insertionLocations(j);
1083 Index to = copyBegin + shift;
1084 Index chunkSize = copyEnd - copyBegin;
1085 m_data.moveChunk(copyBegin, to, chunkSize);
1087 m_data.index(dst) = StorageIndex(j);
1088 m_data.value(dst) = Scalar(0);
1089 assignFunc.assignCoeff(m_data.value(dst), diaEval.coeff(j));
1090 if (!isCompressed()) m_innerNonZeros[j]++;
1092 deferredInsertions--;
1093 copyEnd = copyBegin;
1097 eigen_assert((shift == 0) && (deferredInsertions == 0));
1103 EIGEN_STRONG_INLINE Scalar& insertAtByOuterInner(Index outer, Index inner, Index dst);
1104 Scalar& insertCompressedAtByOuterInner(Index outer, Index inner, Index dst);
1105 Scalar& insertUncompressedAtByOuterInner(Index outer, Index inner, Index dst);
1108 EIGEN_STATIC_ASSERT(NumTraits<StorageIndex>::IsSigned, THE_INDEX_TYPE_MUST_BE_A_SIGNED_TYPE)
1109 EIGEN_STATIC_ASSERT((Options & (ColMajor | RowMajor)) == Options, INVALID_MATRIX_TEMPLATE_PARAMETERS)
1111 struct default_prunning_func {
1112 default_prunning_func(
const Scalar& ref,
const RealScalar& eps) : reference(ref), epsilon(eps) {}
1113 inline bool operator()(
const Index&,
const Index&,
const Scalar& value)
const {
1114 return !internal::isMuchSmallerThan(value, reference, epsilon);
1125template <
typename InputIterator,
typename SparseMatrixType,
typename DupFunctor>
1126void set_from_triplets(
const InputIterator& begin,
const InputIterator& end, SparseMatrixType& mat,
1127 DupFunctor dup_func) {
1128 constexpr bool IsRowMajor = SparseMatrixType::IsRowMajor;
1129 using StorageIndex =
typename SparseMatrixType::StorageIndex;
1130 using IndexMap =
typename VectorX<StorageIndex>::AlignedMapType;
1131 using TransposedSparseMatrix =
1132 SparseMatrix<typename SparseMatrixType::Scalar, IsRowMajor ? ColMajor : RowMajor, StorageIndex>;
1144 TransposedSparseMatrix trmat(mat.rows(), mat.cols());
1148 for (InputIterator it(begin); it != end; ++it) {
1149 eigen_assert(it->row() >= 0 && it->row() < mat.rows() && it->col() >= 0 && it->col() < mat.cols());
1150 StorageIndex j = convert_index<StorageIndex>(IsRowMajor ? it->col() : it->row());
1151 eigen_assert(nonZeros < NumTraits<StorageIndex>::highest() &&
1152 "non-zero count exceeds StorageIndex range, use a wider StorageIndex (e.g. int64_t)");
1153 if (nonZeros >= NumTraits<StorageIndex>::highest()) internal::throw_std_bad_alloc();
1154 trmat.outerIndexPtr()[j + 1]++;
1158 std::partial_sum(trmat.outerIndexPtr(), trmat.outerIndexPtr() + trmat.outerSize() + 1, trmat.outerIndexPtr());
1159 eigen_assert(nonZeros == trmat.outerIndexPtr()[trmat.outerSize()]);
1160 trmat.resizeNonZeros(nonZeros);
1163 ei_declare_aligned_stack_constructed_variable(StorageIndex, tmp, numext::maxi(mat.innerSize(), mat.outerSize()), 0);
1164 smart_copy(trmat.outerIndexPtr(), trmat.outerIndexPtr() + trmat.outerSize(), tmp);
1167 for (InputIterator it(begin); it != end; ++it) {
1168 StorageIndex j = convert_index<StorageIndex>(IsRowMajor ? it->col() : it->row());
1169 StorageIndex i = convert_index<StorageIndex>(IsRowMajor ? it->row() : it->col());
1170 StorageIndex k = tmp[j];
1171 trmat.data().index(k) = i;
1172 trmat.data().value(k) = it->value();
1176 IndexMap wi(tmp, trmat.innerSize());
1177 trmat.collapseDuplicates(wi, dup_func);
1183template <
typename InputIterator,
typename SparseMatrixType,
typename DupFunctor>
1184void set_from_triplets_sorted(
const InputIterator& begin,
const InputIterator& end, SparseMatrixType& mat,
1185 DupFunctor dup_func) {
1186 constexpr bool IsRowMajor = SparseMatrixType::IsRowMajor;
1187 using StorageIndex =
typename SparseMatrixType::StorageIndex;
1189 if (begin == end)
return;
1191 constexpr StorageIndex kEmptyIndexValue(-1);
1193 mat.resize(mat.rows(), mat.cols());
1195 StorageIndex previous_j = kEmptyIndexValue;
1196 StorageIndex previous_i = kEmptyIndexValue;
1199 for (InputIterator it(begin); it != end; ++it) {
1200 eigen_assert(it->row() >= 0 && it->row() < mat.rows() && it->col() >= 0 && it->col() < mat.cols());
1201 StorageIndex j = convert_index<StorageIndex>(IsRowMajor ? it->row() : it->col());
1202 StorageIndex i = convert_index<StorageIndex>(IsRowMajor ? it->col() : it->row());
1203 eigen_assert(j > previous_j || (j == previous_j && i >= previous_i));
1205 bool duplicate = (previous_j == j) && (previous_i == i);
1207 eigen_assert(nonZeros < NumTraits<StorageIndex>::highest() &&
1208 "non-zero count exceeds StorageIndex range, use a wider StorageIndex (e.g. int64_t)");
1209 if (nonZeros >= NumTraits<StorageIndex>::highest()) internal::throw_std_bad_alloc();
1211 mat.outerIndexPtr()[j + 1]++;
1218 std::partial_sum(mat.outerIndexPtr(), mat.outerIndexPtr() + mat.outerSize() + 1, mat.outerIndexPtr());
1219 eigen_assert(nonZeros == mat.outerIndexPtr()[mat.outerSize()]);
1220 mat.resizeNonZeros(nonZeros);
1222 previous_i = kEmptyIndexValue;
1223 previous_j = kEmptyIndexValue;
1225 for (InputIterator it(begin); it != end; ++it) {
1226 StorageIndex j = convert_index<StorageIndex>(IsRowMajor ? it->row() : it->col());
1227 StorageIndex i = convert_index<StorageIndex>(IsRowMajor ? it->col() : it->row());
1228 bool duplicate = (previous_j == j) && (previous_i == i);
1230 mat.data().value(back - 1) = dup_func(mat.data().value(back - 1), it->value());
1233 mat.data().index(back) = i;
1234 mat.data().value(back) = it->value();
1240 eigen_assert(back == nonZeros);
1246template <
typename DupFunctor,
typename LhsScalar,
typename RhsScalar = LhsScalar>
1247struct scalar_disjunction_op {
1248 using result_type =
typename result_of<DupFunctor(LhsScalar, RhsScalar)>::type;
1249 scalar_disjunction_op(
const DupFunctor& op) : m_functor(op) {}
1250 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator()(
const LhsScalar& a,
const RhsScalar& b)
const {
1251 return m_functor(a, b);
1253 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const DupFunctor& functor()
const {
return m_functor; }
1254 const DupFunctor& m_functor;
1257template <
typename DupFunctor,
typename LhsScalar,
typename RhsScalar>
1258struct functor_traits<scalar_disjunction_op<DupFunctor, LhsScalar, RhsScalar>> :
public functor_traits<DupFunctor> {};
1261template <
typename InputIterator,
typename SparseMatrixType,
typename DupFunctor>
1262void insert_from_triplets(
const InputIterator& begin,
const InputIterator& end, SparseMatrixType& mat,
1263 DupFunctor dup_func) {
1264 using Scalar =
typename SparseMatrixType::Scalar;
1266 CwiseBinaryOp<scalar_disjunction_op<DupFunctor, Scalar>,
const SparseMatrixType,
const SparseMatrixType>;
1269 SparseMatrixType trips(mat.rows(), mat.cols());
1270 set_from_triplets(begin, end, trips, dup_func);
1272 SrcXprType src = mat.binaryExpr(trips, scalar_disjunction_op<DupFunctor, Scalar>(dup_func));
1274 assign_sparse_to_sparse<SparseMatrixType, SrcXprType>(mat, src);
1278template <
typename InputIterator,
typename SparseMatrixType,
typename DupFunctor>
1279void insert_from_triplets_sorted(
const InputIterator& begin,
const InputIterator& end, SparseMatrixType& mat,
1280 DupFunctor dup_func) {
1281 using Scalar =
typename SparseMatrixType::Scalar;
1283 CwiseBinaryOp<scalar_disjunction_op<DupFunctor, Scalar>,
const SparseMatrixType,
const SparseMatrixType>;
1287 SparseMatrixType trips(mat.rows(), mat.cols());
1288 set_from_triplets_sorted(begin, end, trips, dup_func);
1290 SrcXprType src = mat.binaryExpr(trips, scalar_disjunction_op<DupFunctor, Scalar>(dup_func));
1292 assign_sparse_to_sparse<SparseMatrixType, SrcXprType>(mat, src);
1334template <
typename Scalar,
int Options_,
typename StorageIndex_>
1335template <
typename InputIterators>
1337 const InputIterators& end) {
1338 internal::set_from_triplets<InputIterators, SparseMatrix<Scalar, Options_, StorageIndex_>>(
1339 begin, end, *
this, internal::scalar_sum_op<Scalar, Scalar>());
1351template <
typename Scalar,
int Options_,
typename StorageIndex_>
1352template <
typename InputIterators,
typename DupFunctor>
1354 const InputIterators& end, DupFunctor dup_func) {
1355 internal::set_from_triplets<InputIterators, SparseMatrix<Scalar, Options_, StorageIndex_>, DupFunctor>(
1356 begin, end, *
this, dup_func);
1364template <
typename Scalar,
int Options_,
typename StorageIndex_>
1365template <
typename InputIterators>
1367 const InputIterators& end) {
1368 internal::set_from_triplets_sorted<InputIterators, SparseMatrix<Scalar, Options_, StorageIndex_>>(
1369 begin, end, *
this, internal::scalar_sum_op<Scalar, Scalar>());
1381template <
typename Scalar,
int Options_,
typename StorageIndex_>
1382template <
typename InputIterators,
typename DupFunctor>
1384 const InputIterators& end,
1385 DupFunctor dup_func) {
1386 internal::set_from_triplets_sorted<InputIterators, SparseMatrix<Scalar, Options_, StorageIndex_>, DupFunctor>(
1387 begin, end, *
this, dup_func);
1428template <
typename Scalar,
int Options_,
typename StorageIndex_>
1429template <
typename InputIterators>
1431 const InputIterators& end) {
1432 internal::insert_from_triplets<InputIterators, SparseMatrix<Scalar, Options_, StorageIndex_>>(
1433 begin, end, *
this, internal::scalar_sum_op<Scalar, Scalar>());
1445template <
typename Scalar,
int Options_,
typename StorageIndex_>
1446template <
typename InputIterators,
typename DupFunctor>
1448 const InputIterators& end, DupFunctor dup_func) {
1449 internal::insert_from_triplets<InputIterators, SparseMatrix<Scalar, Options_, StorageIndex_>, DupFunctor>(
1450 begin, end, *
this, dup_func);
1457template <
typename Scalar,
int Options_,
typename StorageIndex_>
1458template <
typename InputIterators>
1460 const InputIterators& end) {
1461 internal::insert_from_triplets_sorted<InputIterators, SparseMatrix<Scalar, Options_, StorageIndex_>>(
1462 begin, end, *
this, internal::scalar_sum_op<Scalar, Scalar>());
1474template <
typename Scalar,
int Options_,
typename StorageIndex_>
1475template <
typename InputIterators,
typename DupFunctor>
1477 const InputIterators& end,
1478 DupFunctor dup_func) {
1479 internal::insert_from_triplets_sorted<InputIterators, SparseMatrix<Scalar, Options_, StorageIndex_>, DupFunctor>(
1480 begin, end, *
this, dup_func);
1484template <
typename Scalar_,
int Options_,
typename StorageIndex_>
1485template <
typename Derived,
typename DupFunctor>
1486void SparseMatrix<Scalar_, Options_, StorageIndex_>::collapseDuplicates(
DenseBase<Derived>& wi, DupFunctor dup_func) {
1490 eigen_assert(wi.size() == m_innerSize);
1491 constexpr StorageIndex kEmptyIndexValue(-1);
1493 StorageIndex count = 0;
1494 const bool is_compressed = isCompressed();
1496 for (Index j = 0; j < m_outerSize; ++j) {
1497 const StorageIndex newBegin = count;
1498 const StorageIndex end = is_compressed ? m_outerIndex[j + 1] : m_outerIndex[j] + m_innerNonZeros[j];
1499 for (StorageIndex k = m_outerIndex[j]; k < end; ++k) {
1500 StorageIndex i = m_data.index(k);
1501 if (wi(i) >= newBegin) {
1504 m_data.value(wi(i)) = dup_func(m_data.value(wi(i)), m_data.value(k));
1508 m_data.index(count) = i;
1509 m_data.value(count) = m_data.value(k);
1514 m_outerIndex[j] = newBegin;
1516 m_outerIndex[m_outerSize] = count;
1517 m_data.resize(count);
1520 internal::conditional_aligned_delete_auto<StorageIndex, true>(m_innerNonZeros, m_outerSize);
1521 m_innerNonZeros = 0;
1525template <
typename Scalar,
int Options_,
typename StorageIndex_>
1526template <
typename OtherDerived>
1527EIGEN_DONT_INLINE SparseMatrix<Scalar, Options_, StorageIndex_>&
1528SparseMatrix<Scalar, Options_, StorageIndex_>::operator=(
const SparseMatrixBase<OtherDerived>& other) {
1529 EIGEN_STATIC_ASSERT(
1530 (std::is_same<Scalar, typename OtherDerived::Scalar>::value),
1531 YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
1533#ifdef EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
1534 EIGEN_SPARSE_CREATE_TEMPORARY_PLUGIN
1537 const bool needToTranspose = (Flags &
RowMajorBit) != (internal::evaluator<OtherDerived>::Flags & RowMajorBit);
1538 if (needToTranspose) {
1539#ifdef EIGEN_SPARSE_TRANSPOSED_COPY_PLUGIN
1540 EIGEN_SPARSE_TRANSPOSED_COPY_PLUGIN
1547 typename internal::nested_eval<OtherDerived, 2, typename internal::plain_matrix_type<OtherDerived>::type>::type
1549 typedef internal::remove_all_t<OtherCopy> OtherCopy_;
1550 typedef internal::evaluator<OtherCopy_> OtherCopyEval;
1551 OtherCopy otherCopy(other.derived());
1552 OtherCopyEval otherCopyEval(otherCopy);
1554 SparseMatrix dest(other.rows(), other.cols());
1559 for (Index j = 0; j < otherCopy.outerSize(); ++j)
1560 for (
typename OtherCopyEval::InnerIterator it(otherCopyEval, j); it; ++it) ++dest.m_outerIndex[it.index()];
1563 StorageIndex count = 0;
1564 IndexVector positions(dest.outerSize());
1565 for (Index j = 0; j < dest.outerSize(); ++j) {
1566 StorageIndex tmp = dest.m_outerIndex[j];
1567 dest.m_outerIndex[j] = count;
1568 positions[j] = count;
1571 dest.m_outerIndex[dest.outerSize()] = count;
1573 dest.m_data.resize(count);
1575 for (StorageIndex j = 0; j < otherCopy.outerSize(); ++j) {
1576 for (
typename OtherCopyEval::InnerIterator it(otherCopyEval, j); it; ++it) {
1577 Index pos = internal::convert_index<Index>(positions.coeff(it.index()));
1578 positions.coeffRef(it.index()) = internal::convert_index<StorageIndex>(pos + 1);
1579 dest.m_data.index(pos) = j;
1580 dest.m_data.value(pos) = it.value();
1586 if (other.isRValue()) {
1587 initAssignment(other.derived());
1590 return Base::operator=(other.derived());
1594template <
typename Scalar_,
int Options_,
typename StorageIndex_>
1595inline typename SparseMatrix<Scalar_, Options_, StorageIndex_>::Scalar&
1597 return insertByOuterInner(IsRowMajor ?
row :
col, IsRowMajor ?
col :
row);
1600template <
typename Scalar_,
int Options_,
typename StorageIndex_>
1601EIGEN_STRONG_INLINE
typename SparseMatrix<Scalar_, Options_, StorageIndex_>::Scalar&
1602SparseMatrix<Scalar_, Options_, StorageIndex_>::insertAtByOuterInner(Index outer, Index inner, Index dst) {
1605 return insertUncompressedAtByOuterInner(outer, inner, dst);
1608template <
typename Scalar_,
int Options_,
typename StorageIndex_>
1609EIGEN_DEPRECATED EIGEN_DONT_INLINE
typename SparseMatrix<Scalar_, Options_, StorageIndex_>::Scalar&
1610SparseMatrix<Scalar_, Options_, StorageIndex_>::insertUncompressed(Index row, Index col) {
1611 eigen_assert(!isCompressed());
1612 Index outer = IsRowMajor ? row : col;
1613 Index inner = IsRowMajor ? col : row;
1614 Index start = m_outerIndex[outer];
1615 Index end = start + m_innerNonZeros[outer];
1616 Index dst = start == end ? end : m_data.searchLowerIndex(start, end, inner);
1618 Index capacity = m_outerIndex[outer + 1] - end;
1621 m_innerNonZeros[outer]++;
1622 m_data.index(end) = StorageIndex(inner);
1623 m_data.value(end) = Scalar(0);
1624 return m_data.value(end);
1627 eigen_assert((dst == end || m_data.index(dst) != inner) &&
1628 "you cannot insert an element that already exists, you must call coeffRef to this end");
1629 return insertUncompressedAtByOuterInner(outer, inner, dst);
1632template <
typename Scalar_,
int Options_,
typename StorageIndex_>
1633EIGEN_DEPRECATED EIGEN_DONT_INLINE
typename SparseMatrix<Scalar_, Options_, StorageIndex_>::Scalar&
1634SparseMatrix<Scalar_, Options_, StorageIndex_>::insertCompressed(Index row, Index col) {
1635 eigen_assert(isCompressed());
1636 Index outer = IsRowMajor ? row : col;
1637 Index inner = IsRowMajor ? col : row;
1638 Index start = m_outerIndex[outer];
1639 Index end = m_outerIndex[outer + 1];
1640 Index dst = start == end ? end : m_data.searchLowerIndex(start, end, inner);
1641 eigen_assert((dst == end || m_data.index(dst) != inner) &&
1642 "you cannot insert an element that already exists, you must call coeffRef to this end");
1643 return insertCompressedAtByOuterInner(outer, inner, dst);
1646template <
typename Scalar_,
int Options_,
typename StorageIndex_>
1647typename SparseMatrix<Scalar_, Options_, StorageIndex_>::Scalar&
1648SparseMatrix<Scalar_, Options_, StorageIndex_>::insertCompressedAtByOuterInner(Index outer, Index inner, Index dst) {
1649 eigen_assert(isCompressed());
1652 if (m_data.allocatedSize() <= m_data.size()) {
1655 Index minReserve = 32;
1656 Index reserveSize = numext::maxi(minReserve, m_data.allocatedSize());
1657 m_data.reserve(reserveSize);
1659 m_data.resize(m_data.size() + 1);
1660 Index chunkSize = m_outerIndex[m_outerSize] - dst;
1662 m_data.moveChunk(dst, dst + 1, chunkSize);
1665 for (Index j = outer; j < m_outerSize; j++) m_outerIndex[j + 1]++;
1667 m_data.index(dst) = StorageIndex(inner);
1668 m_data.value(dst) = Scalar(0);
1670 return m_data.value(dst);
1673template <
typename Scalar_,
int Options_,
typename StorageIndex_>
1674typename SparseMatrix<Scalar_, Options_, StorageIndex_>::Scalar&
1675SparseMatrix<Scalar_, Options_, StorageIndex_>::insertUncompressedAtByOuterInner(Index outer, Index inner, Index dst) {
1676 eigen_assert(!isCompressed());
1678 for (Index leftTarget = outer - 1, rightTarget = outer; (leftTarget >= 0) || (rightTarget < m_outerSize);) {
1679 if (rightTarget < m_outerSize) {
1680 Index start = m_outerIndex[rightTarget];
1681 Index end = start + m_innerNonZeros[rightTarget];
1682 Index nextStart = m_outerIndex[rightTarget + 1];
1683 Index capacity = nextStart - end;
1686 Index chunkSize = end - dst;
1687 if (chunkSize > 0) m_data.moveChunk(dst, dst + 1, chunkSize);
1688 m_innerNonZeros[outer]++;
1689 for (Index j = outer; j < rightTarget; j++) m_outerIndex[j + 1]++;
1690 m_data.index(dst) = StorageIndex(inner);
1691 m_data.value(dst) = Scalar(0);
1692 return m_data.value(dst);
1696 if (leftTarget >= 0) {
1697 Index start = m_outerIndex[leftTarget];
1698 Index end = start + m_innerNonZeros[leftTarget];
1699 Index nextStart = m_outerIndex[leftTarget + 1];
1700 Index capacity = nextStart - end;
1704 Index chunkSize = dst - nextStart;
1705 if (chunkSize > 0) m_data.moveChunk(nextStart, nextStart - 1, chunkSize);
1706 m_innerNonZeros[outer]++;
1707 for (Index j = leftTarget; j < outer; j++) m_outerIndex[j + 1]--;
1708 m_data.index(dst - 1) = StorageIndex(inner);
1709 m_data.value(dst - 1) = Scalar(0);
1710 return m_data.value(dst - 1);
1719 Index dst_offset = dst - m_outerIndex[outer];
1721 if (m_data.allocatedSize() == 0) {
1723 m_data.resize(m_outerSize);
1724 std::iota(m_outerIndex, m_outerIndex + m_outerSize + 1, StorageIndex(0));
1727 Index maxReserveSize =
static_cast<Index
>(NumTraits<StorageIndex>::highest()) - m_data.allocatedSize();
1728 eigen_assert(maxReserveSize > 0);
1729 if (m_outerSize <= maxReserveSize) {
1731 reserveInnerVectors(IndexVector::Constant(m_outerSize, 1));
1735 typedef internal::sparse_reserve_op<StorageIndex> ReserveSizesOp;
1736 typedef CwiseNullaryOp<ReserveSizesOp, IndexVector> ReserveSizesXpr;
1737 ReserveSizesXpr reserveSizesXpr(m_outerSize, 1, ReserveSizesOp(outer, m_outerSize, maxReserveSize));
1738 reserveInnerVectors(reserveSizesXpr);
1742 Index start = m_outerIndex[outer];
1743 Index end = start + m_innerNonZeros[outer];
1744 Index new_dst = start + dst_offset;
1745 Index chunkSize = end - new_dst;
1746 if (chunkSize > 0) m_data.moveChunk(new_dst, new_dst + 1, chunkSize);
1747 m_innerNonZeros[outer]++;
1748 m_data.index(new_dst) = StorageIndex(inner);
1749 m_data.value(new_dst) = Scalar(0);
1750 return m_data.value(new_dst);
1755template <
typename Scalar_,
int Options_,
typename StorageIndex_>
1756struct evaluator<SparseMatrix<Scalar_, Options_, StorageIndex_>>
1757 : evaluator<SparseCompressedBase<SparseMatrix<Scalar_, Options_, StorageIndex_>>> {
1758 using Base = evaluator<SparseCompressedBase<SparseMatrix<Scalar_, Options_, StorageIndex_>>>;
1759 using SparseMatrixType = SparseMatrix<Scalar_, Options_, StorageIndex_>;
1760 evaluator() =
default;
1761 explicit evaluator(
const SparseMatrixType& mat) : Base(mat) {}
1769template <
typename Scalar,
int Options,
typename StorageIndex>
1770class Serializer<SparseMatrix<Scalar, Options, StorageIndex>, void> {
1772 using SparseMat = SparseMatrix<Scalar, Options, StorageIndex>;
1775 typename SparseMat::Index rows;
1776 typename SparseMat::Index cols;
1779 Index inner_buffer_size;
1782 EIGEN_DEVICE_FUNC
size_t size(
const SparseMat& value)
const {
1784 std::size_t num_storage_indices = value.isCompressed() ? 0 : value.outerSize();
1786 num_storage_indices += value.outerSize() + 1;
1788 const StorageIndex inner_buffer_size = value.outerIndexPtr()[value.outerSize()];
1789 num_storage_indices += inner_buffer_size;
1791 std::size_t num_values = inner_buffer_size;
1792 return sizeof(Header) +
sizeof(Scalar) * num_values +
sizeof(StorageIndex) * num_storage_indices;
1795 EIGEN_DEVICE_FUNC uint8_t* serialize(uint8_t* dest, uint8_t* end,
const SparseMat& value) {
1796 if (EIGEN_PREDICT_FALSE(dest ==
nullptr))
return nullptr;
1797 if (EIGEN_PREDICT_FALSE(dest + size(value) > end))
return nullptr;
1799 const size_t header_bytes =
sizeof(Header);
1800 Header header = {value.rows(), value.cols(), value.isCompressed(), value.outerSize(),
1801 value.outerIndexPtr()[value.outerSize()]};
1802 EIGEN_USING_STD(memcpy)
1803 memcpy(dest, &header, header_bytes);
1804 dest += header_bytes;
1807 if (!header.compressed) {
1808 std::size_t data_bytes =
sizeof(StorageIndex) * header.outer_size;
1809 memcpy(dest, value.innerNonZeroPtr(), data_bytes);
1814 std::size_t data_bytes =
sizeof(StorageIndex) * (header.outer_size + 1);
1815 memcpy(dest, value.outerIndexPtr(), data_bytes);
1819 data_bytes =
sizeof(StorageIndex) * header.inner_buffer_size;
1820 memcpy(dest, value.innerIndexPtr(), data_bytes);
1824 data_bytes =
sizeof(Scalar) * header.inner_buffer_size;
1825 memcpy(dest, value.valuePtr(), data_bytes);
1831 EIGEN_DEVICE_FUNC
const uint8_t* deserialize(
const uint8_t* src,
const uint8_t* end, SparseMat& value)
const {
1832 if (EIGEN_PREDICT_FALSE(src ==
nullptr))
return nullptr;
1833 if (EIGEN_PREDICT_FALSE(src +
sizeof(Header) > end))
return nullptr;
1835 const size_t header_bytes =
sizeof(Header);
1837 EIGEN_USING_STD(memcpy)
1838 memcpy(&header, src, header_bytes);
1839 src += header_bytes;
1842 value.resize(header.rows, header.cols);
1843 if (header.compressed) {
1844 value.makeCompressed();
1850 value.data().resize(header.inner_buffer_size);
1853 if (!header.compressed) {
1855 std::size_t data_bytes =
sizeof(StorageIndex) * header.outer_size;
1856 if (EIGEN_PREDICT_FALSE(src + data_bytes > end))
return nullptr;
1857 if (data_bytes != 0) {
1858 memcpy(value.innerNonZeroPtr(), src, data_bytes);
1864 std::size_t data_bytes =
sizeof(StorageIndex) * (header.outer_size + 1);
1865 if (EIGEN_PREDICT_FALSE(src + data_bytes > end))
return nullptr;
1866 if (data_bytes != 0) {
1867 memcpy(value.outerIndexPtr(), src, data_bytes);
1872 data_bytes =
sizeof(StorageIndex) * header.inner_buffer_size;
1873 if (EIGEN_PREDICT_FALSE(src + data_bytes > end))
return nullptr;
1874 if (data_bytes != 0) {
1875 memcpy(value.innerIndexPtr(), src, data_bytes);
1880 data_bytes =
sizeof(Scalar) * header.inner_buffer_size;
1881 if (EIGEN_PREDICT_FALSE(src + data_bytes > end))
return nullptr;
1882 if (data_bytes != 0) {
1883 memcpy(value.valuePtr(), src, data_bytes);
Base class for all dense matrices, vectors, and arrays.
Definition DenseBase.h:45
Derived & setConstant(const Scalar &value)
Definition CwiseNullaryOp.h:333
Base class for diagonal matrices and expressions.
Definition DiagonalMatrix.h:34
const Derived & derived() const
Definition DiagonalMatrix.h:60
Expression of a diagonal/subdiagonal/superdiagonal in a matrix.
Definition Diagonal.h:78
A matrix or vector expression mapping an existing array of data.
Definition Map.h:97
Common base class for sparse [compressed]-{row|column}-storage format.
Definition SparseCompressedBase.h:44
Index nonZeros() const
Definition SparseCompressedBase.h:65
SparseCompressedBase()=default
bool isCompressed() const
Definition SparseCompressedBase.h:115
Base class of any sparse matrices or sparse expressions.
Definition SparseMatrixBase.h:31
Index size() const
Definition SparseMatrixBase.h:187
typename NumTraits< Scalar >::Real RealScalar
Definition SparseMatrixBase.h:128
constexpr RowXpr row(Index i)
Definition SparseMatrixBase.h:1094
typename internal::traits< SparseMatrix< Scalar_, Options_, StorageIndex_ > >::StorageIndex StorageIndex
Definition SparseMatrixBase.h:45
constexpr ColXpr col(Index i)
Definition SparseMatrixBase.h:1081
@ Flags
Definition SparseMatrixBase.h:95
A versatile sparse matrix representation.
Definition SparseMatrix.h:122
Scalar coeff(Index row, Index col) const
Definition SparseMatrix.h:212
void resize(Index rows, NoChange_t)
Definition SparseMatrix.h:765
const ConstDiagonalReturnType diagonal() const
Definition SparseMatrix.h:772
void swap(SparseMatrix &other)
Definition SparseMatrix.h:844
void insertFromSortedTriplets(const InputIterators &begin, const InputIterators &end, DupFunctor dup_func)
Definition SparseMatrix.h:1476
const StorageIndex * innerIndexPtr() const
Definition SparseMatrix.h:181
void setZero()
Definition SparseMatrix.h:305
bool isCompressed() const
Definition SparseCompressedBase.h:115
Index cols() const
Definition SparseMatrix.h:162
StorageIndex * innerIndexPtr()
Definition SparseMatrix.h:185
SparseMatrix(const ReturnByValue< OtherDerived > &other)
Copy constructor with in-place evaluation.
Definition SparseMatrix.h:829
void setFromSortedTriplets(const InputIterators &begin, const InputIterators &end)
Definition SparseMatrix.h:1366
void setFromTriplets(const InputIterators &begin, const InputIterators &end, DupFunctor dup_func)
Definition SparseMatrix.h:1353
Index outerSize() const
Definition SparseMatrix.h:167
SparseMatrix()
Definition SparseMatrix.h:781
void uncompress()
Definition SparseMatrix.h:624
void insertFromSortedTriplets(const InputIterators &begin, const InputIterators &end)
Definition SparseMatrix.h:1459
const Scalar * valuePtr() const
Definition SparseMatrix.h:172
void makeCompressed()
Definition SparseMatrix.h:591
void setFromSortedTriplets(const InputIterators &begin, const InputIterators &end, DupFunctor dup_func)
Definition SparseMatrix.h:1383
SparseMatrix(const SparseSelfAdjointView< OtherDerived, UpLo > &other)
Definition SparseMatrix.h:808
void resize(Index rows, Index cols)
Definition SparseMatrix.h:743
void conservativeResize(Index rows, NoChange_t)
Definition SparseMatrix.h:734
Index rows() const
Definition SparseMatrix.h:160
SparseMatrix(const SparseMatrix &other)
Definition SparseMatrix.h:822
StorageIndex * innerNonZeroPtr()
Definition SparseMatrix.h:203
void setFromTriplets(const InputIterators &begin, const InputIterators &end)
Definition SparseMatrix.h:1336
SparseMatrix(const DiagonalBase< OtherDerived > &other)
Copy constructor with in-place evaluation.
Definition SparseMatrix.h:837
void setIdentity()
Definition SparseMatrix.h:856
Index innerSize() const
Definition SparseMatrix.h:165
SparseMatrix(Index rows, Index cols)
Definition SparseMatrix.h:784
StorageIndex * outerIndexPtr()
Definition SparseMatrix.h:194
const StorageIndex * innerNonZeroPtr() const
Definition SparseMatrix.h:199
void conservativeResize(Index rows, Index cols)
Definition SparseMatrix.h:684
void insertFromTriplets(const InputIterators &begin, const InputIterators &end, DupFunctor dup_func)
Definition SparseMatrix.h:1447
void prune(const Scalar &reference, const RealScalar &epsilon=NumTraits< RealScalar >::dummy_precision())
Definition SparseMatrix.h:636
const StorageIndex * outerIndexPtr() const
Definition SparseMatrix.h:190
SparseMatrix(const SparseMatrixBase< OtherDerived > &other)
Definition SparseMatrix.h:790
friend void swap(SparseMatrix &a, SparseMatrix &b)
Definition SparseMatrix.h:852
~SparseMatrix()
Definition SparseMatrix.h:943
Scalar * valuePtr()
Definition SparseMatrix.h:176
void prune(const KeepFunc &keep=KeepFunc())
Definition SparseMatrix.h:649
void conservativeResize(NoChange_t, Index cols)
Definition SparseMatrix.h:731
Scalar sum() const
Definition SparseRedux.h:31
void reserve(Index reserveSize)
Definition SparseMatrix.h:317
Scalar & coeffRef(Index row, Index col)
Definition SparseMatrix.h:276
Scalar & insert(Index row, Index col)
Definition SparseMatrix.h:1596
void reserve(const SizesType &reserveSizes)
DiagonalReturnType diagonal()
Definition SparseMatrix.h:778
void resize(NoChange_t, Index cols)
Definition SparseMatrix.h:762
Scalar & findOrInsertCoeff(Index row, Index col, bool *inserted)
Definition SparseMatrix.h:232
void insertFromTriplets(const InputIterators &begin, const InputIterators &end)
Definition SparseMatrix.h:1430
SparseMatrix(SparseMatrix &&other)
Definition SparseMatrix.h:814
Pseudo expression to manipulate a triangular sparse matrix as a selfadjoint matrix.
Definition SparseSelfAdjointView.h:53
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
constexpr Index size() const noexcept
Definition EigenBase.h:65
Eigen::Index Index
Definition EigenBase.h:44