18 #ifndef PM_VECTOR_COLUMN_H
19 #define PM_VECTOR_COLUMN_H
24 #include <type_traits>
26 #include <unordered_set>
29 #include <boost/iterator/indirect_iterator.hpp>
33 namespace persistence_matrix {
49 template <
class Master_matrix>
55 using Master = Master_matrix;
56 using index =
typename Master_matrix::index;
57 using id_index =
typename Master_matrix::id_index;
58 using dimension_type =
typename Master_matrix::dimension_type;
59 using Field_element_type =
typename Master_matrix::element_type;
60 using Cell =
typename Master_matrix::Cell_type;
61 using Column_settings =
typename Master_matrix::Column_settings;
64 using Field_operators =
typename Master_matrix::Field_operators;
65 using Column_type = std::vector<Cell*>;
66 using Cell_constructor =
typename Master_matrix::Cell_constructor;
69 using iterator = boost::indirect_iterator<typename Column_type::iterator>;
70 using const_iterator = boost::indirect_iterator<typename Column_type::const_iterator>;
71 using reverse_iterator = boost::indirect_iterator<typename Column_type::reverse_iterator>;
72 using const_reverse_iterator = boost::indirect_iterator<typename Column_type::const_reverse_iterator>;
75 template <
class Container_type =
typename Master_matrix::boundary_type>
76 Vector_column(
const Container_type& nonZeroRowIndices, Column_settings* colSettings);
77 template <
class Container_type =
typename Master_matrix::boundary_type,
class Row_container_type>
79 const Container_type& nonZeroRowIndices,
80 Row_container_type* rowContainer,
81 Column_settings* colSettings);
82 template <
class Container_type =
typename Master_matrix::boundary_type>
84 dimension_type dimension,
85 Column_settings* colSettings);
86 template <
class Container_type =
typename Master_matrix::boundary_type,
class Row_container_type>
88 const Container_type& nonZeroChainRowIndices,
89 dimension_type dimension,
90 Row_container_type* rowContainer,
91 Column_settings* colSettings);
93 Column_settings* colSettings =
nullptr);
94 template <
class Row_container_type>
97 Row_container_type* rowContainer,
98 Column_settings* colSettings =
nullptr);
102 std::vector<Field_element_type> get_content(
int columnLength = -1)
const;
103 bool is_non_zero(id_index rowIndex)
const;
104 bool is_empty()
const;
105 std::size_t size()
const;
107 template <
class Map_type>
108 void reorder(
const Map_type& valueMap, [[maybe_unused]] index columnIndex = -1);
111 void clear(id_index rowIndex);
113 id_index get_pivot();
114 Field_element_type get_pivot_value();
116 iterator begin() noexcept;
117 const_iterator begin()
const noexcept;
118 iterator end() noexcept;
119 const_iterator end()
const noexcept;
120 reverse_iterator rbegin() noexcept;
121 const_reverse_iterator rbegin()
const noexcept;
122 reverse_iterator rend() noexcept;
123 const_reverse_iterator rend()
const noexcept;
125 template <
class Cell_range>
132 template <
class Cell_range>
133 Vector_column& multiply_target_and_add(
const Field_element_type& val,
const Cell_range& column);
136 template <
class Cell_range>
137 Vector_column& multiply_source_and_add(
const Cell_range& column,
const Field_element_type& val);
140 std::size_t compute_hash_value();
143 if (&c1 == &c2)
return true;
144 if (c1.erasedValues_.empty() && c2.erasedValues_.empty() && c1.column_.size() != c2.column_.size())
return false;
146 auto it1 = c1.column_.begin();
147 auto it2 = c2.column_.begin();
148 while (it1 != c1.column_.end() && it2 != c2.column_.end()) {
149 if constexpr (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type) {
150 while (it1 != c1.column_.end() && c1.erasedValues_.find((*it1)->get_row_index()) != c1.erasedValues_.end())
152 while (it2 != c2.column_.end() && c2.erasedValues_.find((*it2)->get_row_index()) != c2.erasedValues_.end())
154 if (it1 == c1.column_.end() || it2 == c2.column_.end())
break;
156 if constexpr (Master_matrix::Option_list::is_z2) {
157 if ((*it1)->get_row_index() != (*it2)->get_row_index())
return false;
159 if ((*it1)->get_row_index() != (*it2)->get_row_index() || (*it1)->get_element() != (*it2)->get_element())
166 if constexpr (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type) {
167 while (it1 != c1.column_.end() && c1.erasedValues_.find((*it1)->get_row_index()) != c1.erasedValues_.end()) ++it1;
168 while (it2 != c2.column_.end() && c2.erasedValues_.find((*it2)->get_row_index()) != c2.erasedValues_.end()) ++it2;
169 return it2 == c2.column_.end() && it1 == c1.column_.end();
175 if (&c1 == &c2)
return false;
177 auto it1 = c1.column_.begin();
178 auto it2 = c2.column_.begin();
179 while (it1 != c1.column_.end() && it2 != c2.column_.end()) {
180 if constexpr (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type) {
181 while (it1 != c1.column_.end() && c1.erasedValues_.find((*it1)->get_row_index()) != c1.erasedValues_.end())
183 while (it2 != c2.column_.end() && c2.erasedValues_.find((*it2)->get_row_index()) != c2.erasedValues_.end())
185 if (it1 == c1.column_.end() || it2 == c2.column_.end())
break;
188 if ((*it1)->get_row_index() != (*it2)->get_row_index())
return (*it1)->get_row_index() < (*it2)->get_row_index();
189 if constexpr (!Master_matrix::Option_list::is_z2) {
190 if ((*it1)->get_element() != (*it2)->get_element())
return (*it1)->get_element() < (*it2)->get_element();
195 if constexpr (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type) {
196 while (it1 != c1.column_.end() && c1.erasedValues_.find((*it1)->get_row_index()) != c1.erasedValues_.end()) ++it1;
197 while (it2 != c2.column_.end() && c2.erasedValues_.find((*it2)->get_row_index()) != c2.erasedValues_.end()) ++it2;
199 return it2 != c2.column_.end();
212 col1.column_.swap(col2.column_);
213 col1.erasedValues_.swap(col2.erasedValues_);
214 std::swap(col1.operators_, col2.operators_);
215 std::swap(col1.cellPool_, col2.cellPool_);
224 std::unordered_set<id_index> erasedValues_;
226 Field_operators* operators_;
227 Cell_constructor* cellPool_;
229 template <
class Column_type,
class Cell_iterator,
typename F1,
typename F2,
typename F3,
typename F4>
230 friend void _generic_merge_cell_to_column(Column_type& targetColumn,
231 Cell_iterator& itSource,
232 typename Column_type::Column_type::iterator& itTarget,
237 bool& pivotIsZeroed);
239 void _delete_cell(Cell* cell);
240 void _delete_cell(
typename Column_type::iterator& it);
241 Cell* _insert_cell(
const Field_element_type& value, id_index rowIndex, Column_type& column);
242 void _insert_cell(id_index rowIndex, Column_type& column);
243 void _update_cell(
const Field_element_type& value, id_index rowIndex, index position);
244 void _update_cell(id_index rowIndex, index position);
245 template <
class Cell_range>
246 bool _add(
const Cell_range& column);
247 template <
class Cell_range>
248 bool _multiply_target_and_add(
const Field_element_type& val,
const Cell_range& column);
249 template <
class Cell_range>
250 bool _multiply_source_and_add(
const Cell_range& column,
const Field_element_type& val);
251 template <
class Cell_range,
typename F1,
typename F2,
typename F3,
typename F4>
252 bool _generic_add(
const Cell_range& source,
256 F4&& update_target2);
259 template <
class Master_matrix>
261 : ra_opt(), dim_opt(), chain_opt(), operators_(nullptr), cellPool_(colSettings == nullptr ? nullptr : &(colSettings->cellConstructor))
263 if (operators_ ==
nullptr && cellPool_ ==
nullptr)
return;
264 if constexpr (!Master_matrix::Option_list::is_z2){
265 operators_ = &(colSettings->operators);
269 template <
class Master_matrix>
270 template <
class Container_type>
271 inline Vector_column<Master_matrix>::Vector_column(
const Container_type& nonZeroRowIndices,
272 Column_settings* colSettings)
274 dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
276 column_(nonZeroRowIndices.size(), nullptr),
278 cellPool_(&(colSettings->cellConstructor))
280 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
281 "Constructor not available for chain columns, please specify the dimension of the chain.");
283 if constexpr (!Master_matrix::Option_list::is_z2){
284 operators_ = &(colSettings->operators);
288 if constexpr (Master_matrix::Option_list::is_z2) {
289 for (id_index
id : nonZeroRowIndices) {
290 _update_cell(
id, i++);
293 for (
const auto& p : nonZeroRowIndices) {
294 _update_cell(operators_->get_value(p.second), p.first, i++);
299 template <
class Master_matrix>
300 template <
class Container_type,
class Row_container_type>
301 inline Vector_column<Master_matrix>::Vector_column(index columnIndex,
302 const Container_type& nonZeroRowIndices,
303 Row_container_type* rowContainer,
304 Column_settings* colSettings)
305 : ra_opt(columnIndex, rowContainer),
306 dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
308 if constexpr (Master_matrix::Option_list::is_z2) {
309 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : *std::prev(nonZeroRowIndices.end());
311 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : std::prev(nonZeroRowIndices.end())->first;
314 column_(nonZeroRowIndices.size(),
nullptr),
316 cellPool_(&(colSettings->cellConstructor))
318 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
319 "Constructor not available for chain columns, please specify the dimension of the chain.");
321 if constexpr (!Master_matrix::Option_list::is_z2){
322 operators_ = &(colSettings->operators);
326 if constexpr (Master_matrix::Option_list::is_z2) {
327 for (id_index
id : nonZeroRowIndices) {
328 _update_cell(
id, i++);
331 for (
const auto& p : nonZeroRowIndices) {
332 _update_cell(operators_->get_value(p.second), p.first, i++);
337 template <
class Master_matrix>
338 template <
class Container_type>
339 inline Vector_column<Master_matrix>::Vector_column(
const Container_type& nonZeroRowIndices,
340 dimension_type dimension,
341 Column_settings* colSettings)
345 if constexpr (Master_matrix::Option_list::is_z2) {
346 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : *std::prev(nonZeroRowIndices.end());
348 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : std::prev(nonZeroRowIndices.end())->first;
351 column_(nonZeroRowIndices.size(),
nullptr),
353 cellPool_(&(colSettings->cellConstructor))
355 if constexpr (!Master_matrix::Option_list::is_z2){
356 operators_ = &(colSettings->operators);
360 if constexpr (Master_matrix::Option_list::is_z2) {
361 for (id_index
id : nonZeroRowIndices) {
362 _update_cell(
id, i++);
365 for (
const auto& p : nonZeroRowIndices) {
366 _update_cell(operators_->get_value(p.second), p.first, i++);
371 template <
class Master_matrix>
372 template <
class Container_type,
class Row_container_type>
373 inline Vector_column<Master_matrix>::Vector_column(
375 const Container_type& nonZeroRowIndices,
376 dimension_type dimension,
377 Row_container_type* rowContainer,
378 Column_settings* colSettings)
379 : ra_opt(columnIndex, rowContainer),
382 if constexpr (Master_matrix::Option_list::is_z2) {
383 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : *std::prev(nonZeroRowIndices.end());
385 return nonZeroRowIndices.begin() == nonZeroRowIndices.end() ? -1 : std::prev(nonZeroRowIndices.end())->first;
388 column_(nonZeroRowIndices.size(),
nullptr),
390 cellPool_(&(colSettings->cellConstructor))
392 if constexpr (!Master_matrix::Option_list::is_z2){
393 operators_ = &(colSettings->operators);
397 if constexpr (Master_matrix::Option_list::is_z2) {
398 for (id_index
id : nonZeroRowIndices) {
399 _update_cell(
id, i++);
402 for (
const auto& p : nonZeroRowIndices) {
403 _update_cell(operators_->get_value(p.second), p.first, i++);
408 template <
class Master_matrix>
409 inline Vector_column<Master_matrix>::Vector_column(
const Vector_column& column,
410 Column_settings* colSettings)
412 dim_opt(static_cast<const dim_opt&>(column)),
413 chain_opt(static_cast<const chain_opt&>(column)),
414 column_(column.column_.size(), nullptr),
415 erasedValues_(column.erasedValues_),
416 operators_(colSettings == nullptr ? column.operators_ : nullptr),
417 cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor))
419 static_assert(!Master_matrix::Option_list::has_row_access,
420 "Simple copy constructor not available when row access option enabled. Please specify the new column "
421 "index and the row container.");
423 if constexpr (!Master_matrix::Option_list::is_z2){
424 if (colSettings !=
nullptr) operators_ = &(colSettings->operators);
428 for (
const Cell* cell : column.column_) {
429 if constexpr (Master_matrix::Option_list::is_z2) {
430 _update_cell(cell->get_row_index(), i++);
432 _update_cell(cell->get_element(), cell->get_row_index(), i++);
437 template <
class Master_matrix>
438 template <
class Row_container_type>
439 inline Vector_column<Master_matrix>::Vector_column(
const Vector_column& column, index columnIndex,
440 Row_container_type* rowContainer,
441 Column_settings* colSettings)
442 : ra_opt(columnIndex, rowContainer),
443 dim_opt(static_cast<const dim_opt&>(column)),
444 chain_opt(static_cast<const chain_opt&>(column)),
445 column_(column.column_.size(), nullptr),
446 erasedValues_(column.erasedValues_),
447 operators_(colSettings == nullptr ? column.operators_ : nullptr),
448 cellPool_(colSettings == nullptr ? column.cellPool_ : &(colSettings->cellConstructor))
450 if constexpr (!Master_matrix::Option_list::is_z2){
451 if (colSettings !=
nullptr) operators_ = &(colSettings->operators);
455 for (
const Cell* cell : column.column_) {
456 if constexpr (Master_matrix::Option_list::is_z2) {
457 _update_cell(cell->get_row_index(), i++);
459 _update_cell(cell->get_element(), cell->get_row_index(), i++);
464 template <
class Master_matrix>
465 inline Vector_column<Master_matrix>::Vector_column(Vector_column&& column) noexcept
466 : ra_opt(std::move(
static_cast<ra_opt&
>(column))),
467 dim_opt(std::move(
static_cast<dim_opt&
>(column))),
468 chain_opt(std::move(
static_cast<chain_opt&
>(column))),
469 column_(std::move(column.column_)),
470 erasedValues_(std::move(column.erasedValues_)),
471 operators_(std::exchange(column.operators_,
nullptr)),
472 cellPool_(std::exchange(column.cellPool_,
nullptr))
475 template <
class Master_matrix>
476 inline Vector_column<Master_matrix>::~Vector_column()
478 for (
auto* cell : column_) {
483 template <
class Master_matrix>
484 inline std::vector<typename Vector_column<Master_matrix>::Field_element_type>
485 Vector_column<Master_matrix>::get_content(
int columnLength)
const
487 if (columnLength < 0 && column_.size() > 0)
488 columnLength = column_.back()->get_row_index() + 1;
489 else if (columnLength < 0)
490 return std::vector<Field_element_type>();
492 std::vector<Field_element_type> container(columnLength, 0);
493 for (
auto it = column_.begin(); it != column_.end() && (*it)->get_row_index() <
static_cast<id_index
>(columnLength);
495 if constexpr (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type) {
496 if (erasedValues_.find((*it)->get_row_index()) != erasedValues_.end())
continue;
498 if constexpr (Master_matrix::Option_list::is_z2) {
499 container[(*it)->get_row_index()] = 1;
501 container[(*it)->get_row_index()] = (*it)->get_element();
507 template <
class Master_matrix>
508 inline bool Vector_column<Master_matrix>::is_non_zero(id_index rowIndex)
const
510 if constexpr (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type)
511 if (erasedValues_.find(rowIndex) != erasedValues_.end())
return false;
514 return std::binary_search(column_.begin(), column_.end(), &cell,
515 [](
const Cell* a,
const Cell* b) { return a->get_row_index() < b->get_row_index(); });
518 template <
class Master_matrix>
519 inline bool Vector_column<Master_matrix>::is_empty()
const
521 if constexpr (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type) {
522 return column_.size() == erasedValues_.size();
525 return column_.empty();
529 template <
class Master_matrix>
530 inline std::size_t Vector_column<Master_matrix>::size()
const
532 if constexpr (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type) {
533 return column_.size() - erasedValues_.size();
536 return column_.size();
540 template <
class Master_matrix>
541 template <
class Map_type>
542 inline void Vector_column<Master_matrix>::reorder(
const Map_type& valueMap,
543 [[maybe_unused]] index columnIndex)
545 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
546 "Method not available for chain columns.");
548 if (erasedValues_.empty()) {
549 for (Cell* cell : column_) {
550 if constexpr (Master_matrix::Option_list::has_row_access) {
551 ra_opt::unlink(cell);
552 if (columnIndex !=
static_cast<index
>(-1)) cell->set_column_index(columnIndex);
554 cell->set_row_index(valueMap.at(cell->get_row_index()));
555 if constexpr (Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access)
556 ra_opt::insert_cell(cell->get_row_index(), cell);
560 if constexpr (!Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) {
561 for (Cell* cell : column_) {
562 ra_opt::insert_cell(cell->get_row_index(), cell);
566 std::sort(column_.begin(), column_.end(), [](
const Cell* c1,
const Cell* c2) { return *c1 < *c2; });
568 Column_type newColumn;
569 for (Cell* cell : column_) {
570 if (erasedValues_.find(cell->get_row_index()) == erasedValues_.end()) {
571 if constexpr (Master_matrix::Option_list::has_row_access) {
572 ra_opt::unlink(cell);
573 if (columnIndex !=
static_cast<index
>(-1)) cell->set_column_index(columnIndex);
575 cell->set_row_index(valueMap.at(cell->get_row_index()));
576 newColumn.push_back(cell);
577 if constexpr (Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access)
578 ra_opt::insert_cell(cell->get_row_index(), cell);
584 if constexpr (!Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) {
585 for (Cell* cell : column_) {
586 ra_opt::insert_cell(cell->get_row_index(), cell);
589 std::sort(newColumn.begin(), newColumn.end(), [](
const Cell* c1,
const Cell* c2) { return *c1 < *c2; });
590 erasedValues_.clear();
591 column_.swap(newColumn);
595 template <
class Master_matrix>
596 inline void Vector_column<Master_matrix>::clear()
598 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
599 "Method not available for chain columns as a base element should not be empty.");
601 for (
auto* cell : column_) {
602 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::unlink(cell);
603 cellPool_->destroy(cell);
607 erasedValues_.clear();
610 template <
class Master_matrix>
611 inline void Vector_column<Master_matrix>::clear(id_index rowIndex)
613 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
614 "Method not available for chain columns.");
616 erasedValues_.insert(rowIndex);
619 template <
class Master_matrix>
620 inline typename Vector_column<Master_matrix>::id_index
621 Vector_column<Master_matrix>::get_pivot()
623 static_assert(Master_matrix::isNonBasic,
624 "Method not available for base columns.");
626 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
627 if (column_.empty())
return -1;
628 if (erasedValues_.empty())
return column_.back()->get_row_index();
630 auto it = erasedValues_.find(column_.back()->get_row_index());
631 while (!column_.empty() && it != erasedValues_.end()) {
632 erasedValues_.erase(it);
633 _delete_cell(column_.back());
635 if (!column_.empty()) it = erasedValues_.find(column_.back()->get_row_index());
638 if (column_.empty())
return -1;
639 return column_.back()->get_row_index();
641 return chain_opt::get_pivot();
645 template <
class Master_matrix>
646 inline typename Vector_column<Master_matrix>::Field_element_type
647 Vector_column<Master_matrix>::get_pivot_value()
649 static_assert(Master_matrix::isNonBasic,
650 "Method not available for base columns.");
652 if constexpr (Master_matrix::Option_list::is_z2) {
655 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
656 if (column_.empty())
return 0;
657 if (erasedValues_.empty())
return column_.back()->get_element();
659 auto it = erasedValues_.find(column_.back()->get_row_index());
660 while (!column_.empty() && it != erasedValues_.end()) {
661 erasedValues_.erase(it);
662 _delete_cell(column_.back());
664 if (!column_.empty()) it = erasedValues_.find(column_.back()->get_row_index());
667 if (column_.empty())
return 0;
668 return column_.back()->get_element();
670 if (chain_opt::get_pivot() ==
static_cast<id_index
>(-1))
return Field_element_type();
671 for (
const Cell* cell : column_) {
672 if (cell->get_row_index() == chain_opt::get_pivot())
return cell->get_element();
674 return Field_element_type();
679 template <
class Master_matrix>
680 inline typename Vector_column<Master_matrix>::iterator
681 Vector_column<Master_matrix>::begin() noexcept
683 return column_.begin();
686 template <
class Master_matrix>
687 inline typename Vector_column<Master_matrix>::const_iterator
688 Vector_column<Master_matrix>::begin() const noexcept
690 return column_.begin();
693 template <
class Master_matrix>
694 inline typename Vector_column<Master_matrix>::iterator
695 Vector_column<Master_matrix>::end() noexcept
697 return column_.end();
700 template <
class Master_matrix>
701 inline typename Vector_column<Master_matrix>::const_iterator
702 Vector_column<Master_matrix>::end() const noexcept
704 return column_.end();
707 template <
class Master_matrix>
708 inline typename Vector_column<Master_matrix>::reverse_iterator
709 Vector_column<Master_matrix>::rbegin() noexcept
711 return column_.rbegin();
714 template <
class Master_matrix>
715 inline typename Vector_column<Master_matrix>::const_reverse_iterator
716 Vector_column<Master_matrix>::rbegin() const noexcept
718 return column_.rbegin();
721 template <
class Master_matrix>
722 inline typename Vector_column<Master_matrix>::reverse_iterator
723 Vector_column<Master_matrix>::rend() noexcept
725 return column_.rend();
728 template <
class Master_matrix>
729 inline typename Vector_column<Master_matrix>::const_reverse_iterator
730 Vector_column<Master_matrix>::rend() const noexcept
732 return column_.rend();
735 template <
class Master_matrix>
736 template <
class Cell_range>
737 inline Vector_column<Master_matrix>& Vector_column<Master_matrix>::operator+=(
738 const Cell_range& column)
740 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Cell_range, Vector_column>),
741 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
743 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
744 "For chain columns, the given column cannot be constant.");
751 template <
class Master_matrix>
752 inline Vector_column<Master_matrix>& Vector_column<Master_matrix>::operator+=(
753 Vector_column& column)
755 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
758 chain_opt::swap_pivots(column);
759 dim_opt::swap_dimension(column);
768 template <
class Master_matrix>
769 inline Vector_column<Master_matrix>& Vector_column<Master_matrix>::operator*=(
772 if constexpr (Master_matrix::Option_list::is_z2) {
774 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
775 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
781 Field_element_type val = operators_->get_value(v);
783 if (val == Field_operators::get_additive_identity()) {
784 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
785 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
792 if (val == Field_operators::get_multiplicative_identity())
return *
this;
794 for (Cell* cell : column_) {
795 operators_->multiply_inplace(cell->get_element(), val);
796 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::update_cell(*cell);
803 template <
class Master_matrix>
804 template <
class Cell_range>
805 inline Vector_column<Master_matrix>& Vector_column<Master_matrix>::multiply_target_and_add(
806 const Field_element_type& val,
const Cell_range& column)
808 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Cell_range, Vector_column>),
809 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
811 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
812 "For chain columns, the given column cannot be constant.");
814 if constexpr (Master_matrix::Option_list::is_z2) {
822 _multiply_target_and_add(val, column);
828 template <
class Master_matrix>
829 inline Vector_column<Master_matrix>& Vector_column<Master_matrix>::multiply_target_and_add(
830 const Field_element_type& val, Vector_column& column)
832 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
834 if constexpr (Master_matrix::Option_list::is_z2) {
837 chain_opt::swap_pivots(column);
838 dim_opt::swap_dimension(column);
841 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
844 if (_multiply_target_and_add(val, column)) {
845 chain_opt::swap_pivots(column);
846 dim_opt::swap_dimension(column);
850 if constexpr (Master_matrix::Option_list::is_z2) {
858 _multiply_target_and_add(val, column);
865 template <
class Master_matrix>
866 template <
class Cell_range>
867 inline Vector_column<Master_matrix>& Vector_column<Master_matrix>::multiply_source_and_add(
868 const Cell_range& column,
const Field_element_type& val)
870 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Cell_range, Vector_column>),
871 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
873 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
874 "For chain columns, the given column cannot be constant.");
876 if constexpr (Master_matrix::Option_list::is_z2) {
881 _multiply_source_and_add(column, val);
887 template <
class Master_matrix>
888 inline Vector_column<Master_matrix>& Vector_column<Master_matrix>::multiply_source_and_add(
889 Vector_column& column,
const Field_element_type& val)
891 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
893 if constexpr (Master_matrix::Option_list::is_z2) {
896 chain_opt::swap_pivots(column);
897 dim_opt::swap_dimension(column);
901 if (_multiply_source_and_add(column, val)) {
902 chain_opt::swap_pivots(column);
903 dim_opt::swap_dimension(column);
907 if constexpr (Master_matrix::Option_list::is_z2) {
912 _multiply_source_and_add(column, val);
919 template <
class Master_matrix>
920 inline Vector_column<Master_matrix>& Vector_column<Master_matrix>::operator=(
921 const Vector_column& other)
923 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignement not enabled with row access option.");
925 dim_opt::operator=(other);
926 chain_opt::operator=(other);
928 auto tmpPool = cellPool_;
929 cellPool_ = other.cellPool_;
931 while (column_.size() > other.column_.size()) {
932 if (column_.back() !=
nullptr) {
933 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::unlink(column_.back());
934 tmpPool->destroy(column_.back());
939 column_.resize(other.column_.size(),
nullptr);
941 for (
const Cell* cell : other.column_) {
942 if (column_[i] !=
nullptr) {
943 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::unlink(column_[i]);
944 tmpPool->destroy(column_[i]);
946 if constexpr (Master_matrix::Option_list::is_z2) {
947 _update_cell(cell->get_row_index(), i++);
949 _update_cell(cell->get_element(), cell->get_row_index(), i++);
952 erasedValues_ = other.erasedValues_;
953 operators_ = other.operators_;
958 template <
class Master_matrix>
959 inline std::size_t Vector_column<Master_matrix>::compute_hash_value()
961 std::size_t seed = 0;
962 for (Cell* cell : column_) {
963 if (erasedValues_.find(cell->get_row_index()) == erasedValues_.end()){
964 seed ^= std::hash<unsigned int>()(cell->get_row_index() *
static_cast<unsigned int>(cell->get_element())) +
965 0x9e3779b9 + (seed << 6) + (seed >> 2);
971 template <
class Master_matrix>
972 inline void Vector_column<Master_matrix>::_delete_cell(Cell* cell)
974 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::unlink(cell);
975 cellPool_->destroy(cell);
978 template <
class Master_matrix>
979 inline void Vector_column<Master_matrix>::_delete_cell(
typename Column_type::iterator& it)
985 template <
class Master_matrix>
986 inline typename Vector_column<Master_matrix>::Cell* Vector_column<Master_matrix>::_insert_cell(
987 const Field_element_type& value, id_index rowIndex, Column_type& column)
989 if constexpr (Master_matrix::Option_list::has_row_access) {
990 Cell* newCell = cellPool_->construct(ra_opt::columnIndex_, rowIndex);
991 newCell->set_element(value);
992 column.push_back(newCell);
993 ra_opt::insert_cell(rowIndex, newCell);
996 Cell* newCell = cellPool_->construct(rowIndex);
997 newCell->set_element(value);
998 column.push_back(newCell);
1003 template <
class Master_matrix>
1004 inline void Vector_column<Master_matrix>::_insert_cell(id_index rowIndex, Column_type& column)
1006 if constexpr (Master_matrix::Option_list::has_row_access) {
1007 Cell* newCell = cellPool_->construct(ra_opt::columnIndex_, rowIndex);
1008 column.push_back(newCell);
1009 ra_opt::insert_cell(rowIndex, newCell);
1011 Cell* newCell = cellPool_->construct(rowIndex);
1012 column.push_back(newCell);
1016 template <
class Master_matrix>
1017 inline void Vector_column<Master_matrix>::_update_cell(
const Field_element_type& value,
1018 id_index rowIndex, index position)
1020 if constexpr (Master_matrix::Option_list::has_row_access) {
1021 Cell* newCell = cellPool_->construct(ra_opt::columnIndex_, rowIndex);
1022 newCell->set_element(value);
1023 column_[position] = newCell;
1024 ra_opt::insert_cell(rowIndex, newCell);
1026 column_[position] = cellPool_->construct(rowIndex);
1027 column_[position]->set_element(value);
1031 template <
class Master_matrix>
1032 inline void Vector_column<Master_matrix>::_update_cell(id_index rowIndex, index position)
1034 if constexpr (Master_matrix::Option_list::has_row_access) {
1035 Cell* newCell = cellPool_->construct(ra_opt::columnIndex_, rowIndex);
1036 column_[position] = newCell;
1037 ra_opt::insert_cell(rowIndex, newCell);
1039 column_[position] = cellPool_->construct(rowIndex);
1043 template <
class Master_matrix>
1044 template <
class Cell_range>
1045 inline bool Vector_column<Master_matrix>::_add(
const Cell_range& column)
1047 if (column.begin() == column.end())
return false;
1048 if (column_.empty()) {
1049 column_.resize(column.size());
1051 for (
const Cell& cell : column) {
1052 if constexpr (Master_matrix::Option_list::is_z2) {
1053 _update_cell(cell.get_row_index(), i++);
1055 _update_cell(cell.get_element(), cell.get_row_index(), i++);
1061 Column_type newColumn;
1062 newColumn.reserve(column_.size() + column.size());
1064 auto pivotIsZeroed = _generic_add(
1066 [&](Cell* cellTarget) { newColumn.push_back(cellTarget); },
1067 [&](
typename Cell_range::const_iterator& itSource,
1068 [[maybe_unused]]
const typename Column_type::iterator& itTarget) {
1069 if constexpr (Master_matrix::Option_list::is_z2) {
1070 _insert_cell(itSource->get_row_index(), newColumn);
1072 _insert_cell(itSource->get_element(), itSource->get_row_index(), newColumn);
1075 [&](Field_element_type& targetElement,
typename Cell_range::const_iterator& itSource) {
1076 if constexpr (!Master_matrix::Option_list::is_z2)
1077 operators_->add_inplace(targetElement, itSource->get_element());
1079 [&](Cell* cellTarget) { newColumn.push_back(cellTarget); });
1081 column_.swap(newColumn);
1083 return pivotIsZeroed;
1086 template <
class Master_matrix>
1087 template <
class Cell_range>
1088 inline bool Vector_column<Master_matrix>::_multiply_target_and_add(
const Field_element_type& val,
1089 const Cell_range& column)
1092 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1093 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
1099 if (column_.empty()) {
1100 column_.resize(column.size());
1102 for (
const Cell& cell : column) {
1103 if constexpr (Master_matrix::Option_list::is_z2) {
1104 _update_cell(cell.get_row_index(), i++);
1106 _update_cell(cell.get_element(), cell.get_row_index(), i++);
1109 if constexpr (std::is_same_v<Cell_range, Vector_column<Master_matrix> >) erasedValues_ = column.erasedValues_;
1113 Column_type newColumn;
1114 newColumn.reserve(column_.size() + column.size());
1116 auto pivotIsZeroed = _generic_add(
1118 [&](Cell* cellTarget) {
1119 operators_->multiply_inplace(cellTarget->get_element(), val);
1120 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::update_cell(*cellTarget);
1121 newColumn.push_back(cellTarget);
1123 [&](
typename Cell_range::const_iterator& itSource,
const typename Column_type::iterator& itTarget) {
1124 _insert_cell(itSource->get_element(), itSource->get_row_index(), newColumn);
1126 [&](Field_element_type& targetElement,
typename Cell_range::const_iterator& itSource) {
1127 operators_->multiply_and_add_inplace_front(targetElement, val, itSource->get_element());
1129 [&](Cell* cellTarget) { newColumn.push_back(cellTarget); });
1131 column_.swap(newColumn);
1133 return pivotIsZeroed;
1136 template <
class Master_matrix>
1137 template <
class Cell_range>
1138 inline bool Vector_column<Master_matrix>::_multiply_source_and_add(
const Cell_range& column,
1139 const Field_element_type& val)
1141 if (val == 0u || column.begin() == column.end()) {
1145 Column_type newColumn;
1146 newColumn.reserve(column_.size() + column.size());
1148 auto pivotIsZeroed = _generic_add(
1150 [&](Cell* cellTarget) { newColumn.push_back(cellTarget); },
1151 [&](
typename Cell_range::const_iterator& itSource,
const typename Column_type::iterator& itTarget) {
1152 Cell* newCell = _insert_cell(itSource->get_element(), itSource->get_row_index(), newColumn);
1153 operators_->multiply_inplace(newCell->get_element(), val);
1154 if constexpr (Master_matrix::Option_list::has_row_access) ra_opt::update_cell(*newCell);
1156 [&](Field_element_type& targetElement,
typename Cell_range::const_iterator& itSource) {
1157 operators_->multiply_and_add_inplace_back(itSource->get_element(), val, targetElement);
1159 [&](Cell* cellTarget) { newColumn.push_back(cellTarget); });
1161 column_.swap(newColumn);
1163 return pivotIsZeroed;
1166 template <
class Master_matrix>
1167 template <
class Cell_range,
typename F1,
typename F2,
typename F3,
typename F4>
1168 inline bool Vector_column<Master_matrix>::_generic_add(
const Cell_range& column,
1169 F1&& process_target,
1170 F2&& process_source,
1171 F3&& update_target1,
1172 F4&& update_target2)
1174 auto updateTargetIterator = [&](
typename Column_type::iterator& itTarget){
1175 if constexpr (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type){
1176 while (itTarget != column_.end() && erasedValues_.find((*itTarget)->get_row_index()) != erasedValues_.end()) {
1177 _delete_cell(*itTarget);
1182 auto updateSourceIterator = [&](
typename Cell_range::const_iterator& itSource){
1183 if constexpr (std::is_same_v<Cell_range, Vector_column<Master_matrix> > &&
1184 (!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type)) {
1185 while (itSource != column.end() &&
1186 column.erasedValues_.find(itSource->get_row_index()) != column.erasedValues_.end())
1191 bool pivotIsZeroed =
false;
1193 auto itTarget = column_.begin();
1194 auto itSource = column.begin();
1195 while (itTarget != column_.end() && itSource != column.end()) {
1196 updateTargetIterator(itTarget);
1197 updateSourceIterator(itSource);
1198 if (itTarget == column_.end() || itSource == column.end())
break;
1200 _generic_merge_cell_to_column(*
this,
1202 process_target, process_source, update_target1, update_target2,
1206 while (itSource != column.end()) {
1207 updateSourceIterator(itSource);
1208 if (itSource == column.end())
break;
1210 process_source(itSource, column_.end());
1214 while (itTarget != column_.end()) {
1215 updateTargetIterator(itTarget);
1216 if (itTarget == column_.end())
break;
1218 process_target(*itTarget);
1222 erasedValues_.clear();
1224 return pivotIsZeroed;
1238 template <
class Master_matrix>
1239 struct std::hash<
Gudhi::persistence_matrix::Vector_column<Master_matrix> >
1242 return column.compute_hash_value();
Column class following the PersistenceMatrixColumn concept.
Definition: vector_column.h:53
Contains helper methods for column addition and column hasher.
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