17 #ifndef PM_HEAP_COLUMN_H
18 #define PM_HEAP_COLUMN_H
22 #include <type_traits>
26 #include <boost/iterator/indirect_iterator.hpp>
31 namespace persistence_matrix {
48 template <
class Master_matrix>
52 using Master = Master_matrix;
53 using index =
typename Master_matrix::index;
54 using id_index =
typename Master_matrix::id_index;
55 using dimension_type =
typename Master_matrix::dimension_type;
56 using Field_element_type =
typename Master_matrix::element_type;
57 using Cell =
typename Master_matrix::Cell_type;
58 using Column_settings =
typename Master_matrix::Column_settings;
61 using Field_operators =
typename Master_matrix::Field_operators;
62 using Column_type = std::vector<Cell*>;
63 using Cell_constructor =
typename Master_matrix::Cell_constructor;
66 using iterator = boost::indirect_iterator<typename Column_type::iterator>;
67 using const_iterator = boost::indirect_iterator<typename Column_type::const_iterator>;
68 using reverse_iterator = boost::indirect_iterator<typename Column_type::reverse_iterator>;
69 using const_reverse_iterator = boost::indirect_iterator<typename Column_type::const_reverse_iterator>;
71 Heap_column(Column_settings* colSettings =
nullptr);
72 template <
class Container_type =
typename Master_matrix::boundary_type>
73 Heap_column(
const Container_type& nonZeroRowIndices, Column_settings* colSettings);
74 template <
class Container_type =
typename Master_matrix::boundary_type>
75 Heap_column(
const Container_type& nonZeroChainRowIndices,
76 dimension_type dimension,
77 Column_settings* colSettings);
84 template <
class Container_type =
typename Master_matrix::boundary_type,
class Row_container_type>
86 const Container_type& nonZeroRowIndices,
87 Row_container_type* rowContainer,
88 Column_settings* colSettings);
89 template <
class Container_type =
typename Master_matrix::boundary_type,
class Row_container_type>
91 const Container_type& nonZeroChainRowIndices,
92 dimension_type dimension,
93 Row_container_type* rowContainer,
94 Column_settings* colSettings);
95 template <
class Row_container_type>
98 Row_container_type* rowContainer,
99 Column_settings* colSettings =
nullptr);
101 std::vector<Field_element_type> get_content(
int columnLength = -1)
const;
102 bool is_non_zero(id_index rowIndex)
const;
104 std::size_t size()
const;
106 template <
class Map_type>
107 void reorder(
const Map_type& valueMap, [[maybe_unused]] index columnIndex = -1);
109 void clear(id_index rowIndex);
111 id_index get_pivot();
112 Field_element_type 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 Cell_range>
130 template <
class Cell_range>
131 Heap_column& multiply_target_and_add(
const Field_element_type& val,
const Cell_range& column);
134 template <
class Cell_range>
135 Heap_column& multiply_source_and_add(
const Cell_range& column,
const Field_element_type& val);
138 std::size_t compute_hash_value();
141 if (&c1 == &c2)
return true;
144 Cell* p1 = cc1._pop_pivot();
145 Cell* p2 = cc2._pop_pivot();
146 while (p1 !=
nullptr && p2 !=
nullptr) {
147 if (p1->get_row_index() != p2->get_row_index()) {
148 c1.cellPool_->destroy(p1);
149 c2.cellPool_->destroy(p2);
152 if constexpr (!Master_matrix::Option_list::is_z2){
153 if (p1->get_element() != p2->get_element()) {
154 c1.cellPool_->destroy(p1);
155 c2.cellPool_->destroy(p2);
159 c1.cellPool_->destroy(p1);
160 c2.cellPool_->destroy(p2);
161 p1 = cc1._pop_pivot();
162 p2 = cc2._pop_pivot();
165 if (p1 ==
nullptr && p2 ==
nullptr)
return true;
167 c1.cellPool_->destroy(p1);
170 c2.cellPool_->destroy(p2);
174 if (&c1 == &c2)
return false;
178 Cell* p1 = cc1._pop_pivot();
179 Cell* p2 = cc2._pop_pivot();
180 while (p1 !=
nullptr && p2 !=
nullptr) {
181 if (p1->get_row_index() > p2->get_row_index()) {
182 c1.cellPool_->destroy(p1);
183 c2.cellPool_->destroy(p2);
186 if (p1->get_row_index() < p2->get_row_index()) {
187 c1.cellPool_->destroy(p1);
188 c2.cellPool_->destroy(p2);
191 if constexpr (!Master_matrix::Option_list::is_z2){
192 if (p1->get_element() > p2->get_element()) {
193 c1.cellPool_->destroy(p1);
194 c2.cellPool_->destroy(p2);
197 if (p1->get_element() < p2->get_element()) {
198 c1.cellPool_->destroy(p1);
199 c2.cellPool_->destroy(p2);
203 c1.cellPool_->destroy(p1);
204 c2.cellPool_->destroy(p2);
205 p1 = cc1._pop_pivot();
206 p2 = cc2._pop_pivot();
210 c1.cellPool_->destroy(p1);
213 c2.cellPool_->destroy(p2);
225 col1.column_.swap(col2.column_);
226 std::swap(col1.insertsSinceLastPrune_, col2.insertsSinceLastPrune_);
227 std::swap(col1.operators_, col2.operators_);
228 std::swap(col1.cellPool_, col2.cellPool_);
236 bool operator()(
const Cell* c1,
const Cell* c2)
const {
return *c1 < *c2; }
240 unsigned int insertsSinceLastPrune_;
241 Field_operators* operators_;
242 Cell_constructor* cellPool_;
246 template <
class Cell_range>
247 bool _add(
const Cell_range& column);
248 template <
class Cell_range>
249 bool _multiply_target_and_add(
const Field_element_type& val,
const Cell_range& column);
250 template <
class Cell_range>
251 bool _multiply_source_and_add(
const Cell_range& column,
const Field_element_type& val);
254 template <
class Master_matrix>
256 : dim_opt(), chain_opt(), insertsSinceLastPrune_(0), operators_(nullptr), cellPool_(colSettings == nullptr ? nullptr : &(colSettings->cellConstructor))
258 if (colSettings ==
nullptr)
return;
259 if constexpr (!Master_matrix::Option_list::is_z2){
260 operators_ = &(colSettings->operators);
264 template <
class Master_matrix>
265 template <
class Container_type>
266 inline Heap_column<Master_matrix>::Heap_column(
const Container_type& nonZeroRowIndices, Column_settings* colSettings)
267 : dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
269 column_(nonZeroRowIndices.size(), nullptr),
270 insertsSinceLastPrune_(0),
272 cellPool_(&(colSettings->cellConstructor))
274 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
275 "Constructor not available for chain columns, please specify the dimension of the chain.");
277 if constexpr (!Master_matrix::Option_list::is_z2){
278 operators_ = &(colSettings->operators);
282 if constexpr (Master_matrix::Option_list::is_z2) {
283 for (id_index
id : nonZeroRowIndices) {
284 column_[i++] = cellPool_->construct(
id);
287 for (
const auto& p : nonZeroRowIndices) {
288 column_[i] = cellPool_->construct(p.first);
289 column_[i++]->set_element(operators_->get_value(p.second));
292 std::make_heap(column_.begin(), column_.end(), cellPointerComp_);
295 template <
class Master_matrix>
296 template <
class Container_type>
297 inline Heap_column<Master_matrix>::Heap_column(
const Container_type& nonZeroRowIndices,
298 dimension_type dimension,
299 Column_settings* colSettings)
300 : dim_opt(dimension),
302 if constexpr (Master_matrix::Option_list::is_z2) {
303 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : *std::prev(nonZeroRowIndices.end());
305 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : std::prev(nonZeroRowIndices.end())->first;
308 column_(nonZeroRowIndices.size(),
nullptr),
309 insertsSinceLastPrune_(0),
311 cellPool_(&(colSettings->cellConstructor))
314 if constexpr (Master_matrix::Option_list::is_z2) {
315 for (id_index
id : nonZeroRowIndices) {
316 column_[i++] = cellPool_->construct(
id);
319 operators_ = &(colSettings->operators);
320 for (
const auto& p : nonZeroRowIndices) {
321 column_[i] = cellPool_->construct(p.first);
322 column_[i++]->set_element(operators_->get_value(p.second));
325 std::make_heap(column_.begin(), column_.end(), cellPointerComp_);
328 template <
class Master_matrix>
329 inline Heap_column<Master_matrix>::Heap_column(
const Heap_column& column,
330 Column_settings* colSettings)
331 : dim_opt(static_cast<const dim_opt&>(column)),
332 chain_opt(static_cast<const chain_opt&>(column)),
333 column_(column.column_.size(), nullptr),
334 insertsSinceLastPrune_(0),
335 operators_(colSettings == nullptr ? column.operators_ : nullptr),
336 cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor))
338 static_assert(!Master_matrix::Option_list::has_row_access,
339 "Simple copy constructor not available when row access option enabled. Please specify the new column "
340 "index and the row container.");
342 if constexpr (!Master_matrix::Option_list::is_z2){
343 if (colSettings !=
nullptr) operators_ = &(colSettings->operators);
347 for (
const Cell* cell : column.column_) {
348 if constexpr (Master_matrix::Option_list::is_z2) {
349 column_[i++] = cellPool_->construct(cell->get_row_index());
351 column_[i] = cellPool_->construct(cell->get_row_index());
352 column_[i++]->set_element(cell->get_element());
358 template <
class Master_matrix>
359 inline Heap_column<Master_matrix>::Heap_column(Heap_column&& column) noexcept
360 : dim_opt(std::move(
static_cast<dim_opt&
>(column))),
361 chain_opt(std::move(
static_cast<chain_opt&
>(column))),
362 column_(std::move(column.column_)),
363 insertsSinceLastPrune_(std::exchange(column.insertsSinceLastPrune_, 0)),
364 operators_(std::exchange(column.operators_,
nullptr)),
365 cellPool_(std::exchange(column.cellPool_,
nullptr))
368 template <
class Master_matrix>
369 template <
class Container_type,
class Row_container_type>
370 inline Heap_column<Master_matrix>::Heap_column(index columnIndex,
371 const Container_type& nonZeroRowIndices,
372 Row_container_type* rowContainer,
373 Column_settings* colSettings)
374 : dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
376 if constexpr (Master_matrix::Option_list::is_z2) {
377 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : *std::prev(nonZeroRowIndices.end());
379 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : std::prev(nonZeroRowIndices.end())->first;
382 column_(nonZeroRowIndices.size(),
nullptr),
383 insertsSinceLastPrune_(0),
385 cellPool_(&(colSettings->cellConstructor))
387 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
388 "Constructor not available for chain columns, please specify the dimension of the chain.");
391 if constexpr (Master_matrix::Option_list::is_z2) {
392 for (id_index
id : nonZeroRowIndices) {
393 column_[i++] = cellPool_->construct(
id);
396 operators_ = &(colSettings->operators);
397 for (
const auto& p : nonZeroRowIndices) {
398 column_[i] = cellPool_->construct(p.first);
399 column_[i++]->set_element(operators_->get_value(p.second));
402 std::make_heap(column_.begin(), column_.end(), cellPointerComp_);
405 template <
class Master_matrix>
406 template <
class Container_type,
class Row_container_type>
407 inline Heap_column<Master_matrix>::Heap_column(
409 const Container_type& nonZeroRowIndices,
410 dimension_type dimension,
411 Row_container_type* rowContainer,
412 Column_settings* colSettings)
413 : dim_opt(dimension),
415 if constexpr (Master_matrix::Option_list::is_z2) {
416 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : *std::prev(nonZeroRowIndices.end());
418 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : std::prev(nonZeroRowIndices.end())->first;
421 column_(nonZeroRowIndices.size(),
nullptr),
422 insertsSinceLastPrune_(0),
424 cellPool_(&(colSettings->cellConstructor))
427 if constexpr (Master_matrix::Option_list::is_z2) {
428 for (id_index
id : nonZeroRowIndices) {
429 column_[i++] = cellPool_->construct(
id);
432 operators_ = &(colSettings->operators);
433 for (
const auto& p : nonZeroRowIndices) {
434 column_[i] = cellPool_->construct(p.first);
435 column_[i++]->set_element(operators_->get_value(p.second));
438 std::make_heap(column_.begin(), column_.end(), cellPointerComp_);
441 template <
class Master_matrix>
442 template <
class Row_container_type>
443 inline Heap_column<Master_matrix>::Heap_column(
const Heap_column& column,
445 Row_container_type* rowContainer,
446 Column_settings* colSettings)
447 : dim_opt(static_cast<const dim_opt&>(column)),
448 chain_opt(static_cast<const chain_opt&>(column)),
449 column_(column.column_.size(), nullptr),
450 insertsSinceLastPrune_(0),
451 operators_(colSettings == nullptr ? column.operators_ : nullptr),
452 cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor))
454 if constexpr (!Master_matrix::Option_list::is_z2){
455 if (colSettings !=
nullptr) operators_ = &(colSettings->operators);
459 for (
const Cell* cell : column.column_) {
460 if constexpr (Master_matrix::Option_list::is_z2) {
461 column_[i++] = cellPool_->construct(cell->get_row_index());
463 column_[i] = cellPool_->construct(cell->get_row_index());
464 column_[i++]->set_element(cell->get_element());
470 template <
class Master_matrix>
471 inline Heap_column<Master_matrix>::~Heap_column()
473 for (
auto* cell : column_) {
474 cellPool_->destroy(cell);
478 template <
class Master_matrix>
479 inline std::vector<typename Heap_column<Master_matrix>::Field_element_type>
480 Heap_column<Master_matrix>::get_content(
int columnLength)
const
482 bool pivotLength = (columnLength < 0);
483 if (columnLength < 0 && column_.size() > 0)
484 columnLength = column_.front()->get_row_index() + 1;
485 else if (columnLength < 0)
486 return std::vector<Field_element_type>();
488 std::vector<Field_element_type> container(columnLength, 0);
489 for (
auto it = column_.begin(); it != column_.end(); ++it) {
490 if ((*it)->get_row_index() <
static_cast<id_index
>(columnLength)) {
491 if constexpr (Master_matrix::Option_list::is_z2) {
492 container[(*it)->get_row_index()] = !container[(*it)->get_row_index()];
494 operators_->add_inplace(container[(*it)->get_row_index()], (*it)->get_element());
500 while (!container.empty() && container.back() == 0u) container.pop_back();
506 template <
class Master_matrix>
507 inline bool Heap_column<Master_matrix>::is_non_zero(id_index rowIndex)
const
509 Field_element_type c(0);
510 for (
const Cell* cell : column_) {
511 if (cell->get_row_index() == rowIndex) {
512 if constexpr (Master_matrix::Option_list::is_z2) c = !c;
513 else operators_->add_inplace(c, cell->get_element());
516 return c != Field_operators::get_additive_identity();
519 template <
class Master_matrix>
520 inline bool Heap_column<Master_matrix>::is_empty()
522 Cell* pivot = _pop_pivot();
523 if (pivot !=
nullptr) {
524 column_.push_back(pivot);
525 std::push_heap(column_.begin(), column_.end(), cellPointerComp_);
531 template <
class Master_matrix>
532 inline std::size_t Heap_column<Master_matrix>::size()
const
534 return column_.size();
537 template <
class Master_matrix>
538 template <
class Map_type>
539 inline void Heap_column<Master_matrix>::reorder(
const Map_type& valueMap,
540 [[maybe_unused]] index columnIndex)
542 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
543 "Method not available for chain columns.");
546 Cell* pivot = _pop_pivot();
547 while (pivot !=
nullptr) {
548 pivot->set_row_index(valueMap.at(pivot->get_row_index()));
549 tempCol.push_back(pivot);
550 pivot = _pop_pivot();
552 column_.swap(tempCol);
553 std::make_heap(column_.begin(), column_.end(), cellPointerComp_);
555 insertsSinceLastPrune_ = 0;
558 template <
class Master_matrix>
559 inline void Heap_column<Master_matrix>::clear()
561 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
562 "Method not available for chain columns as a base element should not be empty.");
564 for (
auto* cell : column_) {
565 cellPool_->destroy(cell);
569 insertsSinceLastPrune_ = 0;
572 template <
class Master_matrix>
573 inline void Heap_column<Master_matrix>::clear(id_index rowIndex)
575 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
576 "Method not available for chain columns.");
579 Cell* pivot = _pop_pivot();
580 while (pivot !=
nullptr) {
581 if (pivot->get_row_index() != rowIndex){
582 tempCol.push_back(pivot);
584 cellPool_->destroy(pivot);
586 pivot = _pop_pivot();
588 column_.swap(tempCol);
590 insertsSinceLastPrune_ = 0;
593 template <
class Master_matrix>
594 inline typename Heap_column<Master_matrix>::id_index
595 Heap_column<Master_matrix>::get_pivot()
597 static_assert(Master_matrix::isNonBasic,
598 "Method not available for base columns.");
600 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
601 Cell* pivot = _pop_pivot();
602 if (pivot !=
nullptr) {
603 column_.push_back(pivot);
604 std::push_heap(column_.begin(), column_.end(), cellPointerComp_);
605 return pivot->get_row_index();
609 return chain_opt::get_pivot();
613 template <
class Master_matrix>
614 inline typename Heap_column<Master_matrix>::Field_element_type
615 Heap_column<Master_matrix>::get_pivot_value()
617 static_assert(Master_matrix::isNonBasic,
618 "Method not available for base columns.");
620 if constexpr (Master_matrix::Option_list::is_z2) {
623 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
624 Cell* pivot = _pop_pivot();
625 if (pivot !=
nullptr) {
626 column_.push_back(pivot);
627 std::push_heap(column_.begin(), column_.end(), cellPointerComp_);
628 return pivot->get_element();
632 Field_element_type sum(0);
633 if (chain_opt::get_pivot() ==
static_cast<id_index
>(-1))
return sum;
634 for (
const Cell* cell : column_) {
635 if (cell->get_row_index() == chain_opt::get_pivot()) operators_->add_inplace(sum, cell->get_element());
642 template <
class Master_matrix>
643 inline typename Heap_column<Master_matrix>::iterator
644 Heap_column<Master_matrix>::begin() noexcept
646 return column_.begin();
649 template <
class Master_matrix>
650 inline typename Heap_column<Master_matrix>::const_iterator
651 Heap_column<Master_matrix>::begin() const noexcept
653 return column_.begin();
656 template <
class Master_matrix>
657 inline typename Heap_column<Master_matrix>::iterator
658 Heap_column<Master_matrix>::end() noexcept
660 return column_.end();
663 template <
class Master_matrix>
664 inline typename Heap_column<Master_matrix>::const_iterator
665 Heap_column<Master_matrix>::end() const noexcept
667 return column_.end();
670 template <
class Master_matrix>
671 inline typename Heap_column<Master_matrix>::reverse_iterator
672 Heap_column<Master_matrix>::rbegin() noexcept
674 return column_.rbegin();
677 template <
class Master_matrix>
678 inline typename Heap_column<Master_matrix>::const_reverse_iterator
679 Heap_column<Master_matrix>::rbegin() const noexcept
681 return column_.rbegin();
684 template <
class Master_matrix>
685 inline typename Heap_column<Master_matrix>::reverse_iterator
686 Heap_column<Master_matrix>::rend() noexcept
688 return column_.rend();
691 template <
class Master_matrix>
692 inline typename Heap_column<Master_matrix>::const_reverse_iterator
693 Heap_column<Master_matrix>::rend() const noexcept
695 return column_.rend();
698 template <
class Master_matrix>
699 template <
class Cell_range>
700 inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::operator+=(
const Cell_range& column)
702 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Cell_range, Heap_column>),
703 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
705 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
706 "For chain columns, the given column cannot be constant.");
713 template <
class Master_matrix>
714 inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::operator+=(Heap_column& column)
716 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
719 chain_opt::swap_pivots(column);
720 dim_opt::swap_dimension(column);
729 template <
class Master_matrix>
730 inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::operator*=(
unsigned int v)
732 if constexpr (Master_matrix::Option_list::is_z2) {
734 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
735 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
741 Field_element_type val = operators_->get_value(v);
743 if (val == Field_operators::get_additive_identity()) {
744 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
745 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
752 if (val == Field_operators::get_multiplicative_identity())
return *
this;
754 for (Cell* cell : column_) {
755 operators_->multiply_inplace(cell->get_element(), val);
762 template <
class Master_matrix>
763 template <
class Cell_range>
764 inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::multiply_target_and_add(
765 const Field_element_type& val,
const Cell_range& column)
767 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Cell_range, Heap_column>),
768 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
770 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
771 "For chain columns, the given column cannot be constant.");
773 if constexpr (Master_matrix::Option_list::is_z2) {
781 _multiply_target_and_add(val, column);
787 template <
class Master_matrix>
788 inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::multiply_target_and_add(
789 const Field_element_type& val, Heap_column& column)
791 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
793 if constexpr (Master_matrix::Option_list::is_z2) {
796 chain_opt::swap_pivots(column);
797 dim_opt::swap_dimension(column);
800 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
803 if (_multiply_target_and_add(val, column)) {
804 chain_opt::swap_pivots(column);
805 dim_opt::swap_dimension(column);
809 if constexpr (Master_matrix::Option_list::is_z2) {
817 _multiply_target_and_add(val, column);
824 template <
class Master_matrix>
825 template <
class Cell_range>
826 inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::multiply_source_and_add(
827 const Cell_range& column,
const Field_element_type& val)
829 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Cell_range, Heap_column>),
830 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
832 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
833 "For chain columns, the given column cannot be constant.");
835 if constexpr (Master_matrix::Option_list::is_z2) {
840 _multiply_source_and_add(column, val);
846 template <
class Master_matrix>
847 inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::multiply_source_and_add(
848 Heap_column& column,
const Field_element_type& val)
850 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
852 if constexpr (Master_matrix::Option_list::is_z2) {
855 chain_opt::swap_pivots(column);
856 dim_opt::swap_dimension(column);
860 if (_multiply_source_and_add(column, val)) {
861 chain_opt::swap_pivots(column);
862 dim_opt::swap_dimension(column);
866 if constexpr (Master_matrix::Option_list::is_z2) {
871 _multiply_source_and_add(column, val);
878 template <
class Master_matrix>
879 inline Heap_column<Master_matrix>& Heap_column<Master_matrix>::operator=(
const Heap_column& other)
881 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignement not enabled with row access option.");
883 dim_opt::operator=(other);
884 chain_opt::operator=(other);
886 while (column_.size() > other.column_.size()) {
887 if (column_.back() !=
nullptr) cellPool_->destroy(column_.back());
891 column_.resize(other.column_.size(),
nullptr);
893 for (
const Cell* cell : other.column_) {
894 if (column_[i] !=
nullptr) {
895 cellPool_->destroy(column_[i]);
897 column_[i] = other.cellPool_->construct(cell->get_row_index());
898 if constexpr (!Master_matrix::Option_list::is_z2) {
899 column_[i]->set_element(cell->get_element());
903 insertsSinceLastPrune_ = other.insertsSinceLastPrune_;
904 operators_ = other.operators_;
905 cellPool_ = other.cellPool_;
910 template <
class Master_matrix>
911 inline std::size_t Heap_column<Master_matrix>::compute_hash_value()
914 return hash_column(*
this);
917 template <
class Master_matrix>
918 inline void Heap_column<Master_matrix>::_prune()
920 if (insertsSinceLastPrune_ == 0)
return;
923 Cell* pivot = _pop_pivot();
924 while (pivot !=
nullptr) {
925 tempCol.push_back(pivot);
926 pivot = _pop_pivot();
928 column_.swap(tempCol);
930 insertsSinceLastPrune_ = 0;
933 template <
class Master_matrix>
934 inline typename Heap_column<Master_matrix>::Cell*
935 Heap_column<Master_matrix>::_pop_pivot()
937 if (column_.empty()) {
941 Cell* pivot = column_.front();
942 std::pop_heap(column_.begin(), column_.end(), cellPointerComp_);
944 if constexpr (Master_matrix::Option_list::is_z2) {
945 while (!column_.empty() && column_.front()->get_row_index() == pivot->get_row_index()) {
946 std::pop_heap(column_.begin(), column_.end(), cellPointerComp_);
947 cellPool_->destroy(column_.back());
950 cellPool_->destroy(pivot);
951 if (column_.empty()) {
954 pivot = column_.front();
955 std::pop_heap(column_.begin(), column_.end(), cellPointerComp_);
959 while (!column_.empty() && column_.front()->get_row_index() == pivot->get_row_index()) {
960 operators_->add_inplace(pivot->get_element(), column_.front()->get_element());
961 std::pop_heap(column_.begin(), column_.end(), cellPointerComp_);
962 cellPool_->destroy(column_.back());
966 if (pivot->get_element() == Field_operators::get_additive_identity()) {
967 cellPool_->destroy(pivot);
975 template <
class Master_matrix>
976 template <
class Cell_range>
977 inline bool Heap_column<Master_matrix>::_add(
const Cell_range& column)
979 if (column.begin() == column.end())
return false;
980 if (column_.empty()) {
981 column_.resize(column.size());
983 for (
const Cell& cell : column) {
984 column_[i] = cellPool_->construct(cell.get_row_index());
985 if constexpr (!Master_matrix::Option_list::is_z2) {
986 column_[i]->set_element(cell.get_element());
990 insertsSinceLastPrune_ = column_.size();
994 Field_element_type pivotVal(1);
996 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type)
997 pivotVal = get_pivot_value();
999 for (
const Cell& cell : column) {
1000 ++insertsSinceLastPrune_;
1001 if constexpr (Master_matrix::Option_list::is_z2) {
1002 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1003 if (cell.get_row_index() == chain_opt::get_pivot()) pivotVal = !pivotVal;
1005 column_.push_back(cellPool_->construct(cell.get_row_index()));
1007 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1008 if (cell.get_row_index() == chain_opt::get_pivot()) operators_->add_inplace(pivotVal, cell.get_element());
1010 column_.push_back(cellPool_->construct(cell.get_row_index()));
1011 column_.back()->set_element(cell.get_element());
1013 std::push_heap(column_.begin(), column_.end(), cellPointerComp_);
1016 if (2 * insertsSinceLastPrune_ > column_.size()) _prune();
1018 if constexpr (Master_matrix::Option_list::is_z2)
1021 return pivotVal == Field_operators::get_additive_identity();
1024 template <
class Master_matrix>
1025 template <
class Cell_range>
1026 inline bool Heap_column<Master_matrix>::_multiply_target_and_add(
const Field_element_type& val,
1027 const Cell_range& column)
1030 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1031 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
1037 if (column_.empty()) {
1038 column_.resize(column.size());
1040 for (
const Cell& cell : column) {
1041 column_[i] = cellPool_->construct(cell.get_row_index());
1042 column_[i++]->set_element(cell.get_element());
1044 insertsSinceLastPrune_ = column_.size();
1048 Field_element_type pivotVal(0);
1050 for (Cell* cell : column_) {
1051 operators_->multiply_inplace(cell->get_element(), val);
1052 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1053 if (cell->get_row_index() == chain_opt::get_pivot()) operators_->add_inplace(pivotVal, cell->get_element());
1057 for (
const Cell& cell : column) {
1058 ++insertsSinceLastPrune_;
1059 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1060 if (cell.get_row_index() == chain_opt::get_pivot()) operators_->add_inplace(pivotVal, cell.get_element());
1062 column_.push_back(cellPool_->construct(cell.get_row_index()));
1063 column_.back()->set_element(cell.get_element());
1064 std::push_heap(column_.begin(), column_.end(), cellPointerComp_);
1067 if (2 * insertsSinceLastPrune_ > column_.size()) _prune();
1069 if constexpr (Master_matrix::Option_list::is_z2)
1072 return pivotVal == Field_operators::get_additive_identity();
1075 template <
class Master_matrix>
1076 template <
class Cell_range>
1077 inline bool Heap_column<Master_matrix>::_multiply_source_and_add(
const Cell_range& column,
1078 const Field_element_type& val)
1080 if (val == 0u || column.begin() == column.end()) {
1083 if (column_.empty()) {
1084 column_.resize(column.size());
1086 for (
const Cell& cell : column) {
1087 column_[i] = cellPool_->construct(cell.get_row_index());
1088 column_[i++]->set_element(cell.get_element());
1090 insertsSinceLastPrune_ = column_.size();
1094 Field_element_type pivotVal(1);
1096 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type)
1097 pivotVal = get_pivot_value();
1099 for (
const Cell& cell : column) {
1100 ++insertsSinceLastPrune_;
1101 column_.push_back(cellPool_->construct(cell.get_row_index()));
1102 column_.back()->set_element(cell.get_element());
1103 operators_->multiply_inplace(column_.back()->get_element(), val);
1104 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1105 if (cell.get_row_index() == chain_opt::get_pivot()){
1106 operators_->add_inplace(pivotVal, column_.back()->get_element());
1109 std::push_heap(column_.begin(), column_.end(), cellPointerComp_);
1112 if (2 * insertsSinceLastPrune_ > column_.size()) _prune();
1114 return pivotVal == 0u;
1128 template <
class Master_matrix>
1129 struct std::hash<
Gudhi::persistence_matrix::Heap_column<Master_matrix> >
1132 return column.compute_hash_value();
Contains the New_cell_constructor and Pool_cell_constructor structures.
Column class following the PersistenceMatrixColumn concept. Not compatible with row access.
Definition: heap_column.h:50
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