18#ifndef PM_INTRUSIVE_SET_COLUMN_H
19#define PM_INTRUSIVE_SET_COLUMN_H
26#include <boost/intrusive/set.hpp>
28#include <gudhi/Debug_utils.h>
46template <
class Master_matrix>
47class Intrusive_set_column :
public Master_matrix::Row_access_option,
48 public Master_matrix::Column_dimension_option,
49 public Master_matrix::Chain_column_option
52 using Master = Master_matrix;
53 using Index =
typename Master_matrix::Index;
54 using ID_index =
typename Master_matrix::ID_index;
55 using Dimension =
typename Master_matrix::Dimension;
56 using Field_element =
typename Master_matrix::Element;
57 using Entry =
typename Master_matrix::Matrix_entry;
58 using Column_settings =
typename Master_matrix::Column_settings;
61 using Field_operators =
typename Master_matrix::Field_operators;
62 using Column_support =
63 boost::intrusive::set<Entry,
64 boost::intrusive::constant_time_size<false>,
65 boost::intrusive::base_hook<typename Master_matrix::Base_hook_matrix_set_column> >;
66 using Entry_constructor =
typename Master_matrix::Entry_constructor;
69 using iterator =
typename Column_support::iterator;
70 using const_iterator =
typename Column_support::const_iterator;
71 using reverse_iterator =
typename Column_support::reverse_iterator;
72 using const_reverse_iterator =
typename Column_support::const_reverse_iterator;
73 using Content_range =
const Column_support&;
75 Intrusive_set_column(Column_settings* colSettings =
nullptr);
76 template <
class Container =
typename Master_matrix::Boundary>
77 Intrusive_set_column(
const Container& nonZeroRowIndices, Column_settings* colSettings);
78 template <
class Container =
typename Master_matrix::Boundary,
class Row_container>
79 Intrusive_set_column(Index columnIndex,
80 const Container& nonZeroRowIndices,
81 Row_container* rowContainer,
82 Column_settings* colSettings);
83 template <
class Container =
typename Master_matrix::Boundary,
84 class = std::enable_if_t<!std::is_arithmetic_v<Container> > >
85 Intrusive_set_column(
const Container& nonZeroRowIndices, Dimension dimension, Column_settings* colSettings);
86 template <
class Container =
typename Master_matrix::Boundary,
88 class = std::enable_if_t<!std::is_arithmetic_v<Container> > >
89 Intrusive_set_column(Index columnIndex,
90 const Container& nonZeroRowIndices,
92 Row_container* rowContainer,
93 Column_settings* colSettings);
94 Intrusive_set_column(ID_index idx, Dimension dimension, Column_settings* colSettings);
95 Intrusive_set_column(ID_index idx,
98 Column_settings* colSettings);
99 template <
class Row_container>
100 Intrusive_set_column(Index columnIndex,
103 Row_container* rowContainer,
104 Column_settings* colSettings);
105 template <
class Row_container>
106 Intrusive_set_column(Index columnIndex,
110 Row_container* rowContainer,
111 Column_settings* colSettings);
112 Intrusive_set_column(
const Intrusive_set_column& column, Column_settings* colSettings =
nullptr);
113 template <
class Row_container>
114 Intrusive_set_column(
const Intrusive_set_column& column,
116 Row_container* rowContainer,
117 Column_settings* colSettings =
nullptr);
118 Intrusive_set_column(Intrusive_set_column&& column)
noexcept;
119 ~Intrusive_set_column();
121 std::vector<Field_element> get_content(
int columnLength = -1)
const;
122 bool is_non_zero(ID_index rowIndex)
const;
123 [[nodiscard]]
bool is_empty()
const;
124 [[nodiscard]] std::size_t size()
const;
126 template <
class Row_index_map>
127 void reorder(
const Row_index_map& valueMap,
128 [[maybe_unused]] Index columnIndex = Master_matrix::template get_null_value<Index>());
130 void clear(ID_index rowIndex);
132 ID_index get_pivot()
const;
133 Field_element get_pivot_value()
const;
135 iterator begin()
noexcept;
136 const_iterator begin()
const noexcept;
137 iterator end()
noexcept;
138 const_iterator end()
const noexcept;
139 reverse_iterator rbegin()
noexcept;
140 const_reverse_iterator rbegin()
const noexcept;
141 reverse_iterator rend()
noexcept;
142 const_reverse_iterator rend()
const noexcept;
144 Content_range get_non_zero_content_range()
const;
146 template <
class Entry_range>
147 Intrusive_set_column& operator+=(
const Entry_range& column);
148 Intrusive_set_column& operator+=(Intrusive_set_column& column);
150 Intrusive_set_column& operator*=(
const Field_element& v);
153 template <
class Entry_range>
154 Intrusive_set_column& multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
155 Intrusive_set_column& multiply_target_and_add(
const Field_element& val, Intrusive_set_column& column);
157 template <
class Entry_range>
158 Intrusive_set_column& multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
159 Intrusive_set_column& multiply_source_and_add(Intrusive_set_column& column,
const Field_element& val);
161 void push_back(
const Entry& entry);
163 friend bool operator==(
const Intrusive_set_column& c1,
const Intrusive_set_column& c2)
165 if (&c1 == &c2)
return true;
167 return std::equal(c1.column_.begin(),
171 [](
const Entry& e1,
const Entry& e2) {
172 return e1.get_row_index() == e2.get_row_index() && e1.get_element() == e2.get_element();
176 friend bool operator<(
const Intrusive_set_column& c1,
const Intrusive_set_column& c2)
178 if (&c1 == &c2)
return false;
180 return std::lexicographical_compare(c1.column_.begin(),
184 [](
const Entry& e1,
const Entry& e2) {
185 if (e1.get_row_index() != e2.get_row_index())
186 return e1.get_row_index() < e2.get_row_index();
187 if (e1.get_element() != e2.get_element())
188 return e1.get_element() < e2.get_element();
194 Intrusive_set_column& operator=(
const Intrusive_set_column& other);
195 Intrusive_set_column& operator=(Intrusive_set_column&& other)
noexcept;
197 friend void swap(Intrusive_set_column& col1, Intrusive_set_column& col2)
noexcept
199 swap(
static_cast<typename Master_matrix::Row_access_option&
>(col1),
200 static_cast<typename Master_matrix::Row_access_option&
>(col2));
201 swap(
static_cast<typename Master_matrix::Column_dimension_option&
>(col1),
202 static_cast<typename Master_matrix::Column_dimension_option&
>(col2));
203 swap(
static_cast<typename Master_matrix::Chain_column_option&
>(col1),
204 static_cast<typename Master_matrix::Chain_column_option&
>(col2));
205 col1.column_.swap(col2.column_);
206 std::swap(col1.operators_, col2.operators_);
207 std::swap(col1.entryPool_, col2.entryPool_);
211 using RA_opt =
typename Master_matrix::Row_access_option;
212 using Dim_opt =
typename Master_matrix::Column_dimension_option;
213 using Chain_opt =
typename Master_matrix::Chain_column_option;
217 New_cloner(Entry_constructor* entryPool) : entryPool_(entryPool) {};
219 Entry* operator()(
const Entry& clone_this) {
return entryPool_->construct(clone_this); }
221 Entry_constructor* entryPool_;
225 struct Delete_disposer {
226 Delete_disposer() =
default;
227 Delete_disposer(Intrusive_set_column* col) : col_(col) {};
229 void operator()(Entry* delete_this)
231 if constexpr (Master_matrix::Option_list::has_row_access) col_->unlink(delete_this);
232 col_->entryPool_->destroy(delete_this);
235 Intrusive_set_column* col_;
238 Column_support column_;
239 Field_operators
const* operators_;
240 Entry_constructor* entryPool_;
242 template <
class Column,
class Entry_iterator,
typename F1,
typename F2,
typename F3,
typename F4>
243 friend void _generic_merge_entry_to_column(Column& targetColumn,
244 Entry_iterator& itSource,
245 typename Column::Column_support::iterator& itTarget,
250 bool& pivotIsZeroed);
251 template <
class Column,
class Entry_range,
typename F1,
typename F2,
typename F3,
typename F4,
typename F5>
252 friend bool _generic_add_to_column(
const Entry_range& source,
253 Column& targetColumn,
259 template <
class Column,
class Entry_range>
260 friend bool _add_to_column(
const Entry_range& source, Column& targetColumn);
261 template <
class Column,
class Entry_range>
262 friend bool _multiply_target_and_add_to_column(
const typename Column::Field_element& val,
263 const Entry_range& source,
264 Column& targetColumn);
265 template <
class Column,
class Entry_range>
266 friend bool _multiply_source_and_add_to_column(
const typename Column::Field_element& val,
267 const Entry_range& source,
268 Column& targetColumn);
270 void _delete_entry(iterator& it);
271 Entry* _insert_entry(
const iterator& position, ID_index rowIndex,
const Field_element& value);
272 template <
class Entry_range>
273 bool _add(
const Entry_range& column);
274 template <
class Entry_range>
275 bool _multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
276 template <
class Entry_range>
277 bool _multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
280template <
class Master_matrix>
281inline Intrusive_set_column<Master_matrix>::Intrusive_set_column(Column_settings* colSettings)
285 operators_(Master_matrix::get_operator_ptr(colSettings)),
286 entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor))
289template <
class Master_matrix>
290template <
class Container>
291inline Intrusive_set_column<Master_matrix>::Intrusive_set_column(
const Container& nonZeroRowIndices,
292 Column_settings* colSettings)
293 : Intrusive_set_column(nonZeroRowIndices,
294 nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1,
297 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
298 "Constructor not available for chain columns, please specify the dimension of the chain.");
301template <
class Master_matrix>
302template <
class Container,
class Row_container>
303inline Intrusive_set_column<Master_matrix>::Intrusive_set_column(Index columnIndex,
304 const Container& nonZeroRowIndices,
305 Row_container* rowContainer,
306 Column_settings* colSettings)
307 : Intrusive_set_column(columnIndex,
309 nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1,
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.");
317template <
class Master_matrix>
318template <
class Container,
class>
319inline Intrusive_set_column<Master_matrix>::Intrusive_set_column(
const Container& nonZeroRowIndices,
321 Column_settings* colSettings)
324 Chain_opt(nonZeroRowIndices.begin() == nonZeroRowIndices.end()
325 ? Master_matrix::template get_null_value<ID_index>()
326 : Master_matrix::get_row_index(*std::prev(nonZeroRowIndices.end()))),
327 operators_(Master_matrix::get_operator_ptr(colSettings)),
328 entryPool_(&(colSettings->entryConstructor))
330 for (
const auto&
id : nonZeroRowIndices) {
331 _insert_entry(column_.end(),
332 Master_matrix::get_row_index(
id),
333 Master_matrix::get_coefficient_value(Master_matrix::get_element(
id), operators_));
337template <
class Master_matrix>
338template <
class Container,
class Row_container,
class>
339inline Intrusive_set_column<Master_matrix>::Intrusive_set_column(Index columnIndex,
340 const Container& nonZeroRowIndices,
342 Row_container* rowContainer,
343 Column_settings* colSettings)
344 : RA_opt(columnIndex, rowContainer),
346 Chain_opt(nonZeroRowIndices.begin() == nonZeroRowIndices.end()
347 ? Master_matrix::template get_null_value<ID_index>()
348 : Master_matrix::get_row_index(*std::prev(nonZeroRowIndices.end()))),
349 operators_(Master_matrix::get_operator_ptr(colSettings)),
350 entryPool_(&(colSettings->entryConstructor))
352 for (
const auto&
id : nonZeroRowIndices) {
353 _insert_entry(column_.end(),
354 Master_matrix::get_row_index(
id),
355 Master_matrix::get_coefficient_value(Master_matrix::get_element(
id), operators_));
359template <
class Master_matrix>
360inline Intrusive_set_column<Master_matrix>::Intrusive_set_column(ID_index idx,
362 Column_settings* colSettings)
363 : RA_opt(), Dim_opt(dimension), Chain_opt(idx), operators_(nullptr), entryPool_(&(colSettings->entryConstructor))
365 static_assert(Master_matrix::Option_list::is_z2,
366 "Constructor not available for Zp != Z2. Please specify the coefficient.");
367 _insert_entry(column_.end(), idx, 1);
370template <
class Master_matrix>
371inline Intrusive_set_column<Master_matrix>::Intrusive_set_column(ID_index idx,
374 Column_settings* colSettings)
378 operators_(&(colSettings->operators)),
379 entryPool_(&(colSettings->entryConstructor))
381 static_assert(!Master_matrix::Option_list::is_z2,
382 "Constructor not available for Zp == Z2. Please do not specify any coefficient.");
383 _insert_entry(column_.end(), idx, operators_->get_value(e));
386template <
class Master_matrix>
387template <
class Row_container>
388inline Intrusive_set_column<Master_matrix>::Intrusive_set_column(Index columnIndex,
391 Row_container* rowContainer,
392 Column_settings* colSettings)
393 : RA_opt(columnIndex, rowContainer),
397 entryPool_(&(colSettings->entryConstructor))
399 static_assert(Master_matrix::Option_list::is_z2,
400 "Constructor not available for Zp != Z2. Please specify the coefficient.");
401 _insert_entry(column_.end(), idx, 1);
404template <
class Master_matrix>
405template <
class Row_container>
406inline Intrusive_set_column<Master_matrix>::Intrusive_set_column(Index columnIndex,
410 Row_container* rowContainer,
411 Column_settings* colSettings)
412 : RA_opt(columnIndex, rowContainer),
415 operators_(&(colSettings->operators)),
416 entryPool_(&(colSettings->entryConstructor))
418 static_assert(!Master_matrix::Option_list::is_z2,
419 "Constructor not available for Zp == Z2. Please do not specify any coefficient.");
420 _insert_entry(column_.end(), idx, operators_->get_value(e));
423template <
class Master_matrix>
424inline Intrusive_set_column<Master_matrix>::Intrusive_set_column(
const Intrusive_set_column& column,
425 Column_settings* colSettings)
427 Dim_opt(static_cast<const Dim_opt&>(column)),
428 Chain_opt(static_cast<const Chain_opt&>(column)),
429 operators_(colSettings == nullptr ? column.operators_ : Master_matrix::get_operator_ptr(colSettings)),
430 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
432 static_assert(!Master_matrix::Option_list::has_row_access,
433 "Simple copy constructor not available when row access option enabled. Please specify the new column "
434 "index and the row container.");
436 column_.clone_from(column.column_, New_cloner(entryPool_), Delete_disposer(
this));
439template <
class Master_matrix>
440template <
class Row_container>
441inline Intrusive_set_column<Master_matrix>::Intrusive_set_column(
const Intrusive_set_column& column,
443 Row_container* rowContainer,
444 Column_settings* colSettings)
445 : RA_opt(columnIndex, rowContainer),
446 Dim_opt(static_cast<const Dim_opt&>(column)),
447 Chain_opt(static_cast<const Chain_opt&>(column)),
448 operators_(colSettings == nullptr ? column.operators_ : Master_matrix::get_operator_ptr(colSettings)),
449 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
451 for (
const Entry& entry : column.column_) {
452 _insert_entry(column_.end(), entry.get_row_index(), entry.get_element());
456template <
class Master_matrix>
457inline Intrusive_set_column<Master_matrix>::Intrusive_set_column(
Intrusive_set_column&& column) noexcept
458 : RA_opt(std::move(
static_cast<RA_opt&
>(column))),
459 Dim_opt(std::move(
static_cast<Dim_opt&
>(column))),
460 Chain_opt(std::move(
static_cast<Chain_opt&
>(column))),
461 column_(std::move(column.column_)),
462 operators_(std::exchange(column.operators_,
nullptr)),
463 entryPool_(std::exchange(column.entryPool_,
nullptr))
466template <
class Master_matrix>
467inline Intrusive_set_column<Master_matrix>::~Intrusive_set_column()
469 column_.clear_and_dispose(Delete_disposer(
this));
472template <
class Master_matrix>
473inline std::vector<typename Intrusive_set_column<Master_matrix>::Field_element>
474Intrusive_set_column<Master_matrix>::get_content(
int columnLength)
const
476 if (columnLength < 0 && column_.size() > 0)
477 columnLength = column_.rbegin()->get_row_index() + 1;
478 else if (columnLength < 0)
479 return std::vector<Field_element>();
481 std::vector<Field_element> container(columnLength);
482 for (
auto it = column_.begin(); it != column_.end() && it->get_row_index() <
static_cast<ID_index
>(columnLength);
484 container[it->get_row_index()] = Master_matrix::get_element(*it);
489template <
class Master_matrix>
490inline bool Intrusive_set_column<Master_matrix>::is_non_zero(ID_index rowIndex)
const
492 return column_.find(
Entry(rowIndex)) != column_.end();
495template <
class Master_matrix>
496inline bool Intrusive_set_column<Master_matrix>::is_empty()
const
498 return column_.empty();
501template <
class Master_matrix>
502inline std::size_t Intrusive_set_column<Master_matrix>::size()
const
504 return column_.size();
507template <
class Master_matrix>
508template <
class Row_index_map>
509inline void Intrusive_set_column<Master_matrix>::reorder(
const Row_index_map& valueMap,
510 [[maybe_unused]] Index columnIndex)
512 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
513 "Method not available for chain columns.");
515 Column_support newSet;
517 if constexpr (Master_matrix::Option_list::has_row_access) {
518 for (
auto it = column_.begin(); it != column_.end();) {
519 Entry* newEntry = entryPool_->construct(
520 columnIndex == Master_matrix::template get_null_value<Index>() ? RA_opt::get_column_index() : columnIndex,
521 valueMap.at(it->get_row_index()));
522 newEntry->set_element(it->get_element());
523 newSet.insert(newSet.end(), *newEntry);
525 if constexpr (Master_matrix::Option_list::has_intrusive_rows)
526 RA_opt::insert_entry(newEntry->get_row_index(), newEntry);
530 if constexpr (!Master_matrix::Option_list::has_intrusive_rows) {
531 for (
Entry& entry : newSet) {
532 RA_opt::insert_entry(entry.get_row_index(), &entry);
536 for (
auto it = column_.begin(); it != column_.end();) {
537 Entry* newEntry = entryPool_->construct(valueMap.at(it->get_row_index()));
538 newEntry->set_element(it->get_element());
539 newSet.insert(newSet.end(), *newEntry);
544 column_.swap(newSet);
547template <
class Master_matrix>
548inline void Intrusive_set_column<Master_matrix>::clear()
550 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
551 "Method not available for chain columns as a base element should not be empty.");
553 column_.clear_and_dispose(Delete_disposer(
this));
556template <
class Master_matrix>
557inline void Intrusive_set_column<Master_matrix>::clear(ID_index rowIndex)
559 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
560 "Method not available for chain columns.");
562 auto it = column_.find(
Entry(rowIndex));
563 if (it != column_.end()) {
568template <
class Master_matrix>
569inline typename Intrusive_set_column<Master_matrix>::ID_index Intrusive_set_column<Master_matrix>::get_pivot()
const
571 static_assert(Master_matrix::isNonBasic,
572 "Method not available for base columns.");
574 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
575 if (column_.empty())
return Master_matrix::template get_null_value<ID_index>();
576 return column_.rbegin()->get_row_index();
578 return Chain_opt::_get_pivot();
582template <
class Master_matrix>
583inline typename Intrusive_set_column<Master_matrix>::Field_element
584Intrusive_set_column<Master_matrix>::get_pivot_value()
const
586 static_assert(Master_matrix::isNonBasic,
587 "Method not available for base columns.");
589 if constexpr (Master_matrix::Option_list::is_z2) {
592 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
593 if (column_.empty())
return 0;
594 return column_.rbegin()->get_element();
596 if (Chain_opt::_get_pivot() == Master_matrix::template get_null_value<ID_index>())
return 0;
597 auto it = column_.find(
Entry(Chain_opt::_get_pivot()));
600 std::logic_error(
"Intrusive_set_column::get_pivot_value - Pivot not found only if the column was misused."));
601 return it->get_element();
606template <
class Master_matrix>
607inline typename Intrusive_set_column<Master_matrix>::iterator Intrusive_set_column<Master_matrix>::begin() noexcept
609 return column_.begin();
612template <
class Master_matrix>
613inline typename Intrusive_set_column<Master_matrix>::const_iterator Intrusive_set_column<Master_matrix>::begin()
616 return column_.begin();
619template <
class Master_matrix>
620inline typename Intrusive_set_column<Master_matrix>::iterator Intrusive_set_column<Master_matrix>::end() noexcept
622 return column_.end();
625template <
class Master_matrix>
626inline typename Intrusive_set_column<Master_matrix>::const_iterator Intrusive_set_column<Master_matrix>::end()
629 return column_.end();
632template <
class Master_matrix>
633inline typename Intrusive_set_column<Master_matrix>::reverse_iterator
634Intrusive_set_column<Master_matrix>::rbegin() noexcept
636 return column_.rbegin();
639template <
class Master_matrix>
640inline typename Intrusive_set_column<Master_matrix>::const_reverse_iterator
641Intrusive_set_column<Master_matrix>::rbegin() const noexcept
643 return column_.rbegin();
646template <
class Master_matrix>
647inline typename Intrusive_set_column<Master_matrix>::reverse_iterator
648Intrusive_set_column<Master_matrix>::rend() noexcept
650 return column_.rend();
653template <
class Master_matrix>
654inline typename Intrusive_set_column<Master_matrix>::const_reverse_iterator Intrusive_set_column<Master_matrix>::rend()
657 return column_.rend();
660template <
class Master_matrix>
661inline typename Intrusive_set_column<Master_matrix>::Content_range
662Intrusive_set_column<Master_matrix>::get_non_zero_content_range()
const
667template <
class Master_matrix>
668template <
class Entry_range>
671 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Intrusive_set_column>),
672 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
674 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
675 "For chain columns, the given column cannot be constant.");
682template <
class Master_matrix>
686 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
689 Chain_opt::_swap_pivots(column);
690 Dim_opt::_swap_dimension(column);
699template <
class Master_matrix>
702 Field_element val = Master_matrix::get_coefficient_value(v, operators_);
704 if (val == Field_operators::get_additive_identity()) {
705 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
706 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
713 if (val == Field_operators::get_multiplicative_identity())
return *
this;
717 if constexpr (!Master_matrix::Option_list::is_z2) {
718 for (
Entry& entry : column_) {
719 operators_->multiply_inplace(entry.get_element(), val);
720 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(entry);
727template <
class Master_matrix>
728template <
class Entry_range>
730 const Field_element& val,
731 const Entry_range& column)
733 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Intrusive_set_column>),
734 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
736 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
737 "For chain columns, the given column cannot be constant.");
739 _multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column);
744template <
class Master_matrix>
746 const Field_element& val,
749 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
751 if (_multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column)) {
752 Chain_opt::_swap_pivots(column);
753 Dim_opt::_swap_dimension(column);
756 _multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column);
762template <
class Master_matrix>
763template <
class Entry_range>
765 const Entry_range& column,
766 const Field_element& val)
768 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Intrusive_set_column>),
769 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
771 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
772 "For chain columns, the given column cannot be constant.");
774 _multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_));
779template <
class Master_matrix>
782 const Field_element& val)
784 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
786 if (_multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_))) {
787 Chain_opt::_swap_pivots(column);
788 Dim_opt::_swap_dimension(column);
791 _multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_));
797template <
class Master_matrix>
798inline void Intrusive_set_column<Master_matrix>::push_back(
const Entry& entry)
800 static_assert(Master_matrix::Option_list::is_of_boundary_type,
"`push_back` is not available for Chain matrices.");
802 GUDHI_CHECK(entry.get_row_index() > get_pivot(),
803 std::invalid_argument(
"The new row index has to be higher than the current pivot."));
805 _insert_entry(column_.end(), entry.get_row_index(), entry.get_element());
808template <
class Master_matrix>
812 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
815 if (
this == &other)
return *
this;
817 Dim_opt::operator=(other);
818 Chain_opt::operator=(other);
821 column_.clear_and_dispose(Delete_disposer(
this));
822 operators_ = other.operators_;
823 entryPool_ = other.entryPool_;
824 column_.clone_from(other.column_, New_cloner(entryPool_), Delete_disposer(
this));
829template <
class Master_matrix>
833 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
836 if (&column_ == &(other.column_))
return *
this;
838 Dim_opt::operator=(std::move(other));
839 Chain_opt::operator=(std::move(other));
841 column_.clear_and_dispose(Delete_disposer(
this));
843 operators_ = std::exchange(other.operators_,
nullptr);
844 entryPool_ = std::exchange(other.entryPool_,
nullptr);
845 column_ = std::move(other.column_);
850template <
class Master_matrix>
851inline void Intrusive_set_column<Master_matrix>::_delete_entry(iterator& it)
853 it = column_.erase_and_dispose(it, Delete_disposer(
this));
856template <
class Master_matrix>
857inline typename Intrusive_set_column<Master_matrix>::Entry* Intrusive_set_column<Master_matrix>::_insert_entry(
858 const iterator& position,
860 const Field_element& value)
863 if constexpr (Master_matrix::Option_list::has_row_access) {
864 newEntry = entryPool_->construct(RA_opt::get_column_index(), rowIndex);
866 newEntry = entryPool_->construct(rowIndex);
868 newEntry->set_element(value);
869 column_.insert(position, *newEntry);
870 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::insert_entry(rowIndex, newEntry);
874template <
class Master_matrix>
875template <
class Entry_range>
876inline bool Intrusive_set_column<Master_matrix>::_add(
const Entry_range& column)
878 return _add_to_column(column, *
this);
881template <
class Master_matrix>
882template <
class Entry_range>
883inline bool Intrusive_set_column<Master_matrix>::_multiply_target_and_add(
const Field_element& val,
884 const Entry_range& column)
886 return _multiply_target_and_add_to_column(val, column, *
this);
889template <
class Master_matrix>
890template <
class Entry_range>
891inline bool Intrusive_set_column<Master_matrix>::_multiply_source_and_add(
const Entry_range& column,
892 const Field_element& val)
894 return _multiply_source_and_add_to_column(val, column, *
this);
908template <
class Master_matrix>
909struct std::hash<
Gudhi::persistence_matrix::Intrusive_set_column<Master_matrix> > {
912 return Gudhi::persistence_matrix::hash_column(column);
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 intrusive_set_column.h:50
Contains helper methods for column addition and column hasher.
Contains different versions of Gudhi::persistence_matrix::Entry factories.
Persistence matrix namespace.
Definition FieldOperators.h:18
Gudhi namespace.
Definition SimplicialComplexForAlpha.h:14