18#ifndef PM_HEAP_COLUMN_H
19#define PM_HEAP_COLUMN_H
27#include <boost/iterator/indirect_iterator.hpp>
28#include "gudhi/Debug_utils.h"
33namespace persistence_matrix {
49template <
class Master_matrix>
53 using Master = Master_matrix;
54 using Index =
typename Master_matrix::Index;
55 using ID_index =
typename Master_matrix::ID_index;
56 using Dimension =
typename Master_matrix::Dimension;
57 using Field_element =
typename Master_matrix::Element;
58 using Entry =
typename Master_matrix::Matrix_entry;
59 using Column_settings =
typename Master_matrix::Column_settings;
62 using Field_operators =
typename Master_matrix::Field_operators;
63 using Column_support = std::vector<Entry*>;
64 using Entry_constructor =
typename Master_matrix::Entry_constructor;
67 using iterator = boost::indirect_iterator<typename Column_support::iterator>;
68 using const_iterator = boost::indirect_iterator<typename Column_support::const_iterator>;
69 using reverse_iterator = boost::indirect_iterator<typename Column_support::reverse_iterator>;
70 using const_reverse_iterator = boost::indirect_iterator<typename Column_support::const_reverse_iterator>;
72 Heap_column(Column_settings* colSettings =
nullptr);
73 template <
class Container =
typename Master_matrix::Boundary>
74 Heap_column(
const Container& nonZeroRowIndices, Column_settings* colSettings);
75 template <
class Container =
typename Master_matrix::Boundary>
76 Heap_column(
const Container& nonZeroChainRowIndices, Dimension dimension, Column_settings* colSettings);
83 template <
class Container =
typename Master_matrix::Boundary,
class Row_container>
85 const Container& nonZeroRowIndices,
86 Row_container* rowContainer,
87 Column_settings* colSettings);
88 template <
class Container =
typename Master_matrix::Boundary,
class Row_container>
90 const Container& nonZeroChainRowIndices,
92 Row_container* rowContainer,
93 Column_settings* colSettings);
94 template <
class Row_container>
97 Row_container* rowContainer,
98 Column_settings* colSettings =
nullptr);
100 std::vector<Field_element> get_content(
int columnLength = -1)
const;
101 bool is_non_zero(ID_index rowIndex)
const;
103 std::size_t size()
const;
105 template <
class Row_index_map>
106 void reorder(
const Row_index_map& valueMap,
107 [[maybe_unused]] Index columnIndex = Master_matrix::template get_null_value<Index>());
109 void clear(ID_index rowIndex);
111 ID_index get_pivot();
112 Field_element get_pivot_value();
114 iterator begin()
noexcept;
115 const_iterator begin()
const noexcept;
116 iterator end()
noexcept;
117 const_iterator end()
const noexcept;
118 reverse_iterator rbegin()
noexcept;
119 const_reverse_iterator rbegin()
const noexcept;
120 reverse_iterator rend()
noexcept;
121 const_reverse_iterator rend()
const noexcept;
123 template <
class Entry_range>
124 Heap_column& operator+=(
const Entry_range& column);
130 template <
class Entry_range>
131 Heap_column& multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
134 template <
class Entry_range>
135 Heap_column& multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
138 void push_back(
const Entry& entry);
140 std::size_t compute_hash_value();
143 if (&c1 == &c2)
return true;
146 Entry* p1 = cc1._pop_pivot();
147 Entry* p2 = cc2._pop_pivot();
148 while (p1 !=
nullptr && p2 !=
nullptr) {
149 if (p1->get_row_index() != p2->get_row_index()) {
150 c1.entryPool_->destroy(p1);
151 c2.entryPool_->destroy(p2);
154 if constexpr (!Master_matrix::Option_list::is_z2) {
155 if (p1->get_element() != p2->get_element()) {
156 c1.entryPool_->destroy(p1);
157 c2.entryPool_->destroy(p2);
161 c1.entryPool_->destroy(p1);
162 c2.entryPool_->destroy(p2);
163 p1 = cc1._pop_pivot();
164 p2 = cc2._pop_pivot();
167 if (p1 ==
nullptr && p2 ==
nullptr)
return true;
169 c1.entryPool_->destroy(p1);
172 c2.entryPool_->destroy(p2);
177 if (&c1 == &c2)
return false;
181 Entry* p1 = cc1._pop_pivot();
182 Entry* p2 = cc2._pop_pivot();
183 while (p1 !=
nullptr && p2 !=
nullptr) {
184 if (p1->get_row_index() > p2->get_row_index()) {
185 c1.entryPool_->destroy(p1);
186 c2.entryPool_->destroy(p2);
189 if (p1->get_row_index() < p2->get_row_index()) {
190 c1.entryPool_->destroy(p1);
191 c2.entryPool_->destroy(p2);
194 if constexpr (!Master_matrix::Option_list::is_z2) {
195 if (p1->get_element() > p2->get_element()) {
196 c1.entryPool_->destroy(p1);
197 c2.entryPool_->destroy(p2);
200 if (p1->get_element() < p2->get_element()) {
201 c1.entryPool_->destroy(p1);
202 c2.entryPool_->destroy(p2);
206 c1.entryPool_->destroy(p1);
207 c2.entryPool_->destroy(p2);
208 p1 = cc1._pop_pivot();
209 p2 = cc2._pop_pivot();
213 c1.entryPool_->destroy(p1);
216 c2.entryPool_->destroy(p2);
228 col1.column_.swap(col2.column_);
229 std::swap(col1.insertsSinceLastPrune_, col2.insertsSinceLastPrune_);
230 std::swap(col1.operators_, col2.operators_);
231 std::swap(col1.entryPool_, col2.entryPool_);
238 struct EntryPointerComp {
239 bool operator()(
const Entry* c1,
const Entry* c2)
const {
return *c1 < *c2; }
242 Column_support column_;
243 unsigned int insertsSinceLastPrune_;
244 Field_operators* operators_;
245 Entry_constructor* entryPool_;
249 template <
class Entry_range>
250 bool _add(
const Entry_range& column);
251 template <
class Entry_range>
252 bool _multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
253 template <
class Entry_range>
254 bool _multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
257template <
class Master_matrix>
261 insertsSinceLastPrune_(0),
263 entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor))
265 if (colSettings ==
nullptr)
return;
267 if constexpr (!Master_matrix::Option_list::is_z2) {
268 operators_ = &(colSettings->operators);
272template <
class Master_matrix>
273template <
class Container>
274inline Heap_column<Master_matrix>::Heap_column(
const Container& nonZeroRowIndices, Column_settings* colSettings)
275 : Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
277 column_(nonZeroRowIndices.size(), nullptr),
278 insertsSinceLastPrune_(0),
280 entryPool_(&(colSettings->entryConstructor))
282 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
283 "Constructor not available for chain columns, please specify the dimension of the chain.");
285 if constexpr (!Master_matrix::Option_list::is_z2) {
286 operators_ = &(colSettings->operators);
290 if constexpr (Master_matrix::Option_list::is_z2) {
291 for (ID_index
id : nonZeroRowIndices) {
292 column_[i++] = entryPool_->construct(
id);
295 for (
const auto& p : nonZeroRowIndices) {
296 column_[i] = entryPool_->construct(p.first);
297 column_[i++]->set_element(operators_->get_value(p.second));
300 std::make_heap(column_.begin(), column_.end(), entryPointerComp_);
303template <
class Master_matrix>
304template <
class Container>
305inline Heap_column<Master_matrix>::Heap_column(
const Container& nonZeroRowIndices,
307 Column_settings* colSettings)
308 : Dim_opt(dimension),
310 if constexpr (Master_matrix::Option_list::is_z2) {
311 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
312 ? Master_matrix::template get_null_value<ID_index>()
313 : *
std::prev(nonZeroRowIndices.end());
315 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
316 ? Master_matrix::template get_null_value<ID_index>()
317 :
std::prev(nonZeroRowIndices.end())->first;
320 column_(nonZeroRowIndices.size(),
nullptr),
321 insertsSinceLastPrune_(0),
323 entryPool_(&(colSettings->entryConstructor))
326 if constexpr (Master_matrix::Option_list::is_z2) {
327 for (ID_index
id : nonZeroRowIndices) {
328 column_[i++] = entryPool_->construct(
id);
331 operators_ = &(colSettings->operators);
332 for (
const auto& p : nonZeroRowIndices) {
333 column_[i] = entryPool_->construct(p.first);
334 column_[i++]->set_element(operators_->get_value(p.second));
337 std::make_heap(column_.begin(), column_.end(), entryPointerComp_);
340template <
class Master_matrix>
341inline Heap_column<Master_matrix>::Heap_column(
const Heap_column& column, Column_settings* colSettings)
342 : Dim_opt(static_cast<const Dim_opt&>(column)),
343 Chain_opt(static_cast<const Chain_opt&>(column)),
344 column_(column.column_.size(), nullptr),
345 insertsSinceLastPrune_(0),
346 operators_(colSettings == nullptr ? column.operators_ : nullptr),
347 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
349 static_assert(!Master_matrix::Option_list::has_row_access,
350 "Simple copy constructor not available when row access option enabled. Please specify the new column "
351 "index and the row container.");
353 if constexpr (!Master_matrix::Option_list::is_z2) {
354 if (colSettings !=
nullptr) operators_ = &(colSettings->operators);
358 for (
const Entry* entry : column.column_) {
359 if constexpr (Master_matrix::Option_list::is_z2) {
360 column_[i++] = entryPool_->construct(entry->get_row_index());
362 column_[i] = entryPool_->construct(entry->get_row_index());
363 column_[i++]->set_element(entry->get_element());
369template <
class Master_matrix>
370inline Heap_column<Master_matrix>::Heap_column(Heap_column&& column) noexcept
371 : Dim_opt(std::move(
static_cast<Dim_opt&
>(column))),
372 Chain_opt(std::move(
static_cast<Chain_opt&
>(column))),
373 column_(std::move(column.column_)),
374 insertsSinceLastPrune_(std::exchange(column.insertsSinceLastPrune_, 0)),
375 operators_(std::exchange(column.operators_,
nullptr)),
376 entryPool_(std::exchange(column.entryPool_,
nullptr))
379template <
class Master_matrix>
380template <
class Container,
class Row_container>
381inline Heap_column<Master_matrix>::Heap_column(Index columnIndex,
382 const Container& nonZeroRowIndices,
383 Row_container* rowContainer,
384 Column_settings* colSettings)
385 : Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
387 if constexpr (Master_matrix::Option_list::is_z2) {
388 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
389 ? Master_matrix::template get_null_value<ID_index>()
390 : *
std::prev(nonZeroRowIndices.end());
392 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
393 ? Master_matrix::template get_null_value<ID_index>()
394 :
std::prev(nonZeroRowIndices.end())->first;
397 column_(nonZeroRowIndices.size(),
nullptr),
398 insertsSinceLastPrune_(0),
400 entryPool_(&(colSettings->entryConstructor))
402 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
403 "Constructor not available for chain columns, please specify the dimension of the chain.");
406 if constexpr (Master_matrix::Option_list::is_z2) {
407 for (ID_index
id : nonZeroRowIndices) {
408 column_[i++] = entryPool_->construct(
id);
411 operators_ = &(colSettings->operators);
412 for (
const auto& p : nonZeroRowIndices) {
413 column_[i] = entryPool_->construct(p.first);
414 column_[i++]->set_element(operators_->get_value(p.second));
417 std::make_heap(column_.begin(), column_.end(), entryPointerComp_);
420template <
class Master_matrix>
421template <
class Container,
class Row_container>
422inline Heap_column<Master_matrix>::Heap_column(Index columnIndex,
423 const Container& nonZeroRowIndices,
425 Row_container* rowContainer,
426 Column_settings* colSettings)
427 : Dim_opt(dimension),
429 if constexpr (Master_matrix::Option_list::is_z2) {
430 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
431 ? Master_matrix::template get_null_value<ID_index>()
432 : *
std::prev(nonZeroRowIndices.end());
434 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
435 ? Master_matrix::template get_null_value<ID_index>()
436 :
std::prev(nonZeroRowIndices.end())->first;
439 column_(nonZeroRowIndices.size(),
nullptr),
440 insertsSinceLastPrune_(0),
442 entryPool_(&(colSettings->entryConstructor))
445 if constexpr (Master_matrix::Option_list::is_z2) {
446 for (ID_index
id : nonZeroRowIndices) {
447 column_[i++] = entryPool_->construct(
id);
450 operators_ = &(colSettings->operators);
451 for (
const auto& p : nonZeroRowIndices) {
452 column_[i] = entryPool_->construct(p.first);
453 column_[i++]->set_element(operators_->get_value(p.second));
456 std::make_heap(column_.begin(), column_.end(), entryPointerComp_);
459template <
class Master_matrix>
460template <
class Row_container>
461inline Heap_column<Master_matrix>::Heap_column(
const Heap_column& column,
463 Row_container* rowContainer,
464 Column_settings* colSettings)
465 : Dim_opt(static_cast<const Dim_opt&>(column)),
466 Chain_opt(static_cast<const Chain_opt&>(column)),
467 column_(column.column_.size(), nullptr),
468 insertsSinceLastPrune_(0),
469 operators_(colSettings == nullptr ? column.operators_ : nullptr),
470 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
472 if constexpr (!Master_matrix::Option_list::is_z2) {
473 if (colSettings !=
nullptr) operators_ = &(colSettings->operators);
477 for (
const Entry* entry : column.column_) {
478 if constexpr (Master_matrix::Option_list::is_z2) {
479 column_[i++] = entryPool_->construct(entry->get_row_index());
481 column_[i] = entryPool_->construct(entry->get_row_index());
482 column_[i++]->set_element(entry->get_element());
488template <
class Master_matrix>
489inline Heap_column<Master_matrix>::~Heap_column()
491 for (
auto* entry : column_) {
492 entryPool_->destroy(entry);
496template <
class Master_matrix>
497inline std::vector<typename Heap_column<Master_matrix>::Field_element> Heap_column<Master_matrix>::get_content(
498 int columnLength)
const
500 bool pivotLength = (columnLength < 0);
501 if (columnLength < 0 && column_.size() > 0)
502 columnLength = column_.front()->get_row_index() + 1;
503 else if (columnLength < 0)
504 return std::vector<Field_element>();
506 std::vector<Field_element> container(columnLength, 0);
507 for (
auto it = column_.begin(); it != column_.end(); ++it) {
508 if ((*it)->get_row_index() <
static_cast<ID_index
>(columnLength)) {
509 if constexpr (Master_matrix::Option_list::is_z2) {
510 container[(*it)->get_row_index()] = !container[(*it)->get_row_index()];
512 operators_->add_inplace(container[(*it)->get_row_index()], (*it)->get_element());
518 while (!container.empty() && container.back() == 0u) container.pop_back();
524template <
class Master_matrix>
525inline bool Heap_column<Master_matrix>::is_non_zero(ID_index rowIndex)
const
528 for (
const Entry* entry : column_) {
529 if (entry->get_row_index() == rowIndex) {
530 if constexpr (Master_matrix::Option_list::is_z2)
533 operators_->add_inplace(c, entry->get_element());
536 return c != Field_operators::get_additive_identity();
539template <
class Master_matrix>
540inline bool Heap_column<Master_matrix>::is_empty()
542 Entry* pivot = _pop_pivot();
543 if (pivot !=
nullptr) {
544 column_.push_back(pivot);
545 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
551template <
class Master_matrix>
552inline std::size_t Heap_column<Master_matrix>::size()
const
554 return column_.size();
557template <
class Master_matrix>
558template <
class Row_index_map>
559inline void Heap_column<Master_matrix>::reorder(
const Row_index_map& valueMap, [[maybe_unused]] Index columnIndex)
561 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
562 "Method not available for chain columns.");
564 Column_support tempCol;
565 Entry* pivot = _pop_pivot();
566 while (pivot !=
nullptr) {
567 pivot->set_row_index(valueMap.at(pivot->get_row_index()));
568 tempCol.push_back(pivot);
569 pivot = _pop_pivot();
571 column_.swap(tempCol);
572 std::make_heap(column_.begin(), column_.end(), entryPointerComp_);
574 insertsSinceLastPrune_ = 0;
577template <
class Master_matrix>
578inline void Heap_column<Master_matrix>::clear()
580 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
581 "Method not available for chain columns as a base element should not be empty.");
583 for (
auto* entry : column_) {
584 entryPool_->destroy(entry);
588 insertsSinceLastPrune_ = 0;
591template <
class Master_matrix>
592inline void Heap_column<Master_matrix>::clear(ID_index rowIndex)
594 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
595 "Method not available for chain columns.");
597 Column_support tempCol;
598 Entry* pivot = _pop_pivot();
599 while (pivot !=
nullptr) {
600 if (pivot->get_row_index() != rowIndex) {
601 tempCol.push_back(pivot);
603 entryPool_->destroy(pivot);
605 pivot = _pop_pivot();
607 column_.swap(tempCol);
609 insertsSinceLastPrune_ = 0;
612template <
class Master_matrix>
613inline typename Heap_column<Master_matrix>::ID_index Heap_column<Master_matrix>::get_pivot()
615 static_assert(Master_matrix::isNonBasic,
616 "Method not available for base columns.");
618 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
619 Entry* pivot = _pop_pivot();
620 if (pivot !=
nullptr) {
621 column_.push_back(pivot);
622 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
623 return pivot->get_row_index();
625 return Master_matrix::template get_null_value<ID_index>();
627 return Chain_opt::get_pivot();
631template <
class Master_matrix>
632inline typename Heap_column<Master_matrix>::Field_element Heap_column<Master_matrix>::get_pivot_value()
634 static_assert(Master_matrix::isNonBasic,
635 "Method not available for base columns.");
637 if constexpr (Master_matrix::Option_list::is_z2) {
640 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
641 Entry* pivot = _pop_pivot();
642 if (pivot !=
nullptr) {
643 column_.push_back(pivot);
644 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
645 return pivot->get_element();
649 Field_element sum(0);
650 if (Chain_opt::get_pivot() == Master_matrix::template get_null_value<ID_index>())
return sum;
651 for (
const Entry* entry : column_) {
652 if (entry->get_row_index() == Chain_opt::get_pivot()) operators_->add_inplace(sum, entry->get_element());
659template <
class Master_matrix>
660inline typename Heap_column<Master_matrix>::iterator Heap_column<Master_matrix>::begin() noexcept
662 return column_.begin();
665template <
class Master_matrix>
666inline typename Heap_column<Master_matrix>::const_iterator Heap_column<Master_matrix>::begin() const noexcept
668 return column_.begin();
671template <
class Master_matrix>
672inline typename Heap_column<Master_matrix>::iterator Heap_column<Master_matrix>::end() noexcept
674 return column_.end();
677template <
class Master_matrix>
678inline typename Heap_column<Master_matrix>::const_iterator Heap_column<Master_matrix>::end() const noexcept
680 return column_.end();
683template <
class Master_matrix>
684inline typename Heap_column<Master_matrix>::reverse_iterator Heap_column<Master_matrix>::rbegin() noexcept
686 return column_.rbegin();
689template <
class Master_matrix>
690inline typename Heap_column<Master_matrix>::const_reverse_iterator Heap_column<Master_matrix>::rbegin() const noexcept
692 return column_.rbegin();
695template <
class Master_matrix>
696inline typename Heap_column<Master_matrix>::reverse_iterator Heap_column<Master_matrix>::rend() noexcept
698 return column_.rend();
701template <
class Master_matrix>
702inline typename Heap_column<Master_matrix>::const_reverse_iterator Heap_column<Master_matrix>::rend() const noexcept
704 return column_.rend();
707template <
class Master_matrix>
708template <
class Entry_range>
709inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::operator+=(
const Entry_range& column)
711 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Heap_column>),
712 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
714 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
715 "For chain columns, the given column cannot be constant.");
722template <
class Master_matrix>
723inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::operator+=(Heap_column& column)
725 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
728 Chain_opt::swap_pivots(column);
729 Dim_opt::swap_dimension(column);
738template <
class Master_matrix>
739inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::operator*=(
unsigned int v)
741 if constexpr (Master_matrix::Option_list::is_z2) {
743 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
744 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
750 Field_element val = operators_->get_value(v);
752 if (val == Field_operators::get_additive_identity()) {
753 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
754 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
761 if (val == Field_operators::get_multiplicative_identity())
return *
this;
763 for (Entry* entry : column_) {
764 operators_->multiply_inplace(entry->get_element(), val);
771template <
class Master_matrix>
772template <
class Entry_range>
773inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::multiply_target_and_add(
const Field_element& val,
774 const Entry_range& column)
776 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Heap_column>),
777 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
779 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
780 "For chain columns, the given column cannot be constant.");
782 if constexpr (Master_matrix::Option_list::is_z2) {
790 _multiply_target_and_add(val, column);
796template <
class Master_matrix>
797inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::multiply_target_and_add(
const Field_element& val,
800 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
802 if constexpr (Master_matrix::Option_list::is_z2) {
805 Chain_opt::swap_pivots(column);
806 Dim_opt::swap_dimension(column);
809 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
812 if (_multiply_target_and_add(val, column)) {
813 Chain_opt::swap_pivots(column);
814 Dim_opt::swap_dimension(column);
818 if constexpr (Master_matrix::Option_list::is_z2) {
826 _multiply_target_and_add(val, column);
833template <
class Master_matrix>
834template <
class Entry_range>
835inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::multiply_source_and_add(
const Entry_range& column,
836 const Field_element& val)
838 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Heap_column>),
839 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
841 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
842 "For chain columns, the given column cannot be constant.");
844 if constexpr (Master_matrix::Option_list::is_z2) {
849 _multiply_source_and_add(column, val);
855template <
class Master_matrix>
856inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::multiply_source_and_add(Heap_column& column,
857 const Field_element& val)
859 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
861 if constexpr (Master_matrix::Option_list::is_z2) {
864 Chain_opt::swap_pivots(column);
865 Dim_opt::swap_dimension(column);
869 if (_multiply_source_and_add(column, val)) {
870 Chain_opt::swap_pivots(column);
871 Dim_opt::swap_dimension(column);
875 if constexpr (Master_matrix::Option_list::is_z2) {
880 _multiply_source_and_add(column, val);
887template <
class Master_matrix>
888inline void Heap_column<Master_matrix>::push_back(
const Entry& entry)
890 static_assert(Master_matrix::Option_list::is_of_boundary_type,
"`push_back` is not available for Chain matrices.");
892 GUDHI_CHECK(entry.get_row_index() > get_pivot(),
"The new row index has to be higher than the current pivot.");
894 Entry* newEntry = entryPool_->construct(entry.get_row_index());
895 if constexpr (!Master_matrix::Option_list::is_z2) {
896 newEntry->set_element(operators_->get_value(entry.get_element()));
898 column_.push_back(newEntry);
899 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
902template <
class Master_matrix>
903inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::operator=(
const Heap_column& other)
905 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
907 Dim_opt::operator=(other);
908 Chain_opt::operator=(other);
910 while (column_.size() > other.column_.size()) {
911 if (column_.back() !=
nullptr) entryPool_->destroy(column_.back());
915 column_.resize(other.column_.size(),
nullptr);
917 for (
const Entry* entry : other.column_) {
918 if (column_[i] !=
nullptr) {
919 entryPool_->destroy(column_[i]);
921 column_[i] = other.entryPool_->construct(entry->get_row_index());
922 if constexpr (!Master_matrix::Option_list::is_z2) {
923 column_[i]->set_element(entry->get_element());
927 insertsSinceLastPrune_ = other.insertsSinceLastPrune_;
928 operators_ = other.operators_;
929 entryPool_ = other.entryPool_;
934template <
class Master_matrix>
935inline std::size_t Heap_column<Master_matrix>::compute_hash_value()
938 return hash_column(*
this);
941template <
class Master_matrix>
942inline void Heap_column<Master_matrix>::_prune()
944 if (insertsSinceLastPrune_ == 0)
return;
946 Column_support tempCol;
947 Entry* pivot = _pop_pivot();
948 while (pivot !=
nullptr) {
949 tempCol.push_back(pivot);
950 pivot = _pop_pivot();
952 column_.swap(tempCol);
954 insertsSinceLastPrune_ = 0;
957template <
class Master_matrix>
958inline typename Heap_column<Master_matrix>::Entry* Heap_column<Master_matrix>::_pop_pivot()
960 if (column_.empty()) {
964 Entry* pivot = column_.front();
965 std::pop_heap(column_.begin(), column_.end(), entryPointerComp_);
967 if constexpr (Master_matrix::Option_list::is_z2) {
968 while (!column_.empty() && column_.front()->get_row_index() == pivot->get_row_index()) {
969 std::pop_heap(column_.begin(), column_.end(), entryPointerComp_);
970 entryPool_->destroy(column_.back());
973 entryPool_->destroy(pivot);
974 if (column_.empty()) {
977 pivot = column_.front();
978 std::pop_heap(column_.begin(), column_.end(), entryPointerComp_);
982 while (!column_.empty() && column_.front()->get_row_index() == pivot->get_row_index()) {
983 operators_->add_inplace(pivot->get_element(), column_.front()->get_element());
984 std::pop_heap(column_.begin(), column_.end(), entryPointerComp_);
985 entryPool_->destroy(column_.back());
989 if (pivot->get_element() == Field_operators::get_additive_identity()) {
990 entryPool_->destroy(pivot);
998template <
class Master_matrix>
999template <
class Entry_range>
1000inline bool Heap_column<Master_matrix>::_add(
const Entry_range& column)
1002 if (column.begin() == column.end())
return false;
1003 if (column_.empty()) {
1004 column_.resize(column.size());
1006 for (
const Entry& entry : column) {
1007 column_[i] = entryPool_->construct(entry.get_row_index());
1008 if constexpr (!Master_matrix::Option_list::is_z2) {
1009 column_[i]->set_element(entry.get_element());
1013 insertsSinceLastPrune_ = column_.size();
1017 Field_element pivotVal(1);
1019 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type)
1020 pivotVal = get_pivot_value();
1022 for (
const Entry& entry : column) {
1023 ++insertsSinceLastPrune_;
1024 if constexpr (Master_matrix::Option_list::is_z2) {
1025 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1026 if (entry.get_row_index() == Chain_opt::get_pivot()) pivotVal = !pivotVal;
1028 column_.push_back(entryPool_->construct(entry.get_row_index()));
1030 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1031 if (entry.get_row_index() == Chain_opt::get_pivot()) operators_->add_inplace(pivotVal, entry.get_element());
1033 column_.push_back(entryPool_->construct(entry.get_row_index()));
1034 column_.back()->set_element(entry.get_element());
1036 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
1039 if (2 * insertsSinceLastPrune_ > column_.size()) _prune();
1041 if constexpr (Master_matrix::Option_list::is_z2)
1044 return pivotVal == Field_operators::get_additive_identity();
1047template <
class Master_matrix>
1048template <
class Entry_range>
1049inline bool Heap_column<Master_matrix>::_multiply_target_and_add(
const Field_element& val,
const Entry_range& column)
1052 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1053 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
1059 if (column_.empty()) {
1060 column_.resize(column.size());
1062 for (
const Entry& entry : column) {
1063 column_[i] = entryPool_->construct(entry.get_row_index());
1064 column_[i++]->set_element(entry.get_element());
1066 insertsSinceLastPrune_ = column_.size();
1070 Field_element pivotVal(0);
1072 for (Entry* entry : column_) {
1073 operators_->multiply_inplace(entry->get_element(), val);
1074 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1075 if (entry->get_row_index() == Chain_opt::get_pivot()) operators_->add_inplace(pivotVal, entry->get_element());
1079 for (
const Entry& entry : column) {
1080 ++insertsSinceLastPrune_;
1081 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1082 if (entry.get_row_index() == Chain_opt::get_pivot()) operators_->add_inplace(pivotVal, entry.get_element());
1084 column_.push_back(entryPool_->construct(entry.get_row_index()));
1085 column_.back()->set_element(entry.get_element());
1086 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
1089 if (2 * insertsSinceLastPrune_ > column_.size()) _prune();
1091 if constexpr (Master_matrix::Option_list::is_z2)
1094 return pivotVal == Field_operators::get_additive_identity();
1097template <
class Master_matrix>
1098template <
class Entry_range>
1099inline bool Heap_column<Master_matrix>::_multiply_source_and_add(
const Entry_range& column,
const Field_element& val)
1101 if (val == 0u || column.begin() == column.end()) {
1104 if (column_.empty()) {
1105 column_.resize(column.size());
1107 for (
const Entry& entry : column) {
1108 column_[i] = entryPool_->construct(entry.get_row_index());
1109 column_[i++]->set_element(entry.get_element());
1111 insertsSinceLastPrune_ = column_.size();
1115 Field_element pivotVal(1);
1117 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type)
1118 pivotVal = get_pivot_value();
1120 for (
const Entry& entry : column) {
1121 ++insertsSinceLastPrune_;
1122 column_.push_back(entryPool_->construct(entry.get_row_index()));
1123 column_.back()->set_element(entry.get_element());
1124 operators_->multiply_inplace(column_.back()->get_element(), val);
1125 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1126 if (entry.get_row_index() == Chain_opt::get_pivot()) {
1127 operators_->add_inplace(pivotVal, column_.back()->get_element());
1130 std::push_heap(column_.begin(), column_.end(), entryPointerComp_);
1133 if (2 * insertsSinceLastPrune_ > column_.size()) _prune();
1135 return pivotVal == 0u;
1149template <
class Master_matrix>
1150struct std::hash<
Gudhi::persistence_matrix::Heap_column<Master_matrix> > {
1152 return column.compute_hash_value();
Column class following the PersistenceMatrixColumn concept. Not compatible with row access.
Definition: heap_column.h:51
Contains different versions of Gudhi::persistence_matrix::Entry factories.
Chain_column_extra_properties Chain_column_option
If PersistenceMatrixOptions::is_of_boundary_type is false, and, PersistenceMatrixOptions::has_column_...
Definition: PersistenceMatrixColumn.h:45
Column_dimension_holder Column_dimension_option
If PersistenceMatrixOptions::has_column_pairings or PersistenceMatrixOptions::has_vine_update or Pers...
Definition: PersistenceMatrixColumn.h:36
Gudhi namespace.
Definition: SimplicialComplexForAlpha.h:14