18#ifndef PM_HEAP_COLUMN_H
19#define PM_HEAP_COLUMN_H
28#include <boost/iterator/indirect_iterator.hpp>
30#include <gudhi/Debug_utils.h>
50template <
class Master_matrix>
51class Heap_column :
public Master_matrix::Column_dimension_option,
public Master_matrix::Chain_column_option
54 using Master = Master_matrix;
55 using Index =
typename Master_matrix::Index;
56 using ID_index =
typename Master_matrix::ID_index;
57 using Dimension =
typename Master_matrix::Dimension;
58 using Field_element =
typename Master_matrix::Element;
59 using Entry =
typename Master_matrix::Matrix_entry;
60 using Column_settings =
typename Master_matrix::Column_settings;
63 using Field_operators =
typename Master_matrix::Field_operators;
64 using Column_support = std::vector<Entry*>;
65 using Entry_constructor =
typename Master_matrix::Entry_constructor;
68 using iterator = boost::indirect_iterator<typename Column_support::iterator>;
69 using const_iterator = boost::indirect_iterator<typename Column_support::const_iterator>;
70 using reverse_iterator = boost::indirect_iterator<typename Column_support::reverse_iterator>;
71 using const_reverse_iterator = boost::indirect_iterator<typename Column_support::const_reverse_iterator>;
72 using Content_range = std::vector<Entry>;
74 Heap_column(Column_settings* colSettings =
nullptr);
75 template <
class Container =
typename Master_matrix::Boundary>
76 Heap_column(
const Container& nonZeroRowIndices, Column_settings* colSettings);
77 template <
class Container =
typename Master_matrix::Boundary,
78 class = std::enable_if_t<!std::is_arithmetic_v<Container> > >
79 Heap_column(
const Container& nonZeroRowIndices, Dimension dimension, Column_settings* colSettings);
80 Heap_column(ID_index idx, Dimension dimension, Column_settings* colSettings);
81 Heap_column(ID_index idx, Field_element e, Dimension dimension, Column_settings* colSettings);
82 Heap_column(
const Heap_column& column, Column_settings* colSettings =
nullptr);
83 Heap_column(Heap_column&& column)
noexcept;
88 template <
class Container =
typename Master_matrix::Boundary,
class Row_container>
89 Heap_column([[maybe_unused]] Index columnIndex,
90 const Container& nonZeroRowIndices,
91 [[maybe_unused]] Row_container* rowContainer,
92 Column_settings* colSettings);
93 template <
class Container =
typename Master_matrix::Boundary,
95 class = std::enable_if_t<!std::is_arithmetic_v<Container> > >
96 Heap_column([[maybe_unused]] Index columnIndex,
97 const Container& nonZeroRowIndices,
99 [[maybe_unused]] Row_container* rowContainer,
100 Column_settings* colSettings);
101 template <
class Row_container>
102 Heap_column([[maybe_unused]] Index columnIndex,
105 [[maybe_unused]] Row_container* rowContainer,
106 Column_settings* colSettings);
107 template <
class Row_container>
108 Heap_column([[maybe_unused]] Index columnIndex,
112 [[maybe_unused]] Row_container* rowContainer,
113 Column_settings* colSettings);
114 template <
class Row_container>
115 Heap_column(
const Heap_column& column,
116 [[maybe_unused]] Index columnIndex,
117 [[maybe_unused]] Row_container* rowContainer,
118 Column_settings* colSettings =
nullptr);
120 std::vector<Field_element> get_content(
int columnLength = -1)
const;
121 bool is_non_zero(ID_index rowIndex)
const;
123 [[nodiscard]] std::size_t size()
const;
125 template <
class Row_index_map>
126 void reorder(
const Row_index_map& valueMap,
127 [[maybe_unused]] Index columnIndex = Master_matrix::template get_null_value<Index>());
129 void clear(ID_index rowIndex);
131 ID_index get_pivot();
132 Field_element get_pivot_value();
134 iterator begin()
noexcept;
135 const_iterator begin()
const noexcept;
136 iterator end()
noexcept;
137 const_iterator end()
const noexcept;
138 reverse_iterator rbegin()
noexcept;
139 const_reverse_iterator rbegin()
const noexcept;
140 reverse_iterator rend()
noexcept;
141 const_reverse_iterator rend()
const noexcept;
143 Content_range get_non_zero_content_range();
145 template <
class Entry_range>
146 Heap_column& operator+=(
const Entry_range& column);
147 Heap_column& operator+=(Heap_column& column);
149 Heap_column& operator*=(
const Field_element& v);
152 template <
class Entry_range>
153 Heap_column& multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
154 Heap_column& multiply_target_and_add(
const Field_element& val, Heap_column& column);
156 template <
class Entry_range>
157 Heap_column& multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
158 Heap_column& multiply_source_and_add(Heap_column& column,
const Field_element& val);
160 void push_back(
const Entry& entry);
162 std::size_t compute_hash_value();
164 friend bool operator==(
const Heap_column& c1,
const Heap_column& c2)
166 if (&c1 == &c2)
return true;
168 Heap_column cc1(c1), cc2(c2);
169 Entry* p1 = cc1._pop_pivot();
170 Entry* p2 = cc2._pop_pivot();
171 while (p1 !=
nullptr && p2 !=
nullptr) {
172 Index r1 = Master_matrix::get_row_index(*p1);
173 Index r2 = Master_matrix::get_row_index(*p2);
174 Field_element e1 = Master_matrix::get_element(*p1);
175 Field_element e2 = Master_matrix::get_element(*p2);
176 c1.entryPool_->destroy(p1);
177 c2.entryPool_->destroy(p2);
179 if (r1 != r2 || e1 != e2) {
183 p1 = cc1._pop_pivot();
184 p2 = cc2._pop_pivot();
188 c1.entryPool_->destroy(p1);
192 c1.entryPool_->destroy(p2);
199 friend bool operator<(
const Heap_column& c1,
const Heap_column& c2)
201 if (&c1 == &c2)
return false;
204 Heap_column cc1(c1), cc2(c2);
205 Entry* p1 = cc1._pop_pivot();
206 Entry* p2 = cc2._pop_pivot();
207 while (p1 !=
nullptr && p2 !=
nullptr) {
208 Index r1 = Master_matrix::get_row_index(*p1);
209 Index r2 = Master_matrix::get_row_index(*p2);
210 Field_element e1 = Master_matrix::get_element(*p1);
211 Field_element e2 = Master_matrix::get_element(*p2);
212 c1.entryPool_->destroy(p1);
213 c2.entryPool_->destroy(p2);
215 if (r1 != r2)
return r1 < r2;
216 if (e1 != e2)
return e1 < e2;
218 p1 = cc1._pop_pivot();
219 p2 = cc2._pop_pivot();
223 c1.entryPool_->destroy(p1);
226 c2.entryPool_->destroy(p2);
231 Heap_column& operator=(
const Heap_column& other);
232 Heap_column& operator=(Heap_column&& other)
noexcept;
234 friend void swap(Heap_column& col1, Heap_column& col2)
noexcept
236 swap(
static_cast<typename Master_matrix::Column_dimension_option&
>(col1),
237 static_cast<typename Master_matrix::Column_dimension_option&
>(col2));
238 swap(
static_cast<typename Master_matrix::Chain_column_option&
>(col1),
239 static_cast<typename Master_matrix::Chain_column_option&
>(col2));
240 col1.column_.swap(col2.column_);
241 std::swap(col1.insertsSinceLastPrune_, col2.insertsSinceLastPrune_);
242 std::swap(col1.operators_, col2.operators_);
243 std::swap(col1.entryPool_, col2.entryPool_);
247 using Dim_opt =
typename Master_matrix::Column_dimension_option;
248 using Chain_opt =
typename Master_matrix::Chain_column_option;
250 struct EntryPointerComp {
251 bool operator()(
const Entry* c1,
const Entry* c2)
const {
return *c1 < *c2; }
254 Column_support column_;
255 unsigned int insertsSinceLastPrune_;
256 Field_operators
const* operators_;
257 Entry_constructor* entryPool_;
261 template <
class Entry_range>
262 void _add(
const Entry_range& column, Field_element& pivotVal);
263 template<
bool computePivotVal>
264 std::conditional_t<computePivotVal, Field_element, void> _multiply(
const Field_element& val);
265 template <
class Entry_range>
266 bool _multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
267 template <
class Entry_range>
268 bool _multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
269 void _add_coefficient(Field_element& e,
const Field_element& a)
const;
270 Field_element _multiply_coefficient(
const Field_element& e,
const Field_element& a)
const;
273template <
class Master_matrix>
274inline Heap_column<Master_matrix>::Heap_column(Column_settings* colSettings)
277 insertsSinceLastPrune_(0),
278 operators_(Master_matrix::get_operator_ptr(colSettings)),
279 entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor))
282template <
class Master_matrix>
283template <
class Container>
284inline Heap_column<Master_matrix>::Heap_column(
const Container& nonZeroRowIndices, Column_settings* colSettings)
285 : Heap_column(nonZeroRowIndices, nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1, colSettings)
287 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
288 "Constructor not available for chain columns, please specify the dimension of the chain.");
291template <
class Master_matrix>
292template <
class Container,
class>
293inline Heap_column<Master_matrix>::Heap_column(
const Container& nonZeroRowIndices,
295 Column_settings* colSettings)
296 : Dim_opt(dimension),
297 Chain_opt(nonZeroRowIndices.begin() == nonZeroRowIndices.end()
298 ? Master_matrix::template get_null_value<ID_index>()
299 : Master_matrix::get_row_index(*
std::prev(nonZeroRowIndices.end()))),
300 column_(nonZeroRowIndices.size(), nullptr),
301 insertsSinceLastPrune_(0),
302 operators_(Master_matrix::get_operator_ptr(colSettings)),
303 entryPool_(&(colSettings->entryConstructor))
307 for (
const auto&
id : nonZeroRowIndices) {
308 column_[i] = entryPool_->construct(Master_matrix::get_row_index(
id));
309 column_[i]->set_element(Master_matrix::get_coefficient_value(Master_matrix::get_element(
id), operators_));
313 std::make_heap(column_.begin(), column_.end(), entryPointerComp_);
316template <
class Master_matrix>
317inline Heap_column<Master_matrix>::Heap_column(ID_index idx, Dimension dimension, Column_settings* colSettings)
318 : Dim_opt(dimension),
321 insertsSinceLastPrune_(0),
323 entryPool_(&(colSettings->entryConstructor))
325 static_assert(Master_matrix::Option_list::is_z2,
326 "Constructor not available for Zp != Z2. Please specify the coefficient.");
327 column_[0] = entryPool_->construct(idx);
330template <
class Master_matrix>
331inline Heap_column<Master_matrix>::Heap_column(ID_index idx,
334 Column_settings* colSettings)
335 : Dim_opt(dimension),
338 insertsSinceLastPrune_(0),
339 operators_(&(colSettings->operators)),
340 entryPool_(&(colSettings->entryConstructor))
342 static_assert(!Master_matrix::Option_list::is_z2,
343 "Constructor not available for Zp == Z2. Please do not specify any coefficient.");
344 column_[0] = entryPool_->construct(idx);
345 column_[0]->set_element(operators_->get_value(e));
348template <
class Master_matrix>
349inline Heap_column<Master_matrix>::Heap_column(
const Heap_column& column, Column_settings* colSettings)
350 : Dim_opt(static_cast<const Dim_opt&>(column)),
351 Chain_opt(static_cast<const Chain_opt&>(column)),
352 column_(column.column_.size(), nullptr),
353 insertsSinceLastPrune_(0),
354 operators_(colSettings == nullptr ? column.operators_ : Master_matrix::get_operator_ptr(colSettings)),
355 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
357 static_assert(!Master_matrix::Option_list::has_row_access,
358 "Simple copy constructor not available when row access option enabled. Please specify the new column "
359 "index and the row container.");
362 for (
const Entry* entry : column.column_) {
363 column_[i] = entryPool_->construct(entry->get_row_index());
364 column_[i]->set_element(entry->get_element());
370template <
class Master_matrix>
371inline Heap_column<Master_matrix>::Heap_column(
Heap_column&& column) noexcept
372 : Dim_opt(std::move(
static_cast<Dim_opt&
>(column))),
373 Chain_opt(std::move(
static_cast<Chain_opt&
>(column))),
374 column_(std::move(column.column_)),
375 insertsSinceLastPrune_(std::exchange(column.insertsSinceLastPrune_, 0)),
376 operators_(std::exchange(column.operators_,
nullptr)),
377 entryPool_(std::exchange(column.entryPool_,
nullptr))
380template <
class Master_matrix>
381template <
class Container,
class Row_container>
382inline Heap_column<Master_matrix>::Heap_column([[maybe_unused]] Index columnIndex,
383 const Container& nonZeroRowIndices,
384 [[maybe_unused]] Row_container* rowContainer,
385 Column_settings* colSettings)
388 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
389 "Constructor not available for chain columns, please specify the dimension of the chain.");
392template <
class Master_matrix>
393template <
class Container,
class Row_container,
class>
394inline Heap_column<Master_matrix>::Heap_column([[maybe_unused]] Index columnIndex,
395 const Container& nonZeroRowIndices,
397 [[maybe_unused]] Row_container* rowContainer,
398 Column_settings* colSettings)
399 :
Heap_column(nonZeroRowIndices, dimension, colSettings)
402template <
class Master_matrix>
403template <
class Row_container>
404inline Heap_column<Master_matrix>::Heap_column(
const Heap_column& column,
405 [[maybe_unused]] Index columnIndex,
406 [[maybe_unused]] Row_container* rowContainer,
407 Column_settings* colSettings)
411template <
class Master_matrix>
412template <
class Row_container>
413inline Heap_column<Master_matrix>::Heap_column([[maybe_unused]] Index columnIndex,
416 [[maybe_unused]] Row_container* rowContainer,
417 Column_settings* colSettings)
421template <
class Master_matrix>
422template <
class Row_container>
423inline Heap_column<Master_matrix>::Heap_column([[maybe_unused]] Index columnIndex,
427 [[maybe_unused]] Row_container* rowContainer,
428 Column_settings* colSettings)
432template <
class Master_matrix>
433inline Heap_column<Master_matrix>::~Heap_column()
435 for (
auto* entry : column_) {
436 entryPool_->destroy(entry);
440template <
class Master_matrix>
441inline std::vector<typename Heap_column<Master_matrix>::Field_element> Heap_column<Master_matrix>::get_content(
442 int columnLength)
const
444 bool pivotLength = (columnLength < 0);
445 if (columnLength < 0 && column_.size() > 0)
446 columnLength = column_.front()->get_row_index() + 1;
447 else if (columnLength < 0)
448 return std::vector<Field_element>();
450 std::vector<Field_element> container(columnLength, 0);
451 for (
auto it = column_.begin(); it != column_.end(); ++it) {
452 auto idx = (*it)->get_row_index();
453 if (idx <
static_cast<ID_index
>(columnLength)) {
456 if constexpr (Master_matrix::Option_list::is_z2) {
457 container[idx] = !container[idx];
459 operators_->add_inplace(container[idx], (*it)->get_element());
465 while (!container.empty() && container.back() == 0U) container.pop_back();
471template <
class Master_matrix>
472inline bool Heap_column<Master_matrix>::is_non_zero(ID_index rowIndex)
const
475 for (
const Entry* entry : column_) {
476 if (entry->get_row_index() == rowIndex) {
477 _add_coefficient(c, entry->get_element());
480 return c != Field_operators::get_additive_identity();
483template <
class Master_matrix>
484inline bool Heap_column<Master_matrix>::is_empty()
486 Entry* pivot = _pop_pivot();
487 if (pivot !=
nullptr) {
488 column_.push_back(pivot);
489 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
495template <
class Master_matrix>
496inline std::size_t Heap_column<Master_matrix>::size()
const
498 return column_.size();
501template <
class Master_matrix>
502template <
class Row_index_map>
503inline void Heap_column<Master_matrix>::reorder(
const Row_index_map& valueMap, [[maybe_unused]] Index columnIndex)
505 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
506 "Method not available for chain columns.");
508 Column_support tempCol;
509 Entry* pivot = _pop_pivot();
510 while (pivot !=
nullptr) {
511 pivot->set_row_index(valueMap.at(pivot->get_row_index()));
512 tempCol.push_back(pivot);
513 pivot = _pop_pivot();
515 column_.swap(tempCol);
516 std::make_heap(column_.begin(), column_.end(), entryPointerComp_);
518 insertsSinceLastPrune_ = 0;
521template <
class Master_matrix>
522inline void Heap_column<Master_matrix>::clear()
524 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
525 "Method not available for chain columns as a base element should not be empty.");
527 for (
auto* entry : column_) {
528 entryPool_->destroy(entry);
532 insertsSinceLastPrune_ = 0;
535template <
class Master_matrix>
536inline void Heap_column<Master_matrix>::clear(ID_index rowIndex)
538 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
539 "Method not available for chain columns.");
541 Column_support tempCol;
542 Entry* pivot = _pop_pivot();
543 while (pivot !=
nullptr) {
544 if (pivot->get_row_index() != rowIndex) {
545 tempCol.push_back(pivot);
547 entryPool_->destroy(pivot);
549 pivot = _pop_pivot();
551 column_.swap(tempCol);
553 insertsSinceLastPrune_ = 0;
556template <
class Master_matrix>
557inline typename Heap_column<Master_matrix>::ID_index Heap_column<Master_matrix>::get_pivot()
559 static_assert(Master_matrix::isNonBasic,
560 "Method not available for base columns.");
562 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
563 Entry* pivot = _pop_pivot();
564 if (pivot !=
nullptr) {
565 column_.push_back(pivot);
566 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
567 return pivot->get_row_index();
569 return Master_matrix::template get_null_value<ID_index>();
571 return Chain_opt::_get_pivot();
575template <
class Master_matrix>
576inline typename Heap_column<Master_matrix>::Field_element Heap_column<Master_matrix>::get_pivot_value()
578 static_assert(Master_matrix::isNonBasic,
579 "Method not available for base columns.");
581 if constexpr (Master_matrix::Option_list::is_z2) {
584 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
585 Entry* pivot = _pop_pivot();
586 if (pivot !=
nullptr) {
587 column_.push_back(pivot);
588 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
589 return pivot->get_element();
593 Field_element sum(0);
594 if (Chain_opt::_get_pivot() == Master_matrix::template get_null_value<ID_index>())
return sum;
595 for (
const Entry* entry : column_) {
596 if (entry->get_row_index() == Chain_opt::_get_pivot()) operators_->add_inplace(sum, entry->get_element());
603template <
class Master_matrix>
604inline typename Heap_column<Master_matrix>::iterator Heap_column<Master_matrix>::begin() noexcept
606 return column_.begin();
609template <
class Master_matrix>
610inline typename Heap_column<Master_matrix>::const_iterator Heap_column<Master_matrix>::begin() const noexcept
612 return column_.begin();
615template <
class Master_matrix>
616inline typename Heap_column<Master_matrix>::iterator Heap_column<Master_matrix>::end() noexcept
618 return column_.end();
621template <
class Master_matrix>
622inline typename Heap_column<Master_matrix>::const_iterator Heap_column<Master_matrix>::end() const noexcept
624 return column_.end();
627template <
class Master_matrix>
628inline typename Heap_column<Master_matrix>::reverse_iterator Heap_column<Master_matrix>::rbegin() noexcept
630 return column_.rbegin();
633template <
class Master_matrix>
634inline typename Heap_column<Master_matrix>::const_reverse_iterator Heap_column<Master_matrix>::rbegin() const noexcept
636 return column_.rbegin();
639template <
class Master_matrix>
640inline typename Heap_column<Master_matrix>::reverse_iterator Heap_column<Master_matrix>::rend() noexcept
642 return column_.rend();
645template <
class Master_matrix>
646inline typename Heap_column<Master_matrix>::const_reverse_iterator Heap_column<Master_matrix>::rend() const noexcept
648 return column_.rend();
651template <
class Master_matrix>
652inline typename Heap_column<Master_matrix>::Content_range Heap_column<Master_matrix>::get_non_zero_content_range()
655 Content_range res(column_.size());
656 for (std::size_t i = 0; i < column_.size(); ++i) res[i] = *column_[i];
657 std::sort(res.begin(), res.end());
661template <
class Master_matrix>
662template <
class Entry_range>
665 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Heap_column>),
666 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
668 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
669 "For chain columns, the given column cannot be constant.");
671 Field_element dummy(0);
677template <
class Master_matrix>
680 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
681 Field_element v = get_pivot_value();
684 if (v == Field_operators::get_additive_identity()) {
685 Chain_opt::_swap_pivots(column);
686 Dim_opt::_swap_dimension(column);
689 Field_element dummy(0);
696template <
class Master_matrix>
699 _multiply<false>(Master_matrix::get_coefficient_value(v, operators_));
704template <
class Master_matrix>
705template <
class Entry_range>
707 const Entry_range& column)
709 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Heap_column>),
710 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
712 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
713 "For chain columns, the given column cannot be constant.");
715 _multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column);
720template <
class Master_matrix>
724 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
726 if (_multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column)) {
727 Chain_opt::_swap_pivots(column);
728 Dim_opt::_swap_dimension(column);
731 _multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column);
737template <
class Master_matrix>
738template <
class Entry_range>
740 const Field_element& val)
742 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Heap_column>),
743 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
745 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
746 "For chain columns, the given column cannot be constant.");
748 _multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_));
753template <
class Master_matrix>
755 const Field_element& val)
757 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
759 if (_multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_))) {
760 Chain_opt::_swap_pivots(column);
761 Dim_opt::_swap_dimension(column);
764 _multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_));
770template <
class Master_matrix>
771inline void Heap_column<Master_matrix>::push_back(
const Entry& entry)
773 static_assert(Master_matrix::Option_list::is_of_boundary_type,
"`push_back` is not available for Chain matrices.");
775 GUDHI_CHECK(entry.get_row_index() > get_pivot(),
776 std::invalid_argument(
"The new row index has to be higher than the current pivot."));
778 Entry* newEntry = entryPool_->construct(entry.get_row_index());
779 newEntry->set_element(Master_matrix::get_coefficient_value(entry.get_element(), operators_));
780 column_.push_back(newEntry);
781 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
784template <
class Master_matrix>
787 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
790 if (
this == &other)
return *
this;
792 Dim_opt::operator=(other);
793 Chain_opt::operator=(other);
795 while (column_.size() > other.column_.size()) {
796 if (column_.back() !=
nullptr) entryPool_->destroy(column_.back());
800 column_.resize(other.column_.size(),
nullptr);
802 for (
const Entry* entry : other.column_) {
803 if (column_[i] !=
nullptr) {
804 entryPool_->destroy(column_[i]);
806 column_[i] = other.entryPool_->construct(entry->get_row_index());
807 column_[i]->set_element(entry->get_element());
810 insertsSinceLastPrune_ = other.insertsSinceLastPrune_;
811 operators_ = other.operators_;
812 entryPool_ = other.entryPool_;
817template <
class Master_matrix>
820 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
823 if (&column_ == &(other.column_))
return *
this;
825 Dim_opt::operator=(std::move(other));
826 Chain_opt::operator=(std::move(other));
828 for (
auto* entry : column_) {
829 if (entry !=
nullptr) entryPool_->destroy(entry);
832 column_ = std::move(other.column_);
833 insertsSinceLastPrune_ = std::exchange(other.insertsSinceLastPrune_, 0);
834 operators_ = std::exchange(other.operators_,
nullptr);
835 entryPool_ = std::exchange(other.entryPool_,
nullptr);
840template <
class Master_matrix>
841inline std::size_t Heap_column<Master_matrix>::compute_hash_value()
844 return hash_column(*
this);
847template <
class Master_matrix>
848inline void Heap_column<Master_matrix>::_prune()
850 if (insertsSinceLastPrune_ == 0)
return;
852 Column_support tempCol;
853 Entry* pivot = _pop_pivot();
854 while (pivot !=
nullptr) {
855 tempCol.push_back(pivot);
856 pivot = _pop_pivot();
858 column_.swap(tempCol);
860 insertsSinceLastPrune_ = 0;
863template <
class Master_matrix>
864inline typename Heap_column<Master_matrix>::Entry* Heap_column<Master_matrix>::_pop_pivot()
866 if (column_.empty()) {
870 Entry* pivot = column_.front();
871 std::pop_heap(column_.begin(), column_.end(), entryPointerComp_);
873 if constexpr (Master_matrix::Option_list::is_z2) {
874 while (!column_.empty() && column_.front()->get_row_index() == pivot->get_row_index()) {
875 std::pop_heap(column_.begin(), column_.end(), entryPointerComp_);
876 entryPool_->destroy(column_.back());
879 entryPool_->destroy(pivot);
880 if (column_.empty()) {
883 pivot = column_.front();
884 std::pop_heap(column_.begin(), column_.end(), entryPointerComp_);
888 while (!column_.empty() && column_.front()->get_row_index() == pivot->get_row_index()) {
889 operators_->add_inplace(pivot->get_element(), column_.front()->get_element());
890 std::pop_heap(column_.begin(), column_.end(), entryPointerComp_);
891 entryPool_->destroy(column_.back());
895 if (pivot->get_element() == Field_operators::get_additive_identity()) {
896 entryPool_->destroy(pivot);
904template <
class Master_matrix>
905template <
class Entry_range>
906inline void Heap_column<Master_matrix>::_add(
const Entry_range& column, [[maybe_unused]] Field_element& pivotVal)
908 if (column.begin() == column.end())
return;
910 if (column_.empty()) {
911 column_.resize(column.size());
913 for (
const Entry& entry : column) {
914 column_[i] = entryPool_->construct(entry.get_row_index());
915 column_[i]->set_element(entry.get_element());
918 insertsSinceLastPrune_ = column_.size();
922 for (
const Entry& entry : column) {
923 ++insertsSinceLastPrune_;
925 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
926 if (entry.get_row_index() == Chain_opt::_get_pivot()) {
927 _add_coefficient(pivotVal, entry.get_element());
931 column_.push_back(entryPool_->construct(entry.get_row_index()));
932 column_.back()->set_element(entry.get_element());
934 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
937 if (2 * insertsSinceLastPrune_ > column_.size()) _prune();
940template <
class Master_matrix>
941template <
bool computePivotVal>
942inline std::conditional_t<computePivotVal, typename Heap_column<Master_matrix>::Field_element,
void>
943Heap_column<Master_matrix>::_multiply(
const Field_element& val)
945 Field_element pivotVal(0);
947 if (val == Field_operators::get_additive_identity()) {
948 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
950 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
953 if constexpr (computePivotVal)
960 if (val == Field_operators::get_multiplicative_identity()) {
961 if constexpr (computePivotVal)
962 return get_pivot_value();
969 if constexpr (!Master_matrix::Option_list::is_z2) {
970 for (
Entry* entry : column_) {
971 operators_->multiply_inplace(entry->get_element(), val);
972 if constexpr (computePivotVal) {
974 if (entry->get_row_index() == Chain_opt::_get_pivot()) {
975 operators_->add_inplace(pivotVal, entry->get_element());
981 if constexpr (computePivotVal)
987template <
class Master_matrix>
988template <
class Entry_range>
989inline bool Heap_column<Master_matrix>::_multiply_target_and_add(
const Field_element& val,
const Entry_range& column)
991 Field_element pivotVal(0);
993 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
994 pivotVal = _multiply<true>(val);
996 _multiply<false>(val);
999 _add(column, pivotVal);
1001 return pivotVal == Field_operators::get_additive_identity();
1005template <
class Master_matrix>
1006template <
class Entry_range>
1007inline bool Heap_column<Master_matrix>::_multiply_source_and_add(
const Entry_range& column,
const Field_element& val)
1009 if (val == Field_operators::get_additive_identity() || column.begin() == column.end()) {
1013 if (column_.empty()) {
1014 column_.resize(column.size());
1016 for (
const Entry& entry : column) {
1017 column_[i] = entryPool_->construct(entry.get_row_index());
1018 column_[i]->set_element(_multiply_coefficient(entry.get_element(), val));
1021 insertsSinceLastPrune_ = column_.size();
1025 Field_element pivotVal(0);
1027 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type)
1028 pivotVal = get_pivot_value();
1030 for (
const Entry& entry : column) {
1031 ++insertsSinceLastPrune_;
1033 column_.push_back(entryPool_->construct(entry.get_row_index()));
1034 column_.back()->set_element(_multiply_coefficient(entry.get_element(), val));
1036 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1037 if (entry.get_row_index() == Chain_opt::_get_pivot()) {
1038 _add_coefficient(pivotVal, column_.back()->get_element());
1042 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
1045 if (2 * insertsSinceLastPrune_ > column_.size()) _prune();
1047 return pivotVal == Field_operators::get_additive_identity();
1050template <
class Master_matrix>
1051inline void Heap_column<Master_matrix>::_add_coefficient(Field_element& e,
1052 [[maybe_unused]]
const Field_element& a)
const
1054 if constexpr (Master_matrix::Option_list::is_z2) {
1058 operators_->add_inplace(e, a);
1062template <
class Master_matrix>
1063inline typename Heap_column<Master_matrix>::Field_element Heap_column<Master_matrix>::_multiply_coefficient(
1064 const Field_element& e,
1065 [[maybe_unused]]
const Field_element& a)
const
1067 if constexpr (Master_matrix::Option_list::is_z2) {
1070 return operators_->multiply(e, a);
1085template <
class Master_matrix>
1086struct std::hash<
Gudhi::persistence_matrix::Heap_column<Master_matrix> > {
1089 return column.compute_hash_value();
Matrix entry class. Stores by default only the row index it belongs to, but can also store its column...
Definition entry_types.h:163
Column class following the PersistenceMatrixColumn concept. Not compatible with row access.
Definition heap_column.h:52
Contains different versions of Gudhi::persistence_matrix::Entry factories.
Persistence matrix namespace.
Definition FieldOperators.h:18
Gudhi namespace.
Definition SimplicialComplexForAlpha.h:14