18#ifndef PM_UNORDERED_SET_COLUMN_H
19#define PM_UNORDERED_SET_COLUMN_H
28#include <boost/iterator/indirect_iterator.hpp>
29#if BOOST_VERSION >= 108100
30#include <boost/unordered/unordered_flat_set.hpp>
32#include <unordered_set>
43struct EntryPointerHash {
44 size_t operator()(
const Entry* c)
const {
return std::hash<Entry>()(*c); }
48struct EntryPointerEq {
49 bool operator()(
const Entry* c1,
const Entry* c2)
const {
return *c1 == *c2; }
64template <
class Master_matrix>
65class Unordered_set_column :
public Master_matrix::Row_access_option,
66 public Master_matrix::Column_dimension_option,
67 public Master_matrix::Chain_column_option
70 using Master = Master_matrix;
71 using Index =
typename Master_matrix::Index;
72 using ID_index =
typename Master_matrix::ID_index;
73 using Dimension =
typename Master_matrix::Dimension;
74 using Field_element =
typename Master_matrix::Element;
75 using Entry =
typename Master_matrix::Matrix_entry;
76 using Column_settings =
typename Master_matrix::Column_settings;
79 using Field_operators =
typename Master_matrix::Field_operators;
80 using Entry_constructor =
typename Master_matrix::Entry_constructor;
82 struct EntryPointerComp {
83 bool operator()(
const Entry* c1,
const Entry* c2)
const {
return *c1 < *c2; }
86#if BOOST_VERSION >= 108100
87 using Column_support = boost::unordered_flat_set<Entry*, EntryPointerHash<Entry>, EntryPointerEq<Entry>>;
89 using Column_support = std::unordered_set<Entry*, EntryPointerHash<Entry>, EntryPointerEq<Entry>>;
93 using iterator = boost::indirect_iterator<typename Column_support::iterator>;
94 using const_iterator = boost::indirect_iterator<typename Column_support::const_iterator>;
95 using Content_range = std::vector<Entry>;
97 Unordered_set_column(Column_settings* colSettings =
nullptr);
98 template <
class Container =
typename Master_matrix::Boundary>
99 Unordered_set_column(
const Container& nonZeroRowIndices, Column_settings* colSettings);
100 template <
class Container =
typename Master_matrix::Boundary,
class Row_container>
101 Unordered_set_column(Index columnIndex,
102 const Container& nonZeroRowIndices,
103 Row_container* rowContainer,
104 Column_settings* colSettings);
105 template <
class Container =
typename Master_matrix::Boundary,
106 class = std::enable_if_t<!std::is_arithmetic_v<Container>>>
107 Unordered_set_column(
const Container& nonZeroRowIndices, Dimension dimension, Column_settings* colSettings);
108 template <
class Container =
typename Master_matrix::Boundary,
110 class = std::enable_if_t<!std::is_arithmetic_v<Container>>>
111 Unordered_set_column(Index columnIndex,
112 const Container& nonZeroRowIndices,
114 Row_container* rowContainer,
115 Column_settings* colSettings);
116 Unordered_set_column(ID_index idx, Dimension dimension, Column_settings* colSettings);
117 Unordered_set_column(ID_index idx,
120 Column_settings* colSettings);
121 template <
class Row_container>
122 Unordered_set_column(Index columnIndex,
125 Row_container* rowContainer,
126 Column_settings* colSettings);
127 template <
class Row_container>
128 Unordered_set_column(Index columnIndex,
132 Row_container* rowContainer,
133 Column_settings* colSettings);
134 Unordered_set_column(
const Unordered_set_column& column, Column_settings* colSettings =
nullptr);
135 template <
class Row_container>
136 Unordered_set_column(
const Unordered_set_column& column,
138 Row_container* rowContainer,
139 Column_settings* colSettings =
nullptr);
140 Unordered_set_column(Unordered_set_column&& column)
noexcept;
141 ~Unordered_set_column();
143 std::vector<Field_element> get_content(
int columnLength = -1)
const;
144 bool is_non_zero(ID_index rowIndex)
const;
145 [[nodiscard]]
bool is_empty()
const;
146 [[nodiscard]] std::size_t size()
const;
148 template <
class Row_index_map>
149 void reorder(
const Row_index_map& valueMap,
150 [[maybe_unused]] Index columnIndex = Master_matrix::template get_null_value<Index>());
152 void clear(ID_index rowIndex);
154 ID_index get_pivot()
const;
155 Field_element get_pivot_value()
const;
157 iterator begin()
noexcept;
158 const_iterator begin()
const noexcept;
159 iterator end()
noexcept;
160 const_iterator end()
const noexcept;
162 Content_range get_non_zero_content_range()
const;
164 template <
class Entry_range>
165 Unordered_set_column& operator+=(
const Entry_range& column);
166 Unordered_set_column& operator+=(Unordered_set_column& column);
168 Unordered_set_column& operator*=(
const Field_element& v);
171 template <
class Entry_range>
172 Unordered_set_column& multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
173 Unordered_set_column& multiply_target_and_add(
const Field_element& val, Unordered_set_column& column);
175 template <
class Entry_range>
176 Unordered_set_column& multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
177 Unordered_set_column& multiply_source_and_add(Unordered_set_column& column,
const Field_element& val);
179 void push_back(
const Entry& entry);
181 friend bool operator==(
const Unordered_set_column& c1,
const Unordered_set_column& c2)
183 if (&c1 == &c2)
return true;
184 if (c1.column_.size() != c2.column_.size())
return false;
186 for (Entry* entry : c1.column_) {
187 auto it = c2.column_.find(entry);
188 if (it == c2.column_.end())
return false;
189 if (Master_matrix::get_element(**it) != Master_matrix::get_element(*entry))
return false;
194 friend bool operator<(
const Unordered_set_column& c1,
const Unordered_set_column& c2)
196 if (&c1 == &c2)
return false;
198 auto comp = [](
const Entry* n1,
const Entry* n2) ->
bool {
199 Index r1 = Master_matrix::get_row_index(*n1);
200 Index r2 = Master_matrix::get_row_index(*n2);
201 Field_element e1 = Master_matrix::get_element(*n1);
202 Field_element e2 = Master_matrix::get_element(*n2);
204 if (r1 != r2)
return r1 < r2;
205 if (e1 != e2)
return e1 < e2;
210 std::set<Entry*,
decltype(comp)> entries1(comp), entries2(comp);
211 entries1.insert(c1.column_.begin(), c1.column_.end());
212 entries2.insert(c2.column_.begin(), c2.column_.end());
214 return std::lexicographical_compare(entries1.begin(), entries1.end(), entries2.begin(), entries2.end(), comp);
218 Unordered_set_column& operator=(
const Unordered_set_column& other);
219 Unordered_set_column& operator=(Unordered_set_column&& other)
noexcept;
221 friend void swap(Unordered_set_column& col1, Unordered_set_column& col2)
noexcept
223 swap(
static_cast<typename Master_matrix::Row_access_option&
>(col1),
224 static_cast<typename Master_matrix::Row_access_option&
>(col2));
225 swap(
static_cast<typename Master_matrix::Column_dimension_option&
>(col1),
226 static_cast<typename Master_matrix::Column_dimension_option&
>(col2));
227 swap(
static_cast<typename Master_matrix::Chain_column_option&
>(col1),
228 static_cast<typename Master_matrix::Chain_column_option&
>(col2));
229 col1.column_.swap(col2.column_);
230 std::swap(col1.operators_, col2.operators_);
231 std::swap(col1.entryPool_, col2.entryPool_);
235 using RA_opt =
typename Master_matrix::Row_access_option;
236 using Dim_opt =
typename Master_matrix::Column_dimension_option;
237 using Chain_opt =
typename Master_matrix::Chain_column_option;
239 Column_support column_;
240 Field_operators
const* operators_;
241 Entry_constructor* entryPool_;
243 void _delete_entry(
typename Column_support::iterator& it);
244 Entry* _insert_entry(ID_index rowIndex,
const Field_element& value);
245 template <
class Entry_range>
246 bool _add(
const Entry_range& column);
247 template <
class Entry_range>
248 bool _multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
249 template <
class Entry_range>
250 bool _multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
251 template <
class Entry_range,
typename F1,
typename F2>
252 bool _generic_add(
const Entry_range& source, F1&& process_source, F2&& update_target);
255template <
class Master_matrix>
256inline Unordered_set_column<Master_matrix>::Unordered_set_column(Column_settings* colSettings)
260 operators_(Master_matrix::get_operator_ptr(colSettings)),
261 entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor))
264template <
class Master_matrix>
265template <
class Container>
266inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Container& nonZeroRowIndices,
267 Column_settings* colSettings)
268 : Unordered_set_column(nonZeroRowIndices,
269 nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1,
272 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
273 "Constructor not available for chain columns, please specify the dimension of the chain.");
276template <
class Master_matrix>
277template <
class Container,
class Row_container>
278inline Unordered_set_column<Master_matrix>::Unordered_set_column(Index columnIndex,
279 const Container& nonZeroRowIndices,
280 Row_container* rowContainer,
281 Column_settings* colSettings)
282 : Unordered_set_column(columnIndex,
284 nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1,
288 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
289 "Constructor not available for chain columns, please specify the dimension of the chain.");
292template <
class Master_matrix>
293template <
class Container,
class>
294inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Container& nonZeroRowIndices,
296 Column_settings* colSettings)
299 Chain_opt(nonZeroRowIndices.begin() == nonZeroRowIndices.end()
300 ? Master_matrix::template get_null_value<ID_index>()
301 : Master_matrix::get_row_index(*std::prev(nonZeroRowIndices.end()))),
302 column_(nonZeroRowIndices.size()),
303 operators_(Master_matrix::get_operator_ptr(colSettings)),
304 entryPool_(&(colSettings->entryConstructor))
306 for (
const auto&
id : nonZeroRowIndices) {
307 _insert_entry(Master_matrix::get_row_index(
id),
308 Master_matrix::get_coefficient_value(Master_matrix::get_element(
id), operators_));
312template <
class Master_matrix>
313template <
class Container,
class Row_container,
class>
314inline Unordered_set_column<Master_matrix>::Unordered_set_column(Index columnIndex,
315 const Container& nonZeroRowIndices,
317 Row_container* rowContainer,
318 Column_settings* colSettings)
319 : RA_opt(columnIndex, rowContainer),
321 Chain_opt(nonZeroRowIndices.begin() == nonZeroRowIndices.end()
322 ? Master_matrix::template get_null_value<ID_index>()
323 : Master_matrix::get_row_index(*std::prev(nonZeroRowIndices.end()))),
324 column_(nonZeroRowIndices.size()),
325 operators_(Master_matrix::get_operator_ptr(colSettings)),
326 entryPool_(&(colSettings->entryConstructor))
328 for (
const auto&
id : nonZeroRowIndices) {
329 _insert_entry(Master_matrix::get_row_index(
id),
330 Master_matrix::get_coefficient_value(Master_matrix::get_element(
id), operators_));
334template <
class Master_matrix>
335inline Unordered_set_column<Master_matrix>::Unordered_set_column(ID_index idx,
337 Column_settings* colSettings)
343 entryPool_(&(colSettings->entryConstructor))
345 static_assert(Master_matrix::Option_list::is_z2,
346 "Constructor not available for Zp != Z2. Please specify the coefficient.");
347 _insert_entry(idx, 1);
350template <
class Master_matrix>
351inline Unordered_set_column<Master_matrix>::Unordered_set_column(ID_index idx,
354 Column_settings* colSettings)
359 operators_(&(colSettings->operators)),
360 entryPool_(&(colSettings->entryConstructor))
362 static_assert(!Master_matrix::Option_list::is_z2,
363 "Constructor not available for Zp == Z2. Please do not specify any coefficient.");
364 _insert_entry(idx, operators_->get_value(e));
367template <
class Master_matrix>
368template <
class Row_container>
369inline Unordered_set_column<Master_matrix>::Unordered_set_column(Index columnIndex,
372 Row_container* rowContainer,
373 Column_settings* colSettings)
374 : RA_opt(columnIndex, rowContainer),
379 entryPool_(&(colSettings->entryConstructor))
381 static_assert(Master_matrix::Option_list::is_z2,
382 "Constructor not available for Zp != Z2. Please specify the coefficient.");
383 _insert_entry(idx, 1);
386template <
class Master_matrix>
387template <
class Row_container>
388inline Unordered_set_column<Master_matrix>::Unordered_set_column(Index columnIndex,
392 Row_container* rowContainer,
393 Column_settings* colSettings)
394 : RA_opt(columnIndex, rowContainer),
398 operators_(&(colSettings->operators)),
399 entryPool_(&(colSettings->entryConstructor))
401 static_assert(!Master_matrix::Option_list::is_z2,
402 "Constructor not available for Zp == Z2. Please do not specify any coefficient.");
403 _insert_entry(idx, operators_->get_value(e));
406template <
class Master_matrix>
407inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Unordered_set_column& column,
408 Column_settings* colSettings)
410 Dim_opt(static_cast<const Dim_opt&>(column)),
411 Chain_opt(static_cast<const Chain_opt&>(column)),
412 column_(column.column_.bucket_count()),
413 operators_(colSettings == nullptr ? column.operators_ : Master_matrix::get_operator_ptr(colSettings)),
414 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
416 static_assert(!Master_matrix::Option_list::has_row_access,
417 "Simple copy constructor not available when row access option enabled. Please specify the new column "
418 "index and the row container.");
420 for (
const Entry* entry : column.column_) {
421 _insert_entry(entry->get_row_index(), entry->get_element());
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_ : Master_matrix::get_operator_ptr(colSettings)),
436 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
438 for (
const Entry* entry : column.column_) {
439 _insert_entry(entry->get_row_index(), entry->get_element());
443template <
class Master_matrix>
444inline Unordered_set_column<Master_matrix>::Unordered_set_column(
Unordered_set_column&& column) noexcept
445 : RA_opt(std::move(
static_cast<RA_opt&
>(column))),
446 Dim_opt(std::move(
static_cast<Dim_opt&
>(column))),
447 Chain_opt(std::move(
static_cast<Chain_opt&
>(column))),
448 column_(std::move(column.column_)),
449 operators_(std::exchange(column.operators_,
nullptr)),
450 entryPool_(std::exchange(column.entryPool_,
nullptr))
453template <
class Master_matrix>
454inline Unordered_set_column<Master_matrix>::~Unordered_set_column()
456 for (
auto* entry : column_) {
457 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
458 entryPool_->destroy(entry);
462template <
class Master_matrix>
463inline std::vector<typename Unordered_set_column<Master_matrix>::Field_element>
464Unordered_set_column<Master_matrix>::get_content(
int columnLength)
const
466 if (columnLength < 0 && column_.size() > 0)
467 columnLength = (*std::max_element(column_.begin(), column_.end(), EntryPointerComp()))->get_row_index() + 1;
468 else if (columnLength < 0)
469 return std::vector<Field_element>();
471 std::vector<Field_element> container(columnLength, 0);
472 for (
auto it = column_.begin(); it != column_.end(); ++it) {
473 if ((*it)->get_row_index() <
static_cast<ID_index
>(columnLength)) {
474 container[(*it)->get_row_index()] = Master_matrix::get_element(**it);
480template <
class Master_matrix>
481inline bool Unordered_set_column<Master_matrix>::is_non_zero(ID_index rowIndex)
const
483 Entry entry(rowIndex);
484 return column_.find(&entry) != column_.end();
487template <
class Master_matrix>
488inline bool Unordered_set_column<Master_matrix>::is_empty()
const
490 return column_.empty();
493template <
class Master_matrix>
494inline std::size_t Unordered_set_column<Master_matrix>::size()
const
496 return column_.size();
499template <
class Master_matrix>
500template <
class Row_index_map>
501inline void Unordered_set_column<Master_matrix>::reorder(
const Row_index_map& valueMap,
502 [[maybe_unused]] Index columnIndex)
504 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
505 "Method not available for chain columns.");
507 Column_support newSet;
509 for (
Entry* entry : column_) {
510 if constexpr (Master_matrix::Option_list::has_row_access) {
511 RA_opt::unlink(entry);
512 if (columnIndex != Master_matrix::template get_null_value<Index>()) entry->set_column_index(columnIndex);
514 entry->set_row_index(valueMap.at(entry->get_row_index()));
515 newSet.insert(entry);
516 if constexpr (Master_matrix::Option_list::has_row_access &&
517 Master_matrix::Option_list::has_intrusive_rows)
518 RA_opt::insert_entry(entry->get_row_index(), entry);
522 if constexpr (Master_matrix::Option_list::has_row_access && !Master_matrix::Option_list::has_intrusive_rows) {
523 for (
Entry* entry : newSet) {
524 RA_opt::insert_entry(entry->get_row_index(), entry);
528 column_.swap(newSet);
531template <
class Master_matrix>
532inline void Unordered_set_column<Master_matrix>::clear()
534 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
535 "Method not available for chain columns as a base element should not be empty.");
537 for (
auto* entry : column_) {
538 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
539 entryPool_->destroy(entry);
545template <
class Master_matrix>
546inline void Unordered_set_column<Master_matrix>::clear(ID_index rowIndex)
548 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
549 "Method not available for chain columns.");
551 auto entry = entryPool_->construct(rowIndex);
552 auto it = column_.find(entry);
553 if (it != column_.end()) {
556 entryPool_->destroy(entry);
559template <
class Master_matrix>
560inline typename Unordered_set_column<Master_matrix>::ID_index Unordered_set_column<Master_matrix>::get_pivot()
const
562 static_assert(Master_matrix::isNonBasic,
563 "Method not available for base columns.");
565 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
566 if (column_.empty())
return Master_matrix::template get_null_value<ID_index>();
569 return (*std::max_element(column_.begin(), column_.end(), EntryPointerComp()))->get_row_index();
571 return Chain_opt::_get_pivot();
575template <
class Master_matrix>
576inline typename Unordered_set_column<Master_matrix>::Field_element
577Unordered_set_column<Master_matrix>::get_pivot_value()
const
579 static_assert(Master_matrix::isNonBasic,
580 "Method not available for base columns.");
582 if constexpr (Master_matrix::Option_list::is_z2) {
585 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
586 if (column_.empty())
return 0;
587 return (*std::max_element(column_.begin(), column_.end(), EntryPointerComp()))->get_element();
589 if (Chain_opt::_get_pivot() == Master_matrix::template get_null_value<ID_index>())
return Field_element();
590 for (
const Entry* entry : column_) {
591 if (entry->get_row_index() == Chain_opt::_get_pivot())
return entry->get_element();
593 return Field_element();
598template <
class Master_matrix>
599inline typename Unordered_set_column<Master_matrix>::iterator Unordered_set_column<Master_matrix>::begin() noexcept
601 return column_.begin();
604template <
class Master_matrix>
605inline typename Unordered_set_column<Master_matrix>::const_iterator Unordered_set_column<Master_matrix>::begin()
608 return column_.begin();
611template <
class Master_matrix>
612inline typename Unordered_set_column<Master_matrix>::iterator Unordered_set_column<Master_matrix>::end() noexcept
614 return column_.end();
617template <
class Master_matrix>
618inline typename Unordered_set_column<Master_matrix>::const_iterator Unordered_set_column<Master_matrix>::end()
621 return column_.end();
624template <
class Master_matrix>
625inline typename Unordered_set_column<Master_matrix>::Content_range
626Unordered_set_column<Master_matrix>::get_non_zero_content_range()
const
628 Content_range res(column_.size());
630 for (
const auto& entry : column_) res[i++] = *entry;
631 std::sort(res.begin(), res.end());
635template <
class Master_matrix>
636template <
class Entry_range>
639 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Unordered_set_column>),
640 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
642 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
643 "For chain columns, the given column cannot be constant.");
650template <
class Master_matrix>
654 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
657 Chain_opt::_swap_pivots(column);
658 Dim_opt::_swap_dimension(column);
667template <
class Master_matrix>
670 Field_element val = Master_matrix::get_coefficient_value(v, operators_);
672 if (val == Field_operators::get_additive_identity()) {
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.");
681 if (val == Field_operators::get_multiplicative_identity())
return *
this;
685 if constexpr (!Master_matrix::Option_list::is_z2) {
686 for (
Entry* entry : column_) {
687 operators_->multiply_inplace(entry->get_element(), val);
688 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entry);
695template <
class Master_matrix>
696template <
class Entry_range>
698 const Field_element& val,
699 const Entry_range& column)
701 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Unordered_set_column>),
702 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
704 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
705 "For chain columns, the given column cannot be constant.");
707 _multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column);
712template <
class Master_matrix>
714 const Field_element& val,
717 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
719 if (_multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column)) {
720 Chain_opt::_swap_pivots(column);
721 Dim_opt::_swap_dimension(column);
724 _multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column);
730template <
class Master_matrix>
731template <
class Entry_range>
733 const Entry_range& column,
734 const Field_element& val)
736 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Unordered_set_column>),
737 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
739 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
740 "For chain columns, the given column cannot be constant.");
742 _multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_));
747template <
class Master_matrix>
750 const Field_element& val)
752 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
754 if (_multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_))) {
755 Chain_opt::_swap_pivots(column);
756 Dim_opt::_swap_dimension(column);
759 _multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_));
765template <
class Master_matrix>
766inline void Unordered_set_column<Master_matrix>::push_back(
const Entry& entry)
768 static_assert(Master_matrix::Option_list::is_of_boundary_type,
"`push_back` is not available for Chain matrices.");
770 GUDHI_CHECK(entry.get_row_index() > get_pivot(),
771 std::invalid_argument(
"The new row index has to be higher than the current pivot."));
773 _insert_entry(entry.get_row_index(), entry.get_element());
776template <
class Master_matrix>
780 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
783 if (
this == &other)
return *
this;
785 Dim_opt::operator=(other);
786 Chain_opt::operator=(other);
788 for (
auto* entry : column_) {
789 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
790 entryPool_->destroy(entry);
794 operators_ = other.operators_;
795 entryPool_ = other.entryPool_;
797 for (
const Entry* entry : other.column_) {
798 _insert_entry(entry->get_row_index(), entry->get_element());
804template <
class Master_matrix>
808 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
811 if (&column_ == &(other.column_))
return *
this;
813 Dim_opt::operator=(std::move(other));
814 Chain_opt::operator=(std::move(other));
816 for (
auto* entry : column_) {
817 if (entry !=
nullptr) entryPool_->destroy(entry);
820 column_ = std::move(other.column_);
821 operators_ = std::exchange(other.operators_,
nullptr);
822 entryPool_ = std::exchange(other.entryPool_,
nullptr);
827template <
class Master_matrix>
828inline void Unordered_set_column<Master_matrix>::_delete_entry(
typename Column_support::iterator& it)
830 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(*it);
831 entryPool_->destroy(*it);
837template <
class Master_matrix>
838inline typename Unordered_set_column<Master_matrix>::Entry* Unordered_set_column<Master_matrix>::_insert_entry(
840 const Field_element& value)
843 if constexpr (Master_matrix::Option_list::has_row_access) {
844 newEntry = entryPool_->construct(RA_opt::get_column_index(), rowIndex);
846 newEntry = entryPool_->construct(rowIndex);
848 newEntry->set_element(value);
849 column_.insert(newEntry);
850 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::insert_entry(rowIndex, newEntry);
854template <
class Master_matrix>
855template <
class Entry_range>
856inline bool Unordered_set_column<Master_matrix>::_add(
const Entry_range& column)
858 if (column.begin() == column.end())
return false;
859 if (column_.empty()) {
860 for (
const Entry& entry : column) {
861 _insert_entry(entry.get_row_index(), entry.get_element());
869 newEntry->set_element(oldEntry.get_element());
871 [&](
Entry* targetEntry,
const Entry& sourceEntry) {
872 if constexpr (!Master_matrix::Option_list::is_z2)
873 operators_->add_inplace(targetEntry->get_element(), sourceEntry.get_element());
877template <
class Master_matrix>
878template <
class Entry_range>
879inline bool Unordered_set_column<Master_matrix>::_multiply_target_and_add(
const Field_element& val,
880 const Entry_range& column)
885 return _add(column) || val == Field_operators::get_additive_identity();
888template <
class Master_matrix>
889template <
class Entry_range>
890inline bool Unordered_set_column<Master_matrix>::_multiply_source_and_add(
const Entry_range& column,
891 const Field_element& val)
893 if (val == Field_operators::get_additive_identity() || column.begin() == column.end()) {
897 if (val == Field_operators::get_multiplicative_identity()) {
903 if constexpr (!Master_matrix::Option_list::is_z2) {
907 newEntry->set_element(oldEntry.get_element());
908 operators_->multiply_inplace(newEntry->get_element(), val);
910 [&](
Entry* targetEntry,
const Entry& sourceEntry) {
911 operators_->multiply_and_add_inplace_back(sourceEntry.get_element(), val, targetEntry->get_element());
918template <
class Master_matrix>
919template <
class Entry_range,
typename F1,
typename F2>
920inline bool Unordered_set_column<Master_matrix>::_generic_add(
const Entry_range& source,
921 [[maybe_unused]] F1&& process_source,
922 [[maybe_unused]] F2&& update_target)
924 bool pivotIsZeroed =
false;
926 for (
const Entry& entry : source) {
928 if constexpr (Master_matrix::Option_list::has_row_access) {
929 newEntry = entryPool_->construct(RA_opt::get_column_index(), entry.get_row_index());
931 newEntry = entryPool_->construct(entry.get_row_index());
933 auto res = column_.insert(newEntry);
935 std::forward<F1>(process_source)(entry, newEntry);
936 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::insert_entry(entry.get_row_index(), newEntry);
938 entryPool_->destroy(newEntry);
939 if constexpr (Master_matrix::Option_list::is_z2) {
940 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
941 if (entry.get_row_index() == Chain_opt::_get_pivot()) pivotIsZeroed =
true;
943 _delete_entry(res.first);
945 std::forward<F2>(update_target)(*res.first, entry);
946 if ((*res.first)->get_element() == Field_operators::get_additive_identity()) {
947 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
948 if ((*res.first)->get_row_index() == Chain_opt::_get_pivot()) pivotIsZeroed =
true;
950 _delete_entry(res.first);
952 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(**res.first);
958 return pivotIsZeroed;
972template <
class Master_matrix>
973struct std::hash<
Gudhi::persistence_matrix::Unordered_set_column<Master_matrix>> {
977 std::size_t seed = 0;
978 for (
const auto& entry : column) {
979 seed ^= std::hash<unsigned int>()(entry.get_row_index() *
static_cast<unsigned int>(entry.get_element()));
Matrix entry class. Stores by default only the row index it belongs to, but can also store its column...
Definition entry_types.h:163
Column class following the PersistenceMatrixColumn concept.
Definition unordered_set_column.h:68
Contains different versions of Gudhi::persistence_matrix::Entry factories.
Persistence matrix namespace.
Definition FieldOperators.h:18
Gudhi namespace.
Definition SimplicialComplexForAlpha.h:14