18#ifndef PM_INTRUSIVE_LIST_COLUMN_H
19#define PM_INTRUSIVE_LIST_COLUMN_H
27#include <boost/intrusive/list.hpp>
46template <
class Master_matrix>
47class Intrusive_list_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::list<Entry,
64 boost::intrusive::constant_time_size<false>,
65 boost::intrusive::base_hook<typename Master_matrix::Base_hook_matrix_list_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_list_column(Column_settings* colSettings =
nullptr);
76 template <
class Container =
typename Master_matrix::Boundary>
77 Intrusive_list_column(
const Container& nonZeroRowIndices, Column_settings* colSettings);
78 template <
class Container =
typename Master_matrix::Boundary,
class Row_container>
79 Intrusive_list_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_list_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_list_column(Index columnIndex,
90 const Container& nonZeroRowIndices,
92 Row_container* rowContainer,
93 Column_settings* colSettings);
94 Intrusive_list_column(ID_index idx, Dimension dimension, Column_settings* colSettings);
95 Intrusive_list_column(ID_index idx,
98 Column_settings* colSettings);
99 template <
class Row_container>
100 Intrusive_list_column(Index columnIndex,
103 Row_container* rowContainer,
104 Column_settings* colSettings);
105 template <
class Row_container>
106 Intrusive_list_column(Index columnIndex,
110 Row_container* rowContainer,
111 Column_settings* colSettings);
112 template <
class Row_container>
113 Intrusive_list_column(
const Intrusive_list_column& column,
115 Row_container* rowContainer,
116 Column_settings* colSettings =
nullptr);
117 Intrusive_list_column(
const Intrusive_list_column& column, Column_settings* colSettings =
nullptr);
118 Intrusive_list_column(Intrusive_list_column&& column)
noexcept;
119 ~Intrusive_list_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_list_column& operator+=(
const Entry_range& column);
148 Intrusive_list_column& operator+=(Intrusive_list_column& column);
150 Intrusive_list_column& operator*=(
const Field_element& val);
153 template <
class Entry_range>
154 Intrusive_list_column& multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
155 Intrusive_list_column& multiply_target_and_add(
const Field_element& val, Intrusive_list_column& column);
157 template <
class Entry_range>
158 Intrusive_list_column& multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
159 Intrusive_list_column& multiply_source_and_add(Intrusive_list_column& column,
const Field_element& val);
161 void push_back(
const Entry& entry);
163 friend bool operator==(
const Intrusive_list_column& c1,
const Intrusive_list_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_list_column& c1,
const Intrusive_list_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_list_column& operator=(
const Intrusive_list_column& other);
195 Intrusive_list_column& operator=(Intrusive_list_column&& other)
noexcept;
197 friend void swap(Intrusive_list_column& col1, Intrusive_list_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_list_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_list_column* col_;
238 Field_operators
const* operators_;
239 Entry_constructor* entryPool_;
240 Column_support column_;
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_list_column<Master_matrix>::Intrusive_list_column(Column_settings* colSettings)
285 operators_(Master_matrix::get_operator_ptr(colSettings)),
286 entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor)),
290template <
class Master_matrix>
291template <
class Container>
292inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(
const Container& nonZeroRowIndices,
293 Column_settings* colSettings)
294 : Intrusive_list_column(nonZeroRowIndices,
295 nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1,
298 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
299 "Constructor not available for chain columns, please specify the dimension of the chain.");
302template <
class Master_matrix>
303template <
class Container,
class Row_container>
304inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(Index columnIndex,
305 const Container& nonZeroRowIndices,
306 Row_container* rowContainer,
307 Column_settings* colSettings)
308 : Intrusive_list_column(columnIndex,
310 nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1,
314 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
315 "Constructor not available for chain columns, please specify the dimension of the chain.");
318template <
class Master_matrix>
319template <
class Container,
class>
320inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(
const Container& nonZeroRowIndices,
322 Column_settings* colSettings)
325 Chain_opt(nonZeroRowIndices.begin() == nonZeroRowIndices.end()
326 ? Master_matrix::template get_null_value<ID_index>()
327 : Master_matrix::get_row_index(*std::prev(nonZeroRowIndices.end()))),
328 operators_(Master_matrix::get_operator_ptr(colSettings)),
329 entryPool_(&(colSettings->entryConstructor)),
332 for (
const auto&
id : nonZeroRowIndices) {
333 _insert_entry(column_.end(),
334 Master_matrix::get_row_index(
id),
335 Master_matrix::get_coefficient_value(Master_matrix::get_element(
id), operators_));
339template <
class Master_matrix>
340template <
class Container,
class Row_container,
class>
341inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(Index columnIndex,
342 const Container& nonZeroRowIndices,
344 Row_container* rowContainer,
345 Column_settings* colSettings)
346 : RA_opt(columnIndex, rowContainer),
348 Chain_opt(nonZeroRowIndices.begin() == nonZeroRowIndices.end()
349 ? Master_matrix::template get_null_value<ID_index>()
350 : Master_matrix::get_row_index(*std::prev(nonZeroRowIndices.end()))),
351 operators_(Master_matrix::get_operator_ptr(colSettings)),
352 entryPool_(&(colSettings->entryConstructor)),
355 for (
const auto&
id : nonZeroRowIndices) {
356 _insert_entry(column_.end(),
357 Master_matrix::get_row_index(
id),
358 Master_matrix::get_coefficient_value(Master_matrix::get_element(
id), operators_));
362template <
class Master_matrix>
363inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(ID_index idx,
365 Column_settings* colSettings)
370 entryPool_(&(colSettings->entryConstructor)),
373 static_assert(Master_matrix::Option_list::is_z2,
374 "Constructor not available for Zp != Z2. Please specify the coefficient.");
375 _insert_entry(column_.end(), idx, 1);
378template <
class Master_matrix>
379inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(ID_index idx,
382 Column_settings* colSettings)
386 operators_(&(colSettings->operators)),
387 entryPool_(&(colSettings->entryConstructor)),
390 static_assert(!Master_matrix::Option_list::is_z2,
391 "Constructor not available for Zp == Z2. Please do not specify any coefficient.");
392 _insert_entry(column_.end(), idx, operators_->get_value(e));
395template <
class Master_matrix>
396template <
class Row_container>
397inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(Index columnIndex,
400 Row_container* rowContainer,
401 Column_settings* colSettings)
402 : RA_opt(columnIndex, rowContainer),
406 entryPool_(&(colSettings->entryConstructor)),
409 static_assert(Master_matrix::Option_list::is_z2,
410 "Constructor not available for Zp != Z2. Please specify the coefficient.");
411 _insert_entry(column_.end(), idx, 1);
414template <
class Master_matrix>
415template <
class Row_container>
416inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(Index columnIndex,
420 Row_container* rowContainer,
421 Column_settings* colSettings)
422 : RA_opt(columnIndex, rowContainer),
425 operators_(&(colSettings->operators)),
426 entryPool_(&(colSettings->entryConstructor)),
429 static_assert(!Master_matrix::Option_list::is_z2,
430 "Constructor not available for Zp == Z2. Please do not specify any coefficient.");
431 _insert_entry(column_.end(), idx, operators_->get_value(e));
434template <
class Master_matrix>
435inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(
const Intrusive_list_column& column,
436 Column_settings* colSettings)
438 Dim_opt(static_cast<const Dim_opt&>(column)),
439 Chain_opt(static_cast<const Chain_opt&>(column)),
440 operators_(colSettings == nullptr ? column.operators_ : Master_matrix::get_operator_ptr(colSettings)),
441 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)),
444 static_assert(!Master_matrix::Option_list::has_row_access,
445 "Simple copy constructor not available when row access option enabled. Please specify the new column "
446 "index and the row container.");
448 column_.clone_from(column.column_, New_cloner(entryPool_), Delete_disposer(
this));
451template <
class Master_matrix>
452template <
class Row_container>
453inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(
const Intrusive_list_column& column,
455 Row_container* rowContainer,
456 Column_settings* colSettings)
457 : RA_opt(columnIndex, rowContainer),
458 Dim_opt(static_cast<const Dim_opt&>(column)),
459 Chain_opt(static_cast<const Chain_opt&>(column)),
460 operators_(colSettings == nullptr ? column.operators_ : Master_matrix::get_operator_ptr(colSettings)),
461 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)),
464 for (
const Entry& entry : column.column_) {
465 _insert_entry(column_.end(), entry.get_row_index(), entry.get_element());
469template <
class Master_matrix>
470inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(
Intrusive_list_column&& column) noexcept
471 : RA_opt(std::move(
static_cast<RA_opt&
>(column))),
472 Dim_opt(std::move(
static_cast<Dim_opt&
>(column))),
473 Chain_opt(std::move(
static_cast<Chain_opt&
>(column))),
474 operators_(std::exchange(column.operators_,
nullptr)),
475 entryPool_(std::exchange(column.entryPool_,
nullptr)),
476 column_(std::move(column.column_))
480template <
class Master_matrix>
481inline Intrusive_list_column<Master_matrix>::~Intrusive_list_column()
483 column_.clear_and_dispose(Delete_disposer(
this));
486template <
class Master_matrix>
487inline std::vector<typename Intrusive_list_column<Master_matrix>::Field_element>
488Intrusive_list_column<Master_matrix>::get_content(
int columnLength)
const
490 if (columnLength < 0 && column_.size() > 0)
491 columnLength = column_.back().get_row_index() + 1;
492 else if (columnLength < 0)
493 return std::vector<Field_element>();
495 std::vector<Field_element> container(columnLength);
496 for (
auto it = column_.begin(); it != column_.end() && it->get_row_index() <
static_cast<ID_index
>(columnLength);
498 container[it->get_row_index()] = Master_matrix::get_element(*it);
503template <
class Master_matrix>
504inline bool Intrusive_list_column<Master_matrix>::is_non_zero(ID_index rowIndex)
const
509 for (
const Entry& entry : column_)
510 if (entry.get_row_index() == rowIndex)
return true;
515template <
class Master_matrix>
516inline bool Intrusive_list_column<Master_matrix>::is_empty()
const
518 return column_.empty();
521template <
class Master_matrix>
522inline std::size_t Intrusive_list_column<Master_matrix>::size()
const
524 return column_.size();
527template <
class Master_matrix>
528template <
class Row_index_map>
529inline void Intrusive_list_column<Master_matrix>::reorder(
const Row_index_map& valueMap,
530 [[maybe_unused]] Index columnIndex)
532 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
533 "Method not available for chain columns.");
535 for (
auto it = column_.begin(); it != column_.end(); ++it) {
536 Entry* entry = &(*it);
537 if constexpr (Master_matrix::Option_list::has_row_access) {
538 RA_opt::unlink(entry);
539 if (columnIndex != Master_matrix::template get_null_value<Index>()) entry->set_column_index(columnIndex);
542 if constexpr (Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access)
543 RA_opt::insert_entry(entry->get_row_index(), entry);
547 if constexpr (!Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) {
548 for (
auto it = column_.begin(); it != column_.end(); ++it) {
549 Entry* entry = &(*it);
550 RA_opt::insert_entry(entry->get_row_index(), entry);
557template <
class Master_matrix>
558inline void Intrusive_list_column<Master_matrix>::clear()
560 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
561 "Method not available for chain columns as a base element should not be empty.");
563 column_.clear_and_dispose(Delete_disposer(
this));
566template <
class Master_matrix>
567inline void Intrusive_list_column<Master_matrix>::clear(ID_index rowIndex)
569 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
570 "Method not available for chain columns.");
572 auto it = column_.begin();
573 while (it != column_.end() && it->get_row_index() != rowIndex) it++;
574 if (it != column_.end()) _delete_entry(it);
577template <
class Master_matrix>
578inline typename Intrusive_list_column<Master_matrix>::ID_index Intrusive_list_column<Master_matrix>::get_pivot()
const
580 static_assert(Master_matrix::isNonBasic,
581 "Method not available for base columns.");
583 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
584 if (column_.empty())
return Master_matrix::template get_null_value<ID_index>();
585 return column_.back().get_row_index();
587 return Chain_opt::_get_pivot();
591template <
class Master_matrix>
592inline typename Intrusive_list_column<Master_matrix>::Field_element
593Intrusive_list_column<Master_matrix>::get_pivot_value()
const
595 static_assert(Master_matrix::isNonBasic,
596 "Method not available for base columns.");
598 if constexpr (Master_matrix::Option_list::is_z2) {
601 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
602 if (column_.empty())
return 0;
603 return column_.back().get_element();
605 if (Chain_opt::_get_pivot() == Master_matrix::template get_null_value<ID_index>())
return Field_element();
606 for (
const Entry& entry : column_) {
607 if (entry.get_row_index() == Chain_opt::_get_pivot())
return entry.get_element();
609 return Field_element();
614template <
class Master_matrix>
615inline typename Intrusive_list_column<Master_matrix>::iterator Intrusive_list_column<Master_matrix>::begin() noexcept
617 return column_.begin();
620template <
class Master_matrix>
621inline typename Intrusive_list_column<Master_matrix>::const_iterator Intrusive_list_column<Master_matrix>::begin()
624 return column_.begin();
627template <
class Master_matrix>
628inline typename Intrusive_list_column<Master_matrix>::iterator Intrusive_list_column<Master_matrix>::end() noexcept
630 return column_.end();
633template <
class Master_matrix>
634inline typename Intrusive_list_column<Master_matrix>::const_iterator Intrusive_list_column<Master_matrix>::end()
637 return column_.end();
640template <
class Master_matrix>
641inline typename Intrusive_list_column<Master_matrix>::reverse_iterator
642Intrusive_list_column<Master_matrix>::rbegin() noexcept
644 return column_.rbegin();
647template <
class Master_matrix>
648inline typename Intrusive_list_column<Master_matrix>::const_reverse_iterator
649Intrusive_list_column<Master_matrix>::rbegin() const noexcept
651 return column_.rbegin();
654template <
class Master_matrix>
655inline typename Intrusive_list_column<Master_matrix>::reverse_iterator
656Intrusive_list_column<Master_matrix>::rend() noexcept
658 return column_.rend();
661template <
class Master_matrix>
662inline typename Intrusive_list_column<Master_matrix>::const_reverse_iterator
663Intrusive_list_column<Master_matrix>::rend() const noexcept
665 return column_.rend();
668template <
class Master_matrix>
669inline typename Intrusive_list_column<Master_matrix>::Content_range
670Intrusive_list_column<Master_matrix>::get_non_zero_content_range()
const
675template <
class Master_matrix>
676template <
class Entry_range>
679 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Intrusive_list_column>),
680 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
682 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
683 "For chain columns, the given column cannot be constant.");
690template <
class Master_matrix>
694 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
697 Chain_opt::_swap_pivots(column);
698 Dim_opt::_swap_dimension(column);
707template <
class Master_matrix>
710 Field_element realVal = Master_matrix::get_coefficient_value(val, operators_);
712 if (realVal == Field_operators::get_additive_identity()) {
713 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
714 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
721 if (realVal == Field_operators::get_multiplicative_identity())
return *
this;
725 if constexpr (!Master_matrix::Option_list::is_z2) {
726 for (
Entry& entry : column_) {
727 operators_->multiply_inplace(entry.get_element(), realVal);
728 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(entry);
735template <
class Master_matrix>
736template <
class Entry_range>
738 const Field_element& val,
739 const Entry_range& column)
741 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Intrusive_list_column>),
742 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
744 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
745 "For chain columns, the given column cannot be constant.");
747 _multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column);
752template <
class Master_matrix>
754 const Field_element& val,
757 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
759 if (_multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column)) {
760 Chain_opt::_swap_pivots(column);
761 Dim_opt::_swap_dimension(column);
764 _multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column);
770template <
class Master_matrix>
771template <
class Entry_range>
773 const Entry_range& column,
774 const Field_element& val)
776 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Intrusive_list_column>),
777 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
779 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
780 "For chain columns, the given column cannot be constant.");
782 _multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_));
787template <
class Master_matrix>
790 const Field_element& val)
792 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
794 if (_multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_))) {
795 Chain_opt::_swap_pivots(column);
796 Dim_opt::_swap_dimension(column);
799 _multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_));
805template <
class Master_matrix>
806inline void Intrusive_list_column<Master_matrix>::push_back(
const Entry& entry)
808 static_assert(Master_matrix::Option_list::is_of_boundary_type,
"`push_back` is not available for Chain matrices.");
810 GUDHI_CHECK(entry.get_row_index() > get_pivot(),
811 std::invalid_argument(
"The new row index has to be higher than the current pivot."));
813 _insert_entry(column_.end(), entry.get_row_index(), entry.get_element());
816template <
class Master_matrix>
820 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
823 if (
this == &other)
return *
this;
825 Dim_opt::operator=(other);
826 Chain_opt::operator=(other);
829 column_.clear_and_dispose(Delete_disposer(
this));
830 operators_ = other.operators_;
831 entryPool_ = other.entryPool_;
832 column_.clone_from(other.column_, New_cloner(entryPool_), Delete_disposer(
this));
837template <
class Master_matrix>
841 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
844 if (&column_ == &(other.column_))
return *
this;
846 Dim_opt::operator=(std::move(other));
847 Chain_opt::operator=(std::move(other));
849 column_.clear_and_dispose(Delete_disposer(
this));
851 operators_ = std::exchange(other.operators_,
nullptr);
852 entryPool_ = std::exchange(other.entryPool_,
nullptr);
853 column_ = std::move(other.column_);
858template <
class Master_matrix>
859inline void Intrusive_list_column<Master_matrix>::_delete_entry(iterator& it)
861 it = column_.erase_and_dispose(it, Delete_disposer(
this));
864template <
class Master_matrix>
865inline typename Intrusive_list_column<Master_matrix>::Entry* Intrusive_list_column<Master_matrix>::_insert_entry(
866 const iterator& position,
868 const Field_element& value)
871 if constexpr (Master_matrix::Option_list::has_row_access) {
872 newEntry = entryPool_->construct(RA_opt::get_column_index(), rowIndex);
874 newEntry = entryPool_->construct(rowIndex);
876 newEntry->set_element(value);
877 column_.insert(position, *newEntry);
878 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::insert_entry(rowIndex, newEntry);
882template <
class Master_matrix>
883template <
class Entry_range>
884inline bool Intrusive_list_column<Master_matrix>::_add(
const Entry_range& column)
886 return _add_to_column(column, *
this);
889template <
class Master_matrix>
890template <
class Entry_range>
891inline bool Intrusive_list_column<Master_matrix>::_multiply_target_and_add(
const Field_element& val,
892 const Entry_range& column)
894 return _multiply_target_and_add_to_column(val, column, *
this);
897template <
class Master_matrix>
898template <
class Entry_range>
899inline bool Intrusive_list_column<Master_matrix>::_multiply_source_and_add(
const Entry_range& column,
900 const Field_element& val)
902 return _multiply_source_and_add_to_column(val, column, *
this);
916template <
class Master_matrix>
917struct std::hash<
Gudhi::persistence_matrix::Intrusive_list_column<Master_matrix> > {
920 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
void set_row_index(ID_index rowIndex)
Sets the row index stored in the entry.
Definition entry_types.h:224
Column class following the PersistenceMatrixColumn concept.
Definition intrusive_list_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