18#ifndef PM_UNORDERED_SET_COLUMN_H
19#define PM_UNORDERED_SET_COLUMN_H
27#include <boost/iterator/indirect_iterator.hpp>
28#if BOOST_VERSION >= 108100
29#include <boost/unordered/unordered_flat_set.hpp>
31#include <unordered_set>
37namespace persistence_matrix {
42struct EntryPointerHash {
43 size_t operator()(
const Entry* c)
const {
return std::hash<Entry>()(*c); }
47struct EntryPointerEq {
48 bool operator()(
const Entry* c1,
const Entry* c2)
const {
return *c1 == *c2; }
63template <
class Master_matrix>
69 using Master = Master_matrix;
70 using Index =
typename Master_matrix::Index;
71 using ID_index =
typename Master_matrix::ID_index;
72 using Dimension =
typename Master_matrix::Dimension;
73 using Field_element =
typename Master_matrix::Element;
74 using Entry =
typename Master_matrix::Matrix_entry;
75 using Column_settings =
typename Master_matrix::Column_settings;
78 using Field_operators =
typename Master_matrix::Field_operators;
79 using Entry_constructor =
typename Master_matrix::Entry_constructor;
81 struct EntryPointerComp {
82 bool operator()(
const Entry* c1,
const Entry* c2)
const {
return *c1 < *c2; }
85#if BOOST_VERSION >= 108100
86 using Column_support = boost::unordered_flat_set<Entry*, EntryPointerHash<Entry>, EntryPointerEq<Entry>>;
88 using Column_support = std::unordered_set<Entry*, EntryPointerHash<Entry>, EntryPointerEq<Entry>>;
92 using iterator = boost::indirect_iterator<typename Column_support::iterator>;
93 using const_iterator = boost::indirect_iterator<typename Column_support::const_iterator>;
96 template <
class Container =
typename Master_matrix::Boundary>
98 template <
class Container =
typename Master_matrix::Boundary,
class Row_container>
100 const Container& nonZeroRowIndices,
101 Row_container* rowContainer,
102 Column_settings* colSettings);
103 template <
class Container =
typename Master_matrix::Boundary>
104 Unordered_set_column(
const Container& nonZeroChainRowIndices, Dimension dimension, Column_settings* colSettings);
105 template <
class Container =
typename Master_matrix::Boundary,
class Row_container>
107 const Container& nonZeroChainRowIndices,
109 Row_container* rowContainer,
110 Column_settings* colSettings);
112 template <
class Row_container>
115 Row_container* rowContainer,
116 Column_settings* colSettings =
nullptr);
120 std::vector<Field_element> get_content(
int columnLength = -1)
const;
121 bool is_non_zero(ID_index rowIndex)
const;
122 bool is_empty()
const;
123 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()
const;
132 Field_element get_pivot_value()
const;
134 iterator begin()
noexcept;
135 const_iterator begin()
const noexcept;
136 iterator end()
noexcept;
137 const_iterator end()
const noexcept;
139 template <
class Entry_range>
146 template <
class Entry_range>
147 Unordered_set_column& multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
150 template <
class Entry_range>
151 Unordered_set_column& multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
154 void push_back(
const Entry& entry);
157 if (&c1 == &c2)
return true;
158 if (c1.column_.size() != c2.column_.size())
return false;
160 for (Entry* entry : c1.column_) {
161 auto it = c2.column_.find(entry);
162 if (it == c2.column_.end())
return false;
163 if constexpr (!Master_matrix::Option_list::is_z2)
164 if ((*it)->get_element() != entry->get_element())
return false;
170 if (&c1 == &c2)
return false;
172 using ID_index = Unordered_set_column<Master_matrix>::ID_index;
174 typename std::conditional<Master_matrix::Option_list::is_z2,
176 std::pair<ID_index, unsigned int>
179 auto it1 = c1.column_.begin();
180 auto it2 = c2.column_.begin();
181 std::set<Entry_rep> entries1, entries2;
182 while (it1 != c1.column_.end() && it2 != c2.column_.end()) {
183 if constexpr (Master_matrix::Option_list::is_z2) {
184 entries1.insert((*it1)->get_row_index());
185 entries2.insert((*it2)->get_row_index());
187 entries1.emplace((*it1)->get_row_index(), (*it1)->get_element());
188 entries2.emplace((*it2)->get_row_index(), (*it2)->get_element());
193 while (it1 != c1.column_.end()) {
194 if constexpr (Master_matrix::Option_list::is_z2) {
195 entries1.insert((*it1)->get_row_index());
197 entries1.emplace((*it1)->get_row_index(), (*it1)->get_element());
201 while (it2 != c2.column_.end()) {
202 if constexpr (Master_matrix::Option_list::is_z2) {
203 entries2.insert((*it2)->get_row_index());
205 entries2.emplace((*it2)->get_row_index(), (*it2)->get_element());
209 return entries1 < entries2;
222 col1.column_.swap(col2.column_);
223 std::swap(col1.operators_, col2.operators_);
224 std::swap(col1.entryPool_, col2.entryPool_);
232 Column_support column_;
233 Field_operators* operators_;
234 Entry_constructor* entryPool_;
236 void _delete_entry(
typename Column_support::iterator& it);
237 Entry* _insert_entry(
const Field_element& value, ID_index rowIndex);
238 void _insert_entry(ID_index rowIndex);
239 template <
class Entry_range>
240 bool _add(
const Entry_range& column);
241 template <
class Entry_range>
242 bool _multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
243 template <
class Entry_range>
244 bool _multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
245 template <
class Entry_range,
typename F1,
typename F2>
246 bool _generic_add(
const Entry_range& source, F1&& process_source, F2&& update_target);
249template <
class Master_matrix>
255 entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor))
257 if (operators_ ==
nullptr && entryPool_ ==
nullptr)
259 if constexpr (!Master_matrix::Option_list::is_z2) {
260 operators_ = &(colSettings->operators);
264template <
class Master_matrix>
265template <
class Container>
266inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Container& nonZeroRowIndices,
267 Column_settings* colSettings)
269 Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
271 column_(nonZeroRowIndices.size()),
273 entryPool_(&(colSettings->entryConstructor))
275 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
276 "Constructor not available for chain columns, please specify the dimension of the chain.");
278 if constexpr (Master_matrix::Option_list::is_z2) {
279 for (ID_index
id : nonZeroRowIndices) {
283 operators_ = &(colSettings->operators);
284 for (
const auto& p : nonZeroRowIndices) {
285 _insert_entry(operators_->get_value(p.second), p.first);
290template <
class Master_matrix>
291template <
class Container,
class Row_container>
292inline Unordered_set_column<Master_matrix>::Unordered_set_column(Index columnIndex,
293 const Container& nonZeroRowIndices,
294 Row_container* rowContainer,
295 Column_settings* colSettings)
296 : RA_opt(columnIndex, rowContainer),
297 Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
299 if constexpr (Master_matrix::Option_list::is_z2) {
300 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
301 ? Master_matrix::template get_null_value<ID_index>()
302 : *
std::prev(nonZeroRowIndices.end());
304 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
305 ? Master_matrix::template get_null_value<ID_index>()
306 :
std::prev(nonZeroRowIndices.end())->first;
309 column_(nonZeroRowIndices.size()),
311 entryPool_(&(colSettings->entryConstructor))
313 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
314 "Constructor not available for chain columns, please specify the dimension of the chain.");
316 if constexpr (Master_matrix::Option_list::is_z2) {
317 for (ID_index
id : nonZeroRowIndices) {
321 operators_ = &(colSettings->operators);
322 for (
const auto& p : nonZeroRowIndices) {
323 _insert_entry(operators_->get_value(p.second), p.first);
328template <
class Master_matrix>
329template <
class Container>
330inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Container& nonZeroRowIndices,
332 Column_settings* colSettings)
336 if constexpr (Master_matrix::Option_list::is_z2) {
337 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
338 ? Master_matrix::template get_null_value<ID_index>()
339 : *
std::prev(nonZeroRowIndices.end());
341 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
342 ? Master_matrix::template get_null_value<ID_index>()
343 :
std::prev(nonZeroRowIndices.end())->first;
346 column_(nonZeroRowIndices.size()),
348 entryPool_(&(colSettings->entryConstructor))
350 if constexpr (Master_matrix::Option_list::is_z2) {
351 for (ID_index
id : nonZeroRowIndices) {
355 operators_ = &(colSettings->operators);
356 for (
const auto& p : nonZeroRowIndices) {
357 _insert_entry(operators_->get_value(p.second), p.first);
362template <
class Master_matrix>
363template <
class Container,
class Row_container>
364inline Unordered_set_column<Master_matrix>::Unordered_set_column(Index columnIndex,
365 const Container& nonZeroRowIndices,
367 Row_container* rowContainer,
368 Column_settings* colSettings)
369 : RA_opt(columnIndex, rowContainer),
372 if constexpr (Master_matrix::Option_list::is_z2) {
373 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
374 ? Master_matrix::template get_null_value<ID_index>()
375 : *
std::prev(nonZeroRowIndices.end());
377 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
378 ? Master_matrix::template get_null_value<ID_index>()
379 :
std::prev(nonZeroRowIndices.end())->first;
382 column_(nonZeroRowIndices.size()),
384 entryPool_(&(colSettings->entryConstructor))
386 if constexpr (Master_matrix::Option_list::is_z2) {
387 for (ID_index
id : nonZeroRowIndices) {
391 operators_ = &(colSettings->operators);
392 for (
const auto& p : nonZeroRowIndices) {
393 _insert_entry(operators_->get_value(p.second), p.first);
398template <
class Master_matrix>
399inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Unordered_set_column& column,
400 Column_settings* colSettings)
402 Dim_opt(static_cast<const Dim_opt&>(column)),
403 Chain_opt(static_cast<const Chain_opt&>(column)),
404 column_(column.column_.bucket_count()),
405 operators_(colSettings == nullptr ? column.operators_ : nullptr),
406 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
408 static_assert(!Master_matrix::Option_list::has_row_access,
409 "Simple copy constructor not available when row access option enabled. Please specify the new column "
410 "index and the row container.");
412 if constexpr (!Master_matrix::Option_list::is_z2) {
413 if (colSettings !=
nullptr) operators_ = &(colSettings->operators);
416 for (
const Entry* entry : column.column_) {
417 if constexpr (Master_matrix::Option_list::is_z2) {
418 _insert_entry(entry->get_row_index());
420 _insert_entry(entry->get_element(), entry->get_row_index());
425template <
class Master_matrix>
426template <
class Row_container>
427inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Unordered_set_column& column,
429 Row_container* rowContainer,
430 Column_settings* colSettings)
431 : RA_opt(columnIndex, rowContainer),
432 Dim_opt(static_cast<const Dim_opt&>(column)),
433 Chain_opt(static_cast<const Chain_opt&>(column)),
434 column_(column.column_.bucket_count()),
435 operators_(colSettings == nullptr ? column.operators_ : nullptr),
436 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
438 if constexpr (!Master_matrix::Option_list::is_z2) {
439 if (colSettings !=
nullptr) operators_ = &(colSettings->operators);
442 for (
const Entry* entry : column.column_) {
443 if constexpr (Master_matrix::Option_list::is_z2) {
444 _insert_entry(entry->get_row_index());
446 _insert_entry(entry->get_element(), entry->get_row_index());
451template <
class Master_matrix>
452inline Unordered_set_column<Master_matrix>::Unordered_set_column(Unordered_set_column&& column) noexcept
453 : RA_opt(std::move(
static_cast<RA_opt&
>(column))),
454 Dim_opt(std::move(
static_cast<Dim_opt&
>(column))),
455 Chain_opt(std::move(
static_cast<Chain_opt&
>(column))),
456 column_(std::move(column.column_)),
457 operators_(std::exchange(column.operators_,
nullptr)),
458 entryPool_(std::exchange(column.entryPool_,
nullptr))
461template <
class Master_matrix>
462inline Unordered_set_column<Master_matrix>::~Unordered_set_column()
464 for (
auto* entry : column_) {
465 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
466 entryPool_->destroy(entry);
470template <
class Master_matrix>
471inline std::vector<typename Unordered_set_column<Master_matrix>::Field_element>
472Unordered_set_column<Master_matrix>::get_content(
int columnLength)
const
474 if (columnLength < 0 && column_.size() > 0)
475 columnLength = (*std::max_element(column_.begin(), column_.end(), EntryPointerComp()))->get_row_index() + 1;
476 else if (columnLength < 0)
477 return std::vector<Field_element>();
479 std::vector<Field_element> container(columnLength, 0);
480 for (
auto it = column_.begin(); it != column_.end(); ++it) {
481 if ((*it)->get_row_index() <
static_cast<ID_index
>(columnLength)) {
482 if constexpr (Master_matrix::Option_list::is_z2) {
483 container[(*it)->get_row_index()] = 1;
485 container[(*it)->get_row_index()] = (*it)->get_element();
492template <
class Master_matrix>
493inline bool Unordered_set_column<Master_matrix>::is_non_zero(ID_index rowIndex)
const
495 Entry entry(rowIndex);
496 return column_.find(&entry) != column_.end();
499template <
class Master_matrix>
500inline bool Unordered_set_column<Master_matrix>::is_empty()
const
502 return column_.empty();
505template <
class Master_matrix>
506inline std::size_t Unordered_set_column<Master_matrix>::size()
const
508 return column_.size();
511template <
class Master_matrix>
512template <
class Row_index_map>
513inline void Unordered_set_column<Master_matrix>::reorder(
const Row_index_map& valueMap,
514 [[maybe_unused]] Index columnIndex)
516 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
517 "Method not available for chain columns.");
519 Column_support newSet;
521 for (Entry* entry : column_) {
522 if constexpr (Master_matrix::Option_list::has_row_access) {
523 RA_opt::unlink(entry);
524 if (columnIndex != Master_matrix::template get_null_value<Index>()) entry->set_column_index(columnIndex);
526 entry->set_row_index(valueMap.at(entry->get_row_index()));
527 newSet.insert(entry);
528 if constexpr (Master_matrix::Option_list::has_row_access &&
529 Master_matrix::Option_list::has_intrusive_rows)
530 RA_opt::insert_entry(entry->get_row_index(), entry);
534 if constexpr (Master_matrix::Option_list::has_row_access && !Master_matrix::Option_list::has_intrusive_rows) {
535 for (Entry* entry : newSet) {
536 RA_opt::insert_entry(entry->get_row_index(), entry);
540 column_.swap(newSet);
543template <
class Master_matrix>
544inline void Unordered_set_column<Master_matrix>::clear()
546 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
547 "Method not available for chain columns as a base element should not be empty.");
549 for (
auto* entry : column_) {
550 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
551 entryPool_->destroy(entry);
557template <
class Master_matrix>
558inline void Unordered_set_column<Master_matrix>::clear(ID_index rowIndex)
560 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
561 "Method not available for chain columns.");
563 auto entry = entryPool_->construct(rowIndex);
564 auto it = column_.find(entry);
565 if (it != column_.end()) {
568 entryPool_->destroy(entry);
571template <
class Master_matrix>
572inline typename Unordered_set_column<Master_matrix>::ID_index Unordered_set_column<Master_matrix>::get_pivot()
const
574 static_assert(Master_matrix::isNonBasic,
575 "Method not available for base columns.");
577 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
578 if (column_.empty())
return Master_matrix::template get_null_value<ID_index>();
581 return (*std::max_element(column_.begin(), column_.end(), EntryPointerComp()))->get_row_index();
583 return Chain_opt::get_pivot();
587template <
class Master_matrix>
588inline typename Unordered_set_column<Master_matrix>::Field_element
589Unordered_set_column<Master_matrix>::get_pivot_value()
const
591 static_assert(Master_matrix::isNonBasic,
592 "Method not available for base columns.");
594 if constexpr (Master_matrix::Option_list::is_z2) {
597 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
598 if (column_.empty())
return 0;
599 return (*std::max_element(column_.begin(), column_.end(), EntryPointerComp()))->get_element();
601 if (Chain_opt::get_pivot() == Master_matrix::template get_null_value<ID_index>())
return Field_element();
602 for (
const Entry* entry : column_) {
603 if (entry->get_row_index() == Chain_opt::get_pivot())
return entry->get_element();
605 return Field_element();
610template <
class Master_matrix>
611inline typename Unordered_set_column<Master_matrix>::iterator Unordered_set_column<Master_matrix>::begin() noexcept
613 return column_.begin();
616template <
class Master_matrix>
617inline typename Unordered_set_column<Master_matrix>::const_iterator Unordered_set_column<Master_matrix>::begin()
620 return column_.begin();
623template <
class Master_matrix>
624inline typename Unordered_set_column<Master_matrix>::iterator Unordered_set_column<Master_matrix>::end() noexcept
626 return column_.end();
629template <
class Master_matrix>
630inline typename Unordered_set_column<Master_matrix>::const_iterator Unordered_set_column<Master_matrix>::end()
633 return column_.end();
636template <
class Master_matrix>
637template <
class Entry_range>
638inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::operator+=(
const Entry_range& column)
640 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Unordered_set_column>),
641 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
643 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
644 "For chain columns, the given column cannot be constant.");
651template <
class Master_matrix>
652inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::operator+=(
653 Unordered_set_column& column)
655 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
658 Chain_opt::swap_pivots(column);
659 Dim_opt::swap_dimension(column);
668template <
class Master_matrix>
669inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::operator*=(
unsigned int v)
671 if constexpr (Master_matrix::Option_list::is_z2) {
673 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
674 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
680 Field_element val = operators_->get_value(v);
682 if (val == Field_operators::get_additive_identity()) {
683 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
684 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
691 if (val == Field_operators::get_multiplicative_identity())
return *
this;
693 for (Entry* entry : column_) {
694 operators_->multiply_inplace(entry->get_element(), val);
695 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entry);
702template <
class Master_matrix>
703template <
class Entry_range>
704inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::multiply_target_and_add(
705 const Field_element& val,
706 const Entry_range& column)
708 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Unordered_set_column>),
709 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
711 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
712 "For chain columns, the given column cannot be constant.");
714 if constexpr (Master_matrix::Option_list::is_z2) {
722 _multiply_target_and_add(val, column);
728template <
class Master_matrix>
729inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::multiply_target_and_add(
730 const Field_element& val,
731 Unordered_set_column& column)
733 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
735 if constexpr (Master_matrix::Option_list::is_z2) {
738 Chain_opt::swap_pivots(column);
739 Dim_opt::swap_dimension(column);
742 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
745 if (_multiply_target_and_add(val, column)) {
746 Chain_opt::swap_pivots(column);
747 Dim_opt::swap_dimension(column);
751 if constexpr (Master_matrix::Option_list::is_z2) {
759 _multiply_target_and_add(val, column);
766template <
class Master_matrix>
767template <
class Entry_range>
768inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::multiply_source_and_add(
769 const Entry_range& column,
770 const Field_element& val)
772 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Unordered_set_column>),
773 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
775 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
776 "For chain columns, the given column cannot be constant.");
778 if constexpr (Master_matrix::Option_list::is_z2) {
783 _multiply_source_and_add(column, val);
789template <
class Master_matrix>
790inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::multiply_source_and_add(
791 Unordered_set_column& column,
792 const Field_element& val)
794 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
796 if constexpr (Master_matrix::Option_list::is_z2) {
799 Chain_opt::swap_pivots(column);
800 Dim_opt::swap_dimension(column);
804 if (_multiply_source_and_add(column, val)) {
805 Chain_opt::swap_pivots(column);
806 Dim_opt::swap_dimension(column);
810 if constexpr (Master_matrix::Option_list::is_z2) {
815 _multiply_source_and_add(column, val);
822template <
class Master_matrix>
823inline void Unordered_set_column<Master_matrix>::push_back(
const Entry& entry)
825 static_assert(Master_matrix::Option_list::is_of_boundary_type,
"`push_back` is not available for Chain matrices.");
827 GUDHI_CHECK(entry.get_row_index() > get_pivot(),
"The new row index has to be higher than the current pivot.");
829 if constexpr (Master_matrix::Option_list::is_z2) {
830 _insert_entry(entry.get_row_index());
832 _insert_entry(entry.get_element(), entry.get_row_index());
836template <
class Master_matrix>
837inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::operator=(
838 const Unordered_set_column& other)
840 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
842 Dim_opt::operator=(other);
843 Chain_opt::operator=(other);
845 for (
auto* entry : column_) {
846 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
847 entryPool_->destroy(entry);
851 operators_ = other.operators_;
852 entryPool_ = other.entryPool_;
854 for (
const Entry* entry : other.column_) {
855 if constexpr (Master_matrix::Option_list::is_z2) {
856 _insert_entry(entry->get_row_index());
858 _insert_entry(entry->get_element(), entry->get_row_index());
865template <
class Master_matrix>
866inline void Unordered_set_column<Master_matrix>::_delete_entry(
typename Column_support::iterator& it)
868 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(*it);
869 entryPool_->destroy(*it);
875template <
class Master_matrix>
876inline typename Unordered_set_column<Master_matrix>::Entry* Unordered_set_column<Master_matrix>::_insert_entry(
877 const Field_element& value,
880 if constexpr (Master_matrix::Option_list::has_row_access) {
881 Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex);
882 newEntry->set_element(value);
883 column_.insert(newEntry);
884 RA_opt::insert_entry(rowIndex, newEntry);
887 Entry* newEntry = entryPool_->construct(rowIndex);
888 newEntry->set_element(value);
889 column_.insert(newEntry);
894template <
class Master_matrix>
895inline void Unordered_set_column<Master_matrix>::_insert_entry(ID_index rowIndex)
897 if constexpr (Master_matrix::Option_list::has_row_access) {
898 Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex);
899 column_.insert(newEntry);
900 RA_opt::insert_entry(rowIndex, newEntry);
902 Entry* newEntry = entryPool_->construct(rowIndex);
903 column_.insert(newEntry);
907template <
class Master_matrix>
908template <
class Entry_range>
909inline bool Unordered_set_column<Master_matrix>::_add(
const Entry_range& column)
913 [&](
const Entry& oldEntry, Entry* newEntry) {
914 if constexpr (!Master_matrix::Option_list::is_z2) newEntry->set_element(oldEntry.get_element());
916 [&](Entry* targetEntry,
const Entry& sourceEntry) {
917 if constexpr (!Master_matrix::Option_list::is_z2)
918 operators_->add_inplace(targetEntry->get_element(), sourceEntry.get_element());
922template <
class Master_matrix>
923template <
class Entry_range>
924inline bool Unordered_set_column<Master_matrix>::_multiply_target_and_add(
const Field_element& val,
925 const Entry_range& column)
928 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
929 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
933 for (
const Entry& v : column) {
934 _insert_entry(v.get_element(), v.get_row_index());
946template <
class Master_matrix>
947template <
class Entry_range>
948inline bool Unordered_set_column<Master_matrix>::_multiply_source_and_add(
const Entry_range& column,
949 const Field_element& val)
957 [&](
const Entry& oldEntry, Entry* newEntry) {
958 newEntry->set_element(oldEntry.get_element());
959 operators_->multiply_inplace(newEntry->get_element(), val);
961 [&](Entry* targetEntry,
const Entry& sourceEntry) {
962 operators_->multiply_and_add_inplace_back(sourceEntry.get_element(), val, targetEntry->get_element());
966template <
class Master_matrix>
967template <
class Entry_range,
typename F1,
typename F2>
968inline bool Unordered_set_column<Master_matrix>::_generic_add(
const Entry_range& source,
972 bool pivotIsZeroed =
false;
974 for (
const Entry& entry : source) {
976 if constexpr (Master_matrix::Option_list::has_row_access) {
977 newEntry = entryPool_->construct(RA_opt::columnIndex_, entry.get_row_index());
979 newEntry = entryPool_->construct(entry.get_row_index());
981 auto res = column_.insert(newEntry);
983 process_source(entry, newEntry);
984 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::insert_entry(entry.get_row_index(), newEntry);
986 entryPool_->destroy(newEntry);
987 if constexpr (Master_matrix::Option_list::is_z2) {
988 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
989 if (entry.get_row_index() == Chain_opt::get_pivot()) pivotIsZeroed =
true;
991 _delete_entry(res.first);
993 update_target(*res.first, entry);
994 if ((*res.first)->get_element() == Field_operators::get_additive_identity()) {
995 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
996 if ((*res.first)->get_row_index() == Chain_opt::get_pivot()) pivotIsZeroed =
true;
998 _delete_entry(res.first);
1000 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(**res.first);
1006 return pivotIsZeroed;
1020template <
class Master_matrix>
1021struct std::hash<
Gudhi::persistence_matrix::Unordered_set_column<Master_matrix>> {
1024 std::size_t seed = 0;
1025 for (
const auto& entry : column) {
1026 seed ^= std::hash<unsigned int>()(entry.get_row_index() *
static_cast<unsigned int>(entry.get_element()));
Column class following the PersistenceMatrixColumn concept.
Definition: unordered_set_column.h:67
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
Row_access Row_access_option
If PersistenceMatrixOptions::has_row_access is true, then Row_access. Otherwise Dummy_row_access....
Definition: PersistenceMatrixColumn.h:28
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