18 #ifndef PM_UNORDERED_SET_COLUMN_H
19 #define PM_UNORDERED_SET_COLUMN_H
23 #include <type_traits>
27 #include <boost/iterator/indirect_iterator.hpp>
28 #if BOOST_VERSION >= 108100
29 #include <boost/unordered/unordered_flat_set.hpp>
31 #include <unordered_set>
37 namespace persistence_matrix {
42 struct CellPointerHash {
43 size_t operator()(
const Cell* c)
const {
return std::hash<Cell>()(*c); }
46 struct CellPointerEq {
47 bool operator()(
const Cell* c1,
const Cell* c2)
const {
return *c1 == *c2; }
63 template <
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_type =
typename Master_matrix::dimension_type;
73 using Field_element_type =
typename Master_matrix::element_type;
74 using Cell =
typename Master_matrix::Cell_type;
75 using Column_settings =
typename Master_matrix::Column_settings;
78 using Field_operators =
typename Master_matrix::Field_operators;
79 using Cell_constructor =
typename Master_matrix::Cell_constructor;
81 struct CellPointerComp {
82 bool operator()(
const Cell* c1,
const Cell* c2)
const {
return *c1 < *c2; }
85 #if BOOST_VERSION >= 108100
86 using Column_type = boost::unordered_flat_set<Cell*, CellPointerHash<Cell>, CellPointerEq<Cell>>;
88 using Column_type = std::unordered_set<Cell*, CellPointerHash<Cell>, CellPointerEq<Cell>>;
92 using iterator = boost::indirect_iterator<typename Column_type::iterator>;
93 using const_iterator = boost::indirect_iterator<typename Column_type::const_iterator>;
96 template <
class Container_type =
typename Master_matrix::boundary_type>
98 Column_settings* colSettings);
99 template <
class Container_type =
typename Master_matrix::boundary_type,
class Row_container_type>
101 const Container_type& nonZeroRowIndices,
102 Row_container_type* rowContainer,
103 Column_settings* colSettings);
104 template <
class Container_type =
typename Master_matrix::boundary_type>
106 dimension_type dimension,
107 Column_settings* colSettings);
108 template <
class Container_type =
typename Master_matrix::boundary_type,
class Row_container_type>
110 const Container_type& nonZeroChainRowIndices,
111 dimension_type dimension,
112 Row_container_type* rowContainer,
113 Column_settings* colSettings);
115 Column_settings* colSettings =
nullptr);
116 template <
class Row_container_type>
119 Row_container_type* rowContainer,
120 Column_settings* colSettings =
nullptr);
124 std::vector<Field_element_type> get_content(
int columnLength = -1)
const;
125 bool is_non_zero(id_index rowIndex)
const;
126 bool is_empty()
const;
127 std::size_t size()
const;
129 template <
class Map_type>
130 void reorder(
const Map_type& valueMap, [[maybe_unused]] index columnIndex = -1);
132 void clear(id_index rowIndex);
134 id_index get_pivot()
const;
135 Field_element_type get_pivot_value()
const;
137 iterator begin() noexcept;
138 const_iterator begin()
const noexcept;
139 iterator end() noexcept;
140 const_iterator end()
const noexcept;
142 template <
class Cell_range>
149 template <
class Cell_range>
150 Unordered_set_column& multiply_target_and_add(
const Field_element_type& val,
const Cell_range& column);
153 template <
class Cell_range>
154 Unordered_set_column& multiply_source_and_add(
const Cell_range& column,
const Field_element_type& val);
158 if (&c1 == &c2)
return true;
159 if (c1.column_.size() != c2.column_.size())
return false;
161 for (Cell* cell : c1.column_){
162 auto it = c2.column_.find(cell);
163 if (it == c2.column_.end())
return false;
164 if constexpr (!Master_matrix::Option_list::is_z2)
165 if ((*it)->get_element() != cell->get_element())
return false;
170 if (&c1 == &c2)
return false;
172 using id_index = Unordered_set_column<Master_matrix>::id_index;
173 using rep_type =
typename std::conditional<Master_matrix::Option_list::is_z2,
175 std::pair<id_index, unsigned int>
178 auto it1 = c1.column_.begin();
179 auto it2 = c2.column_.begin();
180 std::set<rep_type> cells1, cells2;
181 while (it1 != c1.column_.end() && it2 != c2.column_.end()) {
182 if constexpr (Master_matrix::Option_list::is_z2) {
183 cells1.insert((*it1)->get_row_index());
184 cells2.insert((*it2)->get_row_index());
186 cells1.emplace((*it1)->get_row_index(), (*it1)->get_element());
187 cells2.emplace((*it2)->get_row_index(), (*it2)->get_element());
192 while (it1 != c1.column_.end()) {
193 if constexpr (Master_matrix::Option_list::is_z2) {
194 cells1.insert((*it1)->get_row_index());
196 cells1.emplace((*it1)->get_row_index(), (*it1)->get_element());
200 while (it2 != c2.column_.end()) {
201 if constexpr (Master_matrix::Option_list::is_z2) {
202 cells2.insert((*it2)->get_row_index());
204 cells2.emplace((*it2)->get_row_index(), (*it2)->get_element());
208 return cells1 < cells2;
221 col1.column_.swap(col2.column_);
222 std::swap(col1.operators_, col2.operators_);
223 std::swap(col1.cellPool_, col2.cellPool_);
232 Field_operators* operators_;
233 Cell_constructor* cellPool_;
235 void _delete_cell(
typename Column_type::iterator& it);
236 Cell* _insert_cell(
const Field_element_type& value, id_index rowIndex);
237 void _insert_cell(id_index rowIndex);
238 template <
class Cell_range>
239 bool _add(
const Cell_range& column);
240 template <
class Cell_range>
241 bool _multiply_target_and_add(
const Field_element_type& val,
const Cell_range& column);
242 template <
class Cell_range>
243 bool _multiply_source_and_add(
const Cell_range& column,
const Field_element_type& val);
244 template <
class Cell_range,
typename F1,
typename F2>
245 bool _generic_add(
const Cell_range& source, F1&& process_source, F2&& update_target);
248 template <
class Master_matrix>
254 cellPool_(colSettings == nullptr ? nullptr : &(colSettings->cellConstructor))
256 if (operators_ ==
nullptr && cellPool_ ==
nullptr)
return;
257 if constexpr (!Master_matrix::Option_list::is_z2) {
258 operators_ = &(colSettings->operators);
262 template <
class Master_matrix>
263 template <
class Container_type>
264 inline Unordered_set_column<Master_matrix>::Unordered_set_column(
265 const Container_type& nonZeroRowIndices, Column_settings* colSettings)
267 dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
269 column_(nonZeroRowIndices.size()),
271 cellPool_(&(colSettings->cellConstructor))
273 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
274 "Constructor not available for chain columns, please specify the dimension of the chain.");
276 if constexpr (Master_matrix::Option_list::is_z2) {
277 for (id_index
id : nonZeroRowIndices) {
281 operators_ = &(colSettings->operators);
282 for (
const auto& p : nonZeroRowIndices) {
283 _insert_cell(operators_->get_value(p.second), p.first);
288 template <
class Master_matrix>
289 template <
class Container_type,
class Row_container_type>
290 inline Unordered_set_column<Master_matrix>::Unordered_set_column(
292 const Container_type& nonZeroRowIndices,
293 Row_container_type* rowContainer,
294 Column_settings* colSettings)
295 : ra_opt(columnIndex, rowContainer),
296 dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
298 if constexpr (Master_matrix::Option_list::is_z2) {
299 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : *std::prev(nonZeroRowIndices.end());
301 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : std::prev(nonZeroRowIndices.end())->first;
304 column_(nonZeroRowIndices.size()),
306 cellPool_(&(colSettings->cellConstructor))
308 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
309 "Constructor not available for chain columns, please specify the dimension of the chain.");
311 if constexpr (Master_matrix::Option_list::is_z2) {
312 for (id_index
id : nonZeroRowIndices) {
316 operators_ = &(colSettings->operators);
317 for (
const auto& p : nonZeroRowIndices) {
318 _insert_cell(operators_->get_value(p.second), p.first);
323 template <
class Master_matrix>
324 template <
class Container_type>
325 inline Unordered_set_column<Master_matrix>::Unordered_set_column(
326 const Container_type& nonZeroRowIndices,
327 dimension_type dimension,
328 Column_settings* colSettings)
332 if constexpr (Master_matrix::Option_list::is_z2) {
333 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : *std::prev(nonZeroRowIndices.end());
335 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : std::prev(nonZeroRowIndices.end())->first;
338 column_(nonZeroRowIndices.size()),
340 cellPool_(&(colSettings->cellConstructor))
342 if constexpr (Master_matrix::Option_list::is_z2) {
343 for (id_index
id : nonZeroRowIndices) {
347 operators_ = &(colSettings->operators);
348 for (
const auto& p : nonZeroRowIndices) {
349 _insert_cell(operators_->get_value(p.second), p.first);
354 template <
class Master_matrix>
355 template <
class Container_type,
class Row_container_type>
356 inline Unordered_set_column<Master_matrix>::Unordered_set_column(
358 const Container_type& nonZeroRowIndices,
359 dimension_type dimension,
360 Row_container_type* rowContainer,
361 Column_settings* colSettings)
362 : ra_opt(columnIndex, rowContainer),
365 if constexpr (Master_matrix::Option_list::is_z2) {
366 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : *std::prev(nonZeroRowIndices.end());
368 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : std::prev(nonZeroRowIndices.end())->first;
371 column_(nonZeroRowIndices.size()),
373 cellPool_(&(colSettings->cellConstructor))
375 if constexpr (Master_matrix::Option_list::is_z2) {
376 for (id_index
id : nonZeroRowIndices) {
380 operators_ = &(colSettings->operators);
381 for (
const auto& p : nonZeroRowIndices) {
382 _insert_cell(operators_->get_value(p.second), p.first);
387 template <
class Master_matrix>
388 inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Unordered_set_column& column,
389 Column_settings* colSettings)
391 dim_opt(static_cast<const dim_opt&>(column)),
392 chain_opt(static_cast<const chain_opt&>(column)),
393 column_(column.column_.bucket_count()),
394 operators_(colSettings == nullptr ? column.operators_ : nullptr),
395 cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor))
397 static_assert(!Master_matrix::Option_list::has_row_access,
398 "Simple copy constructor not available when row access option enabled. Please specify the new column "
399 "index and the row container.");
401 if constexpr (!Master_matrix::Option_list::is_z2){
402 if (colSettings !=
nullptr) operators_ = &(colSettings->operators);
405 for (
const Cell* cell : column.column_) {
406 if constexpr (Master_matrix::Option_list::is_z2) {
407 _insert_cell(cell->get_row_index());
409 _insert_cell(cell->get_element(), cell->get_row_index());
414 template <
class Master_matrix>
415 template <
class Row_container_type>
416 inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Unordered_set_column& column,
418 Row_container_type* rowContainer,
419 Column_settings* colSettings)
420 : ra_opt(columnIndex, rowContainer),
421 dim_opt(static_cast<const dim_opt&>(column)),
422 chain_opt(static_cast<const chain_opt&>(column)),
423 column_(column.column_.bucket_count()),
424 operators_(colSettings == nullptr ? column.operators_ : nullptr),
425 cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor))
427 if constexpr (!Master_matrix::Option_list::is_z2){
428 if (colSettings !=
nullptr) operators_ = &(colSettings->operators);
431 for (
const Cell* cell : column.column_) {
432 if constexpr (Master_matrix::Option_list::is_z2) {
433 _insert_cell(cell->get_row_index());
435 _insert_cell(cell->get_element(), cell->get_row_index());
440 template <
class Master_matrix>
441 inline Unordered_set_column<Master_matrix>::Unordered_set_column(
442 Unordered_set_column&& column) noexcept
443 : ra_opt(std::move(
static_cast<ra_opt&
>(column))),
444 dim_opt(std::move(
static_cast<dim_opt&
>(column))),
445 chain_opt(std::move(
static_cast<chain_opt&
>(column))),
446 column_(std::move(column.column_)),
447 operators_(std::exchange(column.operators_,
nullptr)),
448 cellPool_(std::exchange(column.cellPool_,
nullptr))
451 template <
class Master_matrix>
452 inline Unordered_set_column<Master_matrix>::~Unordered_set_column()
454 for (
auto* cell : column_) {
455 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::unlink(cell);
456 cellPool_->destroy(cell);
460 template <
class Master_matrix>
461 inline std::vector<typename Unordered_set_column<Master_matrix>::Field_element_type>
462 Unordered_set_column<Master_matrix>::get_content(
int columnLength)
const
464 if (columnLength < 0 && column_.size() > 0)
465 columnLength = (*std::max_element(column_.begin(), column_.end(), CellPointerComp()))->get_row_index() + 1;
466 else if (columnLength < 0)
467 return std::vector<Field_element_type>();
469 std::vector<Field_element_type> container(columnLength, 0);
470 for (
auto it = column_.begin(); it != column_.end(); ++it) {
471 if ((*it)->get_row_index() <
static_cast<id_index
>(columnLength)) {
472 if constexpr (Master_matrix::Option_list::is_z2) {
473 container[(*it)->get_row_index()] = 1;
475 container[(*it)->get_row_index()] = (*it)->get_element();
482 template <
class Master_matrix>
483 inline bool Unordered_set_column<Master_matrix>::is_non_zero(id_index rowIndex)
const
486 return column_.find(&cell) != column_.end();
489 template <
class Master_matrix>
490 inline bool Unordered_set_column<Master_matrix>::is_empty()
const
492 return column_.empty();
495 template <
class Master_matrix>
496 inline std::size_t Unordered_set_column<Master_matrix>::size()
const
498 return column_.size();
501 template <
class Master_matrix>
502 template <
class Map_type>
503 inline void Unordered_set_column<Master_matrix>::reorder(
const Map_type& valueMap,
504 [[maybe_unused]] index columnIndex)
506 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
507 "Method not available for chain columns.");
511 for (Cell* cell : column_) {
512 if constexpr (Master_matrix::Option_list::has_row_access) {
513 ra_opt::unlink(cell);
514 if (columnIndex !=
static_cast<index
>(-1)) cell->set_column_index(columnIndex);
516 cell->set_row_index(valueMap.at(cell->get_row_index()));
518 if constexpr (Master_matrix::Option_list::has_row_access &&
519 Master_matrix::Option_list::has_intrusive_rows)
520 ra_opt::insert_cell(cell->get_row_index(), cell);
524 if constexpr (Master_matrix::Option_list::has_row_access && !Master_matrix::Option_list::has_intrusive_rows) {
525 for (Cell* cell : newSet) {
526 ra_opt::insert_cell(cell->get_row_index(), cell);
530 column_.swap(newSet);
533 template <
class Master_matrix>
534 inline void Unordered_set_column<Master_matrix>::clear()
536 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
537 "Method not available for chain columns as a base element should not be empty.");
539 for (
auto* cell : column_) {
540 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::unlink(cell);
541 cellPool_->destroy(cell);
547 template <
class Master_matrix>
548 inline void Unordered_set_column<Master_matrix>::clear(id_index rowIndex)
550 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
551 "Method not available for chain columns.");
553 auto cell = cellPool_->construct(rowIndex);
554 auto it = column_.find(cell);
555 if (it != column_.end()) {
558 cellPool_->destroy(cell);
561 template <
class Master_matrix>
562 inline typename Unordered_set_column<Master_matrix>::id_index
563 Unordered_set_column<Master_matrix>::get_pivot()
const
565 static_assert(Master_matrix::isNonBasic,
566 "Method not available for base columns.");
568 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
569 if (column_.empty())
return -1;
572 return (*std::max_element(column_.begin(), column_.end(), CellPointerComp()))->get_row_index();
574 return chain_opt::get_pivot();
578 template <
class Master_matrix>
579 inline typename Unordered_set_column<Master_matrix>::Field_element_type
580 Unordered_set_column<Master_matrix>::get_pivot_value()
const
582 static_assert(Master_matrix::isNonBasic,
583 "Method not available for base columns.");
585 if constexpr (Master_matrix::Option_list::is_z2) {
588 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
589 if (column_.empty())
return 0;
590 return (*std::max_element(column_.begin(), column_.end(), CellPointerComp()))->get_element();
592 if (chain_opt::get_pivot() ==
static_cast<id_index
>(-1))
return Field_element_type();
593 for (
const Cell* cell : column_) {
594 if (cell->get_row_index() == chain_opt::get_pivot())
return cell->get_element();
596 return Field_element_type();
601 template <
class Master_matrix>
602 inline typename Unordered_set_column<Master_matrix>::iterator
603 Unordered_set_column<Master_matrix>::begin() noexcept
605 return column_.begin();
608 template <
class Master_matrix>
609 inline typename Unordered_set_column<Master_matrix>::const_iterator
610 Unordered_set_column<Master_matrix>::begin() const noexcept
612 return column_.begin();
615 template <
class Master_matrix>
616 inline typename Unordered_set_column<Master_matrix>::iterator
617 Unordered_set_column<Master_matrix>::end() noexcept
619 return column_.end();
622 template <
class Master_matrix>
623 inline typename Unordered_set_column<Master_matrix>::const_iterator
624 Unordered_set_column<Master_matrix>::end() const noexcept
626 return column_.end();
629 template <
class Master_matrix>
630 template <
class Cell_range>
631 inline Unordered_set_column<Master_matrix>&
632 Unordered_set_column<Master_matrix>::operator+=(
const Cell_range& column)
634 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Cell_range, Unordered_set_column>),
635 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
637 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
638 "For chain columns, the given column cannot be constant.");
645 template <
class Master_matrix>
646 inline Unordered_set_column<Master_matrix>&
647 Unordered_set_column<Master_matrix>::operator+=(Unordered_set_column& column)
649 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
652 chain_opt::swap_pivots(column);
653 dim_opt::swap_dimension(column);
662 template <
class Master_matrix>
663 inline Unordered_set_column<Master_matrix>&
664 Unordered_set_column<Master_matrix>::operator*=(
unsigned int v)
666 if constexpr (Master_matrix::Option_list::is_z2) {
668 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
669 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
675 Field_element_type val = operators_->get_value(v);
677 if (val == Field_operators::get_additive_identity()) {
678 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
679 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
686 if (val == Field_operators::get_multiplicative_identity())
return *
this;
688 for (Cell* cell : column_) {
689 operators_->multiply_inplace(cell->get_element(), val);
690 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::update_cell(*cell);
697 template <
class Master_matrix>
698 template <
class Cell_range>
699 inline Unordered_set_column<Master_matrix>&
700 Unordered_set_column<Master_matrix>::multiply_target_and_add(
const Field_element_type& val,
701 const Cell_range& column)
703 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Cell_range, Unordered_set_column>),
704 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
706 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
707 "For chain columns, the given column cannot be constant.");
709 if constexpr (Master_matrix::Option_list::is_z2) {
717 _multiply_target_and_add(val, column);
723 template <
class Master_matrix>
724 inline Unordered_set_column<Master_matrix>&
725 Unordered_set_column<Master_matrix>::multiply_target_and_add(
const Field_element_type& val,
726 Unordered_set_column& column)
728 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
730 if constexpr (Master_matrix::Option_list::is_z2) {
733 chain_opt::swap_pivots(column);
734 dim_opt::swap_dimension(column);
737 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
740 if (_multiply_target_and_add(val, column)) {
741 chain_opt::swap_pivots(column);
742 dim_opt::swap_dimension(column);
746 if constexpr (Master_matrix::Option_list::is_z2) {
754 _multiply_target_and_add(val, column);
761 template <
class Master_matrix>
762 template <
class Cell_range>
763 inline Unordered_set_column<Master_matrix>&
764 Unordered_set_column<Master_matrix>::multiply_source_and_add(
const Cell_range& column,
765 const Field_element_type& val)
767 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Cell_range, Unordered_set_column>),
768 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
770 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
771 "For chain columns, the given column cannot be constant.");
773 if constexpr (Master_matrix::Option_list::is_z2) {
778 _multiply_source_and_add(column, val);
784 template <
class Master_matrix>
785 inline Unordered_set_column<Master_matrix>&
786 Unordered_set_column<Master_matrix>::multiply_source_and_add(Unordered_set_column& column,
787 const Field_element_type& val)
789 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
791 if constexpr (Master_matrix::Option_list::is_z2) {
794 chain_opt::swap_pivots(column);
795 dim_opt::swap_dimension(column);
799 if (_multiply_source_and_add(column, val)) {
800 chain_opt::swap_pivots(column);
801 dim_opt::swap_dimension(column);
805 if constexpr (Master_matrix::Option_list::is_z2) {
810 _multiply_source_and_add(column, val);
817 template <
class Master_matrix>
818 inline Unordered_set_column<Master_matrix>&
819 Unordered_set_column<Master_matrix>::operator=(
const Unordered_set_column& other)
821 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignement not enabled with row access option.");
823 dim_opt::operator=(other);
824 chain_opt::operator=(other);
826 for (
auto* cell : column_) {
827 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::unlink(cell);
828 cellPool_->destroy(cell);
832 operators_ = other.operators_;
833 cellPool_ = other.cellPool_;
835 for (
const Cell* cell : other.column_) {
836 if constexpr (Master_matrix::Option_list::is_z2) {
837 _insert_cell(cell->get_row_index());
839 _insert_cell(cell->get_element(), cell->get_row_index());
846 template <
class Master_matrix>
847 inline void Unordered_set_column<Master_matrix>::_delete_cell(
typename Column_type::iterator& it)
849 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::unlink(*it);
850 cellPool_->destroy(*it);
856 template <
class Master_matrix>
857 inline typename Unordered_set_column<Master_matrix>::Cell* Unordered_set_column<Master_matrix>::_insert_cell(
858 const Field_element_type& value, id_index rowIndex)
860 if constexpr (Master_matrix::Option_list::has_row_access) {
861 Cell* newCell = cellPool_->construct(ra_opt::columnIndex_, rowIndex);
862 newCell->set_element(value);
863 column_.insert(newCell);
864 ra_opt::insert_cell(rowIndex, newCell);
867 Cell* newCell = cellPool_->construct(rowIndex);
868 newCell->set_element(value);
869 column_.insert(newCell);
874 template <
class Master_matrix>
875 inline void Unordered_set_column<Master_matrix>::_insert_cell(id_index rowIndex)
877 if constexpr (Master_matrix::Option_list::has_row_access) {
878 Cell* newCell = cellPool_->construct(ra_opt::columnIndex_, rowIndex);
879 column_.insert(newCell);
880 ra_opt::insert_cell(rowIndex, newCell);
882 Cell* newCell = cellPool_->construct(rowIndex);
883 column_.insert(newCell);
887 template <
class Master_matrix>
888 template <
class Cell_range>
889 inline bool Unordered_set_column<Master_matrix>::_add(
const Cell_range& column)
893 [&](
const Cell& oldCell, Cell* newCell) {
894 if constexpr (!Master_matrix::Option_list::is_z2) newCell->set_element(oldCell.get_element());
896 [&](Cell* targetCell,
const Cell& sourceCell) {
897 if constexpr (!Master_matrix::Option_list::is_z2)
898 operators_->add_inplace(targetCell->get_element(), sourceCell.get_element());
902 template <
class Master_matrix>
903 template <
class Cell_range>
904 inline bool Unordered_set_column<Master_matrix>::_multiply_target_and_add(
const Field_element_type& val,
905 const Cell_range& column)
908 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
909 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
913 for (
const Cell& v : column) {
914 _insert_cell(v.get_element(), v.get_row_index());
926 template <
class Master_matrix>
927 template <
class Cell_range>
928 inline bool Unordered_set_column<Master_matrix>::_multiply_source_and_add(
const Cell_range& column,
929 const Field_element_type& val)
935 return _generic_add(column,
936 [&](
const Cell& oldCell, Cell* newCell) {
937 newCell->set_element(oldCell.get_element());
938 operators_->multiply_inplace(newCell->get_element(), val);
940 [&](Cell* targetCell,
const Cell& sourceCell) {
941 operators_->multiply_and_add_inplace_back(sourceCell.get_element(), val, targetCell->get_element());
945 template <
class Master_matrix>
946 template <
class Cell_range,
typename F1,
typename F2>
947 inline bool Unordered_set_column<Master_matrix>::_generic_add(
const Cell_range& source,
951 bool pivotIsZeroed =
false;
953 for (
const Cell& cell : source) {
955 if constexpr (Master_matrix::Option_list::has_row_access) {
956 newCell = cellPool_->construct(ra_opt::columnIndex_, cell.get_row_index());
958 newCell = cellPool_->construct(cell.get_row_index());
960 auto res = column_.insert(newCell);
962 process_source(cell, newCell);
963 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::insert_cell(cell.get_row_index(), newCell);
965 cellPool_->destroy(newCell);
966 if constexpr (Master_matrix::Option_list::is_z2) {
967 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
968 if (cell.get_row_index() == chain_opt::get_pivot()) pivotIsZeroed =
true;
970 _delete_cell(res.first);
972 update_target(*res.first, cell);
973 if ((*res.first)->get_element() == Field_operators::get_additive_identity()) {
974 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
975 if ((*res.first)->get_row_index() == chain_opt::get_pivot()) pivotIsZeroed =
true;
977 _delete_cell(res.first);
979 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::update_cell(**res.first);
985 return pivotIsZeroed;
999 template <
class Master_matrix>
1000 struct std::hash<
Gudhi::persistence_matrix::Unordered_set_column<Master_matrix> >
1004 std::size_t seed = 0;
1005 for (
const auto& cell : column) {
1006 seed ^= std::hash<unsigned int>()(cell.get_row_index() *
static_cast<unsigned int>(cell.get_element()));
Contains the New_cell_constructor and Pool_cell_constructor structures.
Column class following the PersistenceMatrixColumn concept.
Definition: unordered_set_column.h:67
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