131 const Index start = coeffsStart();
132 const Scalar* values =
valuePtr() + start;
133 return Array<Scalar, Dynamic, 1>::Map(values,
nonZeros());
148 const Index start = coeffsStart();
149 Scalar* values =
valuePtr() + start;
150 return Array<Scalar, Dynamic, 1>::Map(values,
nonZeros());
155 template <
class Comp = std::less<>>
158 internal::inner_sort_impl<Derived, Comp, IsVectorAtCompileTime>::run(*
this, begin, end);
163 template <
class Comp = std::less<>>
166 return internal::inner_sort_impl<Derived, Comp, IsVectorAtCompileTime>::check(*
this, begin, end);
171 template <
class Comp = std::less<>>
175 internal::inner_sort_impl<Derived, Comp, IsVectorAtCompileTime>::run(*
this, begin, end);
180 template <
class Comp = std::less<>>
184 return internal::inner_sort_impl<Derived, Comp, IsVectorAtCompileTime>::check(*
this, begin, end);
197 const Index outer = Derived::IsRowMajor ?
row :
col;
198 const Index inner = Derived::IsRowMajor ?
col :
row;
203 eigen_assert(end >= start &&
"you are using a non finalized sparse matrix or written coefficient does not exist");
204 internal::LowerBoundIndex p;
207 p.found = (p.value < end) && (this->
innerIndexPtr()[p.value] == inner);
214 template <
typename OtherDerived>
218template <
typename Derived>
219class SparseCompressedBase<Derived>::InnerIterator {
221 InnerIterator() =
default;
223 InnerIterator(
const InnerIterator& other)
224 : m_values(other.m_values),
225 m_indices(other.m_indices),
226 m_outer(other.m_outer),
228 m_end(other.m_end) {}
230 InnerIterator& operator=(
const InnerIterator& other) {
231 m_values = other.m_values;
232 m_indices = other.m_indices;
233 const_cast<OuterType&
>(m_outer).setValue(other.m_outer.value());
241 if (Derived::IsVectorAtCompileTime && mat.outerIndexPtr() == 0) {
243 m_end = mat.nonZeros();
245 m_id = mat.outerIndexPtr()[outer];
246 if (mat.isCompressed())
247 m_end = mat.outerIndexPtr()[outer + 1];
249 m_end = m_id + mat.innerNonZeroPtr()[outer];
254 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
257 explicit InnerIterator(
const internal::CompressedStorage<Scalar, StorageIndex>& data)
258 : m_values(data.
valuePtr()), m_indices(data.indexPtr()), m_outer(0), m_id(0), m_end(data.
size()) {
259 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
262 inline InnerIterator& operator++() {
266 inline InnerIterator& operator+=(
Index i) {
272 InnerIterator result = *
this;
277 inline const Scalar& value()
const {
return m_values[m_id]; }
278 inline Scalar& valueRef() {
return const_cast<Scalar&
>(m_values[m_id]); }
280 inline StorageIndex index()
const {
return m_indices[m_id]; }
281 inline Index outer()
const {
return m_outer.value(); }
282 inline Index row()
const {
return IsRowMajor ? m_outer.value() : index(); }
283 inline Index col()
const {
return IsRowMajor ? index() : m_outer.value(); }
285 inline operator bool()
const {
return m_id < m_end; }
288 inline bool operator==(
const InnerIterator& other)
const {
289 eigen_assert(m_values == other.m_values &&
"comparing iterators from different sources");
290 return m_outer.value() == other.m_outer.value() && m_id == other.m_id;
292 inline bool operator!=(
const InnerIterator& other)
const {
return !(*
this == other); }
295 const Scalar* m_values =
nullptr;
297 using OuterType = internal::variable_if_dynamic<Index, Derived::IsVectorAtCompileTime ? 0 : Dynamic>;
298 const OuterType m_outer{0};
306 template <
typename T>
307 InnerIterator(
const SparseMatrixBase<T>&,
Index outer);
310template <
typename Derived>
315 if (Derived::IsVectorAtCompileTime && mat.outerIndexPtr() == 0) {
317 m_id = mat.nonZeros();
319 m_start = mat.outerIndexPtr()[outer];
320 if (mat.isCompressed())
321 m_id = mat.outerIndexPtr()[outer + 1];
323 m_id = m_start + mat.innerNonZeroPtr()[outer];
328 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
331 explicit ReverseInnerIterator(
const internal::CompressedStorage<Scalar, StorageIndex>& data)
332 : m_values(data.
valuePtr()), m_indices(data.indexPtr()), m_outer(0), m_start(0), m_id(data.
size()) {
333 EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
336 inline ReverseInnerIterator& operator--() {
340 inline ReverseInnerIterator& operator-=(
Index i) {
346 ReverseInnerIterator result = *
this;
351 inline const Scalar& value()
const {
return m_values[m_id - 1]; }
352 inline Scalar& valueRef() {
return const_cast<Scalar&
>(m_values[m_id - 1]); }
354 inline StorageIndex index()
const {
return m_indices[m_id - 1]; }
355 inline Index outer()
const {
return m_outer.value(); }
356 inline Index row()
const {
return IsRowMajor ? m_outer.value() : index(); }
357 inline Index col()
const {
return IsRowMajor ? index() : m_outer.value(); }
359 inline operator bool()
const {
return m_id > m_start; }
361 inline bool operator==(
const ReverseInnerIterator& other)
const {
362 eigen_assert(m_values == other.m_values &&
"comparing iterators from different sources");
363 return m_outer.value() == other.m_outer.value() && m_id == other.m_id;
365 inline bool operator!=(
const ReverseInnerIterator& other)
const {
return !(*
this == other); }
368 const Scalar* m_values;
370 using OuterType = internal::variable_if_dynamic<Index, Derived::IsVectorAtCompileTime ? 0 : Dynamic>;
371 const OuterType m_outer;
380template <
typename Scalar,
typename StorageIndex>
382template <
typename Scalar,
typename StorageIndex>
384template <
typename Scalar,
typename StorageIndex>
385class CompressedStorageIterator;
388template <
typename Scalar,
typename StorageIndex>
391 StorageVal(
const StorageIndex& innerIndex,
const Scalar& value) : m_innerIndex(innerIndex), m_value(value) {}
392 StorageVal(
const StorageVal& other) =
default;
393 StorageVal(StorageVal&& other) =
default;
395 inline const StorageIndex& key()
const {
return m_innerIndex; }
396 inline StorageIndex& key() {
return m_innerIndex; }
397 inline const Scalar& value()
const {
return m_value; }
398 inline Scalar& value() {
return m_value; }
401 inline operator StorageIndex()
const {
return m_innerIndex; }
404 StorageIndex m_innerIndex;
408 StorageVal() =
delete;
412template <
typename Scalar,
typename StorageIndex>
415 using value_type = StorageVal<Scalar, StorageIndex>;
418 StorageRef(StorageRef&& other) =
default;
420 inline StorageRef& operator=(
const StorageRef& other) {
422 value() = other.value();
425 inline StorageRef& operator=(
const value_type& other) {
427 value() = other.value();
430 inline operator value_type()
const {
return value_type(key(), value()); }
431 inline friend void swap(
const StorageRef& a,
const StorageRef& b) {
432 std::iter_swap(a.keyPtr(), b.keyPtr());
433 std::iter_swap(a.valuePtr(), b.valuePtr());
436 inline const StorageIndex& key()
const {
return *m_innerIndexIterator; }
437 inline StorageIndex& key() {
return *m_innerIndexIterator; }
438 inline const Scalar& value()
const {
return *m_valueIterator; }
439 inline Scalar& value() {
return *m_valueIterator; }
440 inline StorageIndex* keyPtr()
const {
return m_innerIndexIterator; }
441 inline Scalar* valuePtr()
const {
return m_valueIterator; }
444 inline operator StorageIndex()
const {
return *m_innerIndexIterator; }
447 StorageIndex* m_innerIndexIterator;
448 Scalar* m_valueIterator;
451 StorageRef() =
delete;
453 StorageRef(StorageIndex* innerIndexIterator, Scalar* valueIterator)
454 : m_innerIndexIterator(innerIndexIterator), m_valueIterator(valueIterator) {}
455 StorageRef(
const StorageRef& other) =
default;
457 friend class CompressedStorageIterator<Scalar, StorageIndex>;
461template <
typename Scalar,
typename StorageIndex>
462class CompressedStorageIterator {
464 using iterator_category = std::random_access_iterator_tag;
465 using reference = StorageRef<Scalar, StorageIndex>;
466 using difference_type = Index;
467 using value_type =
typename reference::value_type;
468 using pointer = value_type*;
470 CompressedStorageIterator() =
delete;
471 CompressedStorageIterator(difference_type index, StorageIndex* innerIndexPtr, Scalar* valuePtr)
472 : m_index(index), m_data(innerIndexPtr, valuePtr) {}
473 CompressedStorageIterator(difference_type index, reference data) : m_index(index), m_data(data) {}
474 CompressedStorageIterator(
const CompressedStorageIterator& other) =
default;
475 CompressedStorageIterator(CompressedStorageIterator&& other) =
default;
476 inline CompressedStorageIterator& operator=(
const CompressedStorageIterator& other) {
477 m_index = other.m_index;
478 m_data = other.m_data;
482 inline CompressedStorageIterator operator+(difference_type offset)
const {
483 return CompressedStorageIterator(m_index + offset, m_data);
485 inline CompressedStorageIterator operator-(difference_type offset)
const {
486 return CompressedStorageIterator(m_index - offset, m_data);
488 inline difference_type operator-(
const CompressedStorageIterator& other)
const {
return m_index - other.m_index; }
489 inline CompressedStorageIterator& operator++() {
493 inline CompressedStorageIterator& operator--() {
497 inline CompressedStorageIterator& operator+=(difference_type offset) {
501 inline CompressedStorageIterator& operator-=(difference_type offset) {
505 inline reference operator*()
const {
return reference(m_data.keyPtr() + m_index, m_data.valuePtr() + m_index); }
506 inline reference operator[](
int index) {
return *(*
this + index); }
508#define MAKE_COMP(OP) \
509 inline bool operator OP(const CompressedStorageIterator& other) const { return m_index OP other.m_index; }
519 difference_type m_index;
523template <
typename Derived,
class Comp,
bool IsVector>
524struct inner_sort_impl {
525 using Scalar =
typename Derived::Scalar;
526 using StorageIndex =
typename Derived::StorageIndex;
527 static inline void run(SparseCompressedBase<Derived>& obj, Index begin, Index end) {
528 const bool is_compressed = obj.isCompressed();
529 for (Index outer = begin; outer < end; outer++) {
530 Index begin_offset = obj.outerIndexPtr()[outer];
531 Index end_offset = is_compressed ? obj.outerIndexPtr()[outer + 1] : (begin_offset + obj.innerNonZeroPtr()[outer]);
532 CompressedStorageIterator<Scalar, StorageIndex> begin_it(begin_offset, obj.innerIndexPtr(), obj.valuePtr());
533 CompressedStorageIterator<Scalar, StorageIndex> end_it(end_offset, obj.innerIndexPtr(), obj.valuePtr());
534 std::sort(begin_it, end_it, Comp());
537 static inline Index check(
const SparseCompressedBase<Derived>& obj, Index begin, Index end) {
538 const bool is_compressed = obj.isCompressed();
539 for (Index outer = begin; outer < end; outer++) {
540 Index begin_offset = obj.outerIndexPtr()[outer];
541 Index end_offset = is_compressed ? obj.outerIndexPtr()[outer + 1] : (begin_offset + obj.innerNonZeroPtr()[outer]);
542 const StorageIndex* begin_it = obj.innerIndexPtr() + begin_offset;
543 const StorageIndex* end_it = obj.innerIndexPtr() + end_offset;
544 bool is_sorted = std::is_sorted(begin_it, end_it, Comp());
545 if (!is_sorted)
return outer;
550template <
typename Derived,
class Comp>
551struct inner_sort_impl<Derived, Comp, true> {
552 using Scalar =
typename Derived::Scalar;
553 using StorageIndex =
typename Derived::StorageIndex;
554 static inline void run(SparseCompressedBase<Derived>& obj, Index, Index) {
555 const StorageIndex* outer = obj.outerIndexPtr();
556 Index begin_offset = (outer && obj.outerSize() > 0) ? internal::convert_index<Index>(outer[0]) : 0;
557 Index end_offset = begin_offset + obj.nonZeros();
558 CompressedStorageIterator<Scalar, StorageIndex> begin_it(begin_offset, obj.innerIndexPtr(), obj.valuePtr());
559 CompressedStorageIterator<Scalar, StorageIndex> end_it(end_offset, obj.innerIndexPtr(), obj.valuePtr());
560 std::sort(begin_it, end_it, Comp());
562 static inline Index check(
const SparseCompressedBase<Derived>& obj, Index, Index) {
563 const StorageIndex* outer = obj.outerIndexPtr();
564 Index begin_offset = (outer && obj.outerSize() > 0) ? internal::convert_index<Index>(outer[0]) : 0;
565 Index end_offset = begin_offset + obj.nonZeros();
566 const StorageIndex* begin_it = obj.innerIndexPtr() + begin_offset;
567 const StorageIndex* end_it = obj.innerIndexPtr() + end_offset;
568 return std::is_sorted(begin_it, end_it, Comp()) ? 1 : 0;
572template <
typename Derived>
573struct evaluator<SparseCompressedBase<Derived>> : evaluator_base<Derived> {
574 using Scalar =
typename Derived::Scalar;
575 using InnerIterator =
typename Derived::InnerIterator;
577 enum { CoeffReadCost = NumTraits<Scalar>::ReadCost, Flags = Derived::Flags };
579 evaluator() : m_matrix(0) { EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); }
580 explicit evaluator(
const Derived& mat) : m_matrix(&mat) { EIGEN_INTERNAL_CHECK_COST_VALUE(CoeffReadCost); }
582 inline Index nonZerosEstimate()
const {
return m_matrix->nonZeros(); }
584 operator Derived&() {
return m_matrix->const_cast_derived(); }
585 operator const Derived&()
const {
return *m_matrix; }
587 using CoeffReturnType =
typename DenseCoeffsBase<Derived, ReadOnlyAccessors>::CoeffReturnType;
588 const Scalar& coeff(Index row, Index col)
const {
589 Index p = find(row, col);
594 return m_matrix->const_cast_derived().valuePtr()[p];
597 Scalar& coeffRef(Index row, Index col) {
598 Index p = find(row, col);
599 eigen_assert(p != Dynamic &&
"written coefficient does not exist");
600 return m_matrix->const_cast_derived().valuePtr()[p];
604 Index find(Index row, Index col)
const {
605 internal::LowerBoundIndex p = m_matrix->lower_bound(row, col);
606 return p.found ? p.value : Dynamic;
613 static const Scalar& zero() {
614 static const Scalar kZero(0);
618 const Derived* m_matrix;