18#ifndef PM_NAIVE_VECTOR_COLUMN_H
19#define PM_NAIVE_VECTOR_COLUMN_H
27#include <boost/iterator/indirect_iterator.hpp>
28#include <boost/container/small_vector.hpp>
34namespace persistence_matrix {
47template <
class Master_matrix,
class Support>
53 using Master = Master_matrix;
54 using Index =
typename Master_matrix::Index;
55 using ID_index =
typename Master_matrix::ID_index;
56 using Dimension =
typename Master_matrix::Dimension;
57 using Field_element =
typename Master_matrix::Element;
58 using Entry =
typename Master_matrix::Matrix_entry;
59 using Column_settings =
typename Master_matrix::Column_settings;
62 using Field_operators =
typename Master_matrix::Field_operators;
63 using Column_support = Support;
64 using Entry_constructor =
typename Master_matrix::Entry_constructor;
67 using iterator = boost::indirect_iterator<typename Column_support::iterator>;
68 using const_iterator = boost::indirect_iterator<typename Column_support::const_iterator>;
69 using reverse_iterator = boost::indirect_iterator<typename Column_support::reverse_iterator>;
70 using const_reverse_iterator = boost::indirect_iterator<typename Column_support::const_reverse_iterator>;
73 template <
class Container =
typename Master_matrix::Boundary>
75 template <
class Container =
typename Master_matrix::Boundary,
class Row_container>
77 const Container& nonZeroRowIndices,
78 Row_container* rowContainer,
79 Column_settings* colSettings);
80 template <
class Container =
typename Master_matrix::Boundary>
81 Naive_vector_column(
const Container& nonZeroChainRowIndices, Dimension dimension, Column_settings* colSettings);
82 template <
class Container =
typename Master_matrix::Boundary,
class Row_container>
84 const Container& nonZeroChainRowIndices,
86 Row_container* rowContainer,
87 Column_settings* colSettings);
89 template <
class Row_container>
92 Row_container* rowContainer,
93 Column_settings* colSettings =
nullptr);
97 std::vector<Field_element> get_content(
int columnLength = -1)
const;
98 bool is_non_zero(ID_index rowIndex)
const;
99 bool is_empty()
const;
100 std::size_t size()
const;
102 template <
class Row_index_map>
103 void reorder(
const Row_index_map& valueMap,
104 [[maybe_unused]] Index columnIndex = Master_matrix::template get_null_value<Index>());
106 void clear(ID_index rowIndex);
108 ID_index get_pivot()
const;
109 Field_element get_pivot_value()
const;
111 iterator begin()
noexcept;
112 const_iterator begin()
const noexcept;
113 iterator end()
noexcept;
114 const_iterator end()
const noexcept;
115 reverse_iterator rbegin()
noexcept;
116 const_reverse_iterator rbegin()
const noexcept;
117 reverse_iterator rend()
noexcept;
118 const_reverse_iterator rend()
const noexcept;
120 template <
class Entry_range>
127 template <
class Entry_range>
128 Naive_vector_column& multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
131 template <
class Entry_range>
132 Naive_vector_column& multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
135 void push_back(
const Entry& entry);
138 if (&c1 == &c2)
return true;
139 if (c1.column_.size() != c2.column_.size())
return false;
141 auto it1 = c1.column_.begin();
142 auto it2 = c2.column_.begin();
143 while (it1 != c1.column_.end() && it2 != c2.column_.end()) {
144 if constexpr (Master_matrix::Option_list::is_z2) {
145 if ((*it1)->get_row_index() != (*it2)->get_row_index())
return false;
147 if ((*it1)->get_row_index() != (*it2)->get_row_index() || (*it1)->get_element() != (*it2)->get_element())
157 if (&c1 == &c2)
return false;
159 auto it1 = c1.column_.begin();
160 auto it2 = c2.column_.begin();
161 while (it1 != c1.column_.end() && it2 != c2.column_.end()) {
162 if ((*it1)->get_row_index() != (*it2)->get_row_index())
return (*it1)->get_row_index() < (*it2)->get_row_index();
163 if constexpr (!Master_matrix::Option_list::is_z2) {
164 if ((*it1)->get_element() != (*it2)->get_element())
return (*it1)->get_element() < (*it2)->get_element();
169 return it2 != c2.column_.end();
182 col1.column_.swap(col2.column_);
183 std::swap(col1.operators_, col2.operators_);
184 std::swap(col1.entryPool_, col2.entryPool_);
192 Column_support column_;
193 Field_operators* operators_;
194 Entry_constructor* entryPool_;
196 template <
class Column,
class Entry_iterator,
typename F1,
typename F2,
typename F3,
typename F4>
197 friend void _generic_merge_entry_to_column(Column& targetColumn,
198 Entry_iterator& itSource,
199 typename Column::Column_support::iterator& itTarget,
204 bool& pivotIsZeroed);
205 template <
class Column,
class Entry_range,
typename F1,
typename F2,
typename F3,
typename F4,
typename F5>
206 friend bool _generic_add_to_column(
const Entry_range& source,
207 Column& targetColumn,
214 void _delete_entry(Entry* entry);
215 void _delete_entry(
typename Column_support::iterator& it);
216 Entry* _insert_entry(
const Field_element& value, ID_index rowIndex, Column_support& column);
217 void _insert_entry(ID_index rowIndex, Column_support& column);
218 void _update_entry(
const Field_element& value, ID_index rowIndex, Index position);
219 void _update_entry(ID_index rowIndex, Index position);
220 template <
class Entry_range>
221 bool _add(
const Entry_range& column);
222 template <
class Entry_range>
223 bool _multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
224 template <
class Entry_range>
225 bool _multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
228template <
class Master_matrix>
230template <
class Master_matrix>
234template <
class Master_matrix,
class Support>
240 entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor))
242 if (operators_ ==
nullptr && entryPool_ ==
nullptr)
244 if constexpr (!Master_matrix::Option_list::is_z2) {
245 operators_ = &(colSettings->operators);
249template <
class Master_matrix,
class Support>
250template <
class Container>
251inline Naive_vector_column<Master_matrix,Support>::Naive_vector_column(
const Container& nonZeroRowIndices,
252 Column_settings* colSettings)
254 Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
256 column_(nonZeroRowIndices.size(), nullptr),
258 entryPool_(&(colSettings->entryConstructor))
260 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
261 "Constructor not available for chain columns, please specify the dimension of the chain.");
264 if constexpr (Master_matrix::Option_list::is_z2) {
265 for (ID_index
id : nonZeroRowIndices) {
266 _update_entry(
id, i++);
269 operators_ = &(colSettings->operators);
270 for (
const auto& p : nonZeroRowIndices) {
271 _update_entry(operators_->get_value(p.second), p.first, i++);
276template <
class Master_matrix,
class Support>
277template <
class Container,
class Row_container>
278inline Naive_vector_column<Master_matrix,Support>::Naive_vector_column(Index columnIndex,
279 const Container& nonZeroRowIndices,
280 Row_container* rowContainer,
281 Column_settings* colSettings)
282 : RA_opt(columnIndex, rowContainer),
283 Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
285 if constexpr (Master_matrix::Option_list::is_z2) {
286 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
287 ? Master_matrix::template get_null_value<ID_index>()
288 : *
std::prev(nonZeroRowIndices.end());
290 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
291 ? Master_matrix::template get_null_value<ID_index>()
292 :
std::prev(nonZeroRowIndices.end())->first;
295 column_(nonZeroRowIndices.size(),
nullptr),
297 entryPool_(&(colSettings->entryConstructor))
299 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
300 "Constructor not available for chain columns, please specify the dimension of the chain.");
303 if constexpr (Master_matrix::Option_list::is_z2) {
304 for (ID_index
id : nonZeroRowIndices) {
305 _update_entry(
id, i++);
308 operators_ = &(colSettings->operators);
309 for (
const auto& p : nonZeroRowIndices) {
310 _update_entry(operators_->get_value(p.second), p.first, i++);
315template <
class Master_matrix,
class Support>
316template <
class Container>
317inline Naive_vector_column<Master_matrix,Support>::Naive_vector_column(
const Container& nonZeroRowIndices,
319 Column_settings* colSettings)
323 if constexpr (Master_matrix::Option_list::is_z2) {
324 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
325 ? Master_matrix::template get_null_value<ID_index>()
326 : *
std::prev(nonZeroRowIndices.end());
328 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
329 ? Master_matrix::template get_null_value<ID_index>()
330 :
std::prev(nonZeroRowIndices.end())->first;
333 column_(nonZeroRowIndices.size(),
nullptr),
335 entryPool_(&(colSettings->entryConstructor))
338 if constexpr (Master_matrix::Option_list::is_z2) {
339 for (ID_index
id : nonZeroRowIndices) {
340 _update_entry(
id, i++);
343 operators_ = &(colSettings->operators);
344 for (
const auto& p : nonZeroRowIndices) {
345 _update_entry(operators_->get_value(p.second), p.first, i++);
350template <
class Master_matrix,
class Support>
351template <
class Container,
class Row_container>
352inline Naive_vector_column<Master_matrix,Support>::Naive_vector_column(Index columnIndex,
353 const Container& nonZeroRowIndices,
355 Row_container* rowContainer,
356 Column_settings* colSettings)
357 : RA_opt(columnIndex, rowContainer),
360 if constexpr (Master_matrix::Option_list::is_z2) {
361 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
362 ? Master_matrix::template get_null_value<ID_index>()
363 : *
std::prev(nonZeroRowIndices.end());
365 return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
366 ? Master_matrix::template get_null_value<ID_index>()
367 :
std::prev(nonZeroRowIndices.end())->first;
370 column_(nonZeroRowIndices.size(),
nullptr),
372 entryPool_(&(colSettings->entryConstructor))
375 if constexpr (Master_matrix::Option_list::is_z2) {
376 for (ID_index
id : nonZeroRowIndices) {
377 _update_entry(
id, i++);
380 operators_ = &(colSettings->operators);
381 for (
const auto& p : nonZeroRowIndices) {
382 _update_entry(operators_->get_value(p.second), p.first, i++);
387template <
class Master_matrix,
class Support>
388inline Naive_vector_column<Master_matrix,Support>::Naive_vector_column(
const Naive_vector_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_.size(), nullptr),
394 operators_(colSettings == nullptr ? column.operators_ : nullptr),
395 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
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);
406 for (
const Entry* entry : column.column_) {
407 if constexpr (Master_matrix::Option_list::is_z2) {
408 _update_entry(entry->get_row_index(), i++);
410 _update_entry(entry->get_element(), entry->get_row_index(), i++);
415template <
class Master_matrix,
class Support>
416template <
class Row_container>
417inline Naive_vector_column<Master_matrix,Support>::Naive_vector_column(
const Naive_vector_column& column,
419 Row_container* rowContainer,
420 Column_settings* colSettings)
421 : RA_opt(columnIndex, rowContainer),
422 Dim_opt(static_cast<const Dim_opt&>(column)),
423 Chain_opt(static_cast<const Chain_opt&>(column)),
424 column_(column.column_.size(), nullptr),
425 operators_(colSettings == nullptr ? column.operators_ : nullptr),
426 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
428 if constexpr (!Master_matrix::Option_list::is_z2) {
429 if (colSettings !=
nullptr) operators_ = &(colSettings->operators);
433 for (
const Entry* entry : column.column_) {
434 if constexpr (Master_matrix::Option_list::is_z2) {
435 _update_entry(entry->get_row_index(), i++);
437 _update_entry(entry->get_element(), entry->get_row_index(), i++);
442template <
class Master_matrix,
class Support>
443inline Naive_vector_column<Master_matrix,Support>::Naive_vector_column(Naive_vector_column&& column) noexcept
444 : RA_opt(std::move(
static_cast<RA_opt&
>(column))),
445 Dim_opt(std::move(
static_cast<Dim_opt&
>(column))),
446 Chain_opt(std::move(
static_cast<Chain_opt&
>(column))),
447 column_(std::move(column.column_)),
448 operators_(std::exchange(column.operators_,
nullptr)),
449 entryPool_(std::exchange(column.entryPool_,
nullptr))
452template <
class Master_matrix,
class Support>
453inline Naive_vector_column<Master_matrix,Support>::~Naive_vector_column()
455 for (
auto* entry : column_) {
456 _delete_entry(entry);
460template <
class Master_matrix,
class Support>
461inline std::vector<typename Naive_vector_column<Master_matrix,Support>::Field_element>
462Naive_vector_column<Master_matrix,Support>::get_content(
int columnLength)
const
464 if (columnLength < 0 && column_.size() > 0)
465 columnLength = column_.back()->get_row_index() + 1;
466 else if (columnLength < 0)
467 return std::vector<Field_element>();
469 std::vector<Field_element> container(columnLength, 0);
470 for (
auto it = column_.begin(); it != column_.end() && (*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();
481template <
class Master_matrix,
class Support>
482inline bool Naive_vector_column<Master_matrix,Support>::is_non_zero(ID_index rowIndex)
const
484 Entry entry(rowIndex);
485 return std::binary_search(column_.begin(), column_.end(), &entry, [](
const Entry* a,
const Entry* b) {
486 return a->get_row_index() < b->get_row_index();
490template <
class Master_matrix,
class Support>
491inline bool Naive_vector_column<Master_matrix,Support>::is_empty()
const
493 return column_.empty();
496template <
class Master_matrix,
class Support>
497inline std::size_t Naive_vector_column<Master_matrix,Support>::size()
const
499 return column_.size();
502template <
class Master_matrix,
class Support>
503template <
class Row_index_map>
504inline void Naive_vector_column<Master_matrix,Support>::reorder(
const Row_index_map& valueMap,
505 [[maybe_unused]] Index columnIndex)
507 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
508 "Method not available for chain columns.");
510 for (Entry* entry : column_) {
511 if constexpr (Master_matrix::Option_list::has_row_access) {
512 RA_opt::unlink(entry);
513 if (columnIndex != Master_matrix::template get_null_value<Index>()) entry->set_column_index(columnIndex);
515 entry->set_row_index(valueMap.at(entry->get_row_index()));
516 if constexpr (Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access)
517 RA_opt::insert_entry(entry->get_row_index(), entry);
521 if constexpr (!Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) {
522 for (Entry* entry : column_) {
523 RA_opt::insert_entry(entry->get_row_index(), entry);
527 std::sort(column_.begin(), column_.end(), [](
const Entry* c1,
const Entry* c2) { return *c1 < *c2; });
530template <
class Master_matrix,
class Support>
531inline void Naive_vector_column<Master_matrix,Support>::clear()
533 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
534 "Method not available for chain columns as a base element should not be empty.");
536 for (
auto* entry : column_) {
537 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
538 entryPool_->destroy(entry);
544template <
class Master_matrix,
class Support>
545inline void Naive_vector_column<Master_matrix,Support>::clear(ID_index rowIndex)
547 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
548 "Method not available for chain columns.");
550 auto it = column_.begin();
551 while (it != column_.end() && (*it)->get_row_index() != rowIndex) ++it;
552 if (it != column_.end()) {
558template <
class Master_matrix,
class Support>
559inline typename Naive_vector_column<Master_matrix,Support>::ID_index Naive_vector_column<Master_matrix,Support>::get_pivot()
const
561 static_assert(Master_matrix::isNonBasic,
562 "Method not available for base columns.");
564 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
565 return column_.empty() ? Master_matrix::template get_null_value<ID_index>() : column_.back()->get_row_index();
567 return Chain_opt::get_pivot();
571template <
class Master_matrix,
class Support>
572inline typename Naive_vector_column<Master_matrix,Support>::Field_element Naive_vector_column<Master_matrix,Support>::get_pivot_value()
575 static_assert(Master_matrix::isNonBasic,
576 "Method not available for base columns.");
578 if constexpr (Master_matrix::Option_list::is_z2) {
581 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
582 return column_.empty() ? Field_element() : column_.back()->get_element();
584 if (Chain_opt::get_pivot() == Master_matrix::template get_null_value<ID_index>())
return Field_element();
585 for (
const Entry* entry : column_) {
586 if (entry->get_row_index() == Chain_opt::get_pivot())
return entry->get_element();
588 return Field_element();
593template <
class Master_matrix,
class Support>
594inline typename Naive_vector_column<Master_matrix,Support>::iterator Naive_vector_column<Master_matrix,Support>::begin() noexcept
596 return column_.begin();
599template <
class Master_matrix,
class Support>
600inline typename Naive_vector_column<Master_matrix,Support>::const_iterator Naive_vector_column<Master_matrix,Support>::begin()
603 return column_.begin();
606template <
class Master_matrix,
class Support>
607inline typename Naive_vector_column<Master_matrix,Support>::iterator Naive_vector_column<Master_matrix,Support>::end() noexcept
609 return column_.end();
612template <
class Master_matrix,
class Support>
613inline typename Naive_vector_column<Master_matrix,Support>::const_iterator Naive_vector_column<Master_matrix,Support>::end()
616 return column_.end();
619template <
class Master_matrix,
class Support>
620inline typename Naive_vector_column<Master_matrix,Support>::reverse_iterator
621Naive_vector_column<Master_matrix,Support>::rbegin() noexcept
623 return column_.rbegin();
626template <
class Master_matrix,
class Support>
627inline typename Naive_vector_column<Master_matrix,Support>::const_reverse_iterator Naive_vector_column<Master_matrix,Support>::rbegin()
630 return column_.rbegin();
633template <
class Master_matrix,
class Support>
634inline typename Naive_vector_column<Master_matrix,Support>::reverse_iterator
635Naive_vector_column<Master_matrix,Support>::rend() noexcept
637 return column_.rend();
640template <
class Master_matrix,
class Support>
641inline typename Naive_vector_column<Master_matrix,Support>::const_reverse_iterator Naive_vector_column<Master_matrix,Support>::rend()
644 return column_.rend();
647template <
class Master_matrix,
class Support>
648template <
class Entry_range>
649inline Naive_vector_column<Master_matrix,Support>& Naive_vector_column<Master_matrix,Support>::operator+=(
const Entry_range& column)
651 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Naive_vector_column>),
652 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
654 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
655 "For chain columns, the given column cannot be constant.");
662template <
class Master_matrix,
class Support>
663inline Naive_vector_column<Master_matrix,Support>& Naive_vector_column<Master_matrix,Support>::operator+=(Naive_vector_column& column)
665 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
668 Chain_opt::swap_pivots(column);
669 Dim_opt::swap_dimension(column);
678template <
class Master_matrix,
class Support>
679inline Naive_vector_column<Master_matrix,Support>& Naive_vector_column<Master_matrix,Support>::operator*=(
unsigned int v)
681 if constexpr (Master_matrix::Option_list::is_z2) {
683 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
684 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
690 Field_element val = operators_->get_value(v);
692 if (val == Field_operators::get_additive_identity()) {
693 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
694 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
701 if (val == Field_operators::get_multiplicative_identity())
return *
this;
703 for (Entry* entry : column_) {
704 operators_->multiply_inplace(entry->get_element(), val);
705 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entry);
712template <
class Master_matrix,
class Support>
713template <
class Entry_range>
714inline Naive_vector_column<Master_matrix,Support>& Naive_vector_column<Master_matrix,Support>::multiply_target_and_add(
715 const Field_element& val,
const Entry_range& column)
717 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Naive_vector_column>),
718 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
720 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
721 "For chain columns, the given column cannot be constant.");
723 if constexpr (Master_matrix::Option_list::is_z2) {
731 _multiply_target_and_add(val, column);
737template <
class Master_matrix,
class Support>
738inline Naive_vector_column<Master_matrix,Support>& Naive_vector_column<Master_matrix,Support>::multiply_target_and_add(
739 const Field_element& val, Naive_vector_column& column)
741 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
743 if constexpr (Master_matrix::Option_list::is_z2) {
746 Chain_opt::swap_pivots(column);
747 Dim_opt::swap_dimension(column);
750 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
753 if (_multiply_target_and_add(val, column)) {
754 Chain_opt::swap_pivots(column);
755 Dim_opt::swap_dimension(column);
759 if constexpr (Master_matrix::Option_list::is_z2) {
767 _multiply_target_and_add(val, column);
774template <
class Master_matrix,
class Support>
775template <
class Entry_range>
776inline Naive_vector_column<Master_matrix,Support>& Naive_vector_column<Master_matrix,Support>::multiply_source_and_add(
777 const Entry_range& column,
const Field_element& val)
779 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Naive_vector_column>),
780 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
782 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
783 "For chain columns, the given column cannot be constant.");
785 if constexpr (Master_matrix::Option_list::is_z2) {
790 _multiply_source_and_add(column, val);
796template <
class Master_matrix,
class Support>
797inline Naive_vector_column<Master_matrix,Support>& Naive_vector_column<Master_matrix,Support>::multiply_source_and_add(
798 Naive_vector_column& column,
const Field_element& val)
800 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
802 if constexpr (Master_matrix::Option_list::is_z2) {
805 Chain_opt::swap_pivots(column);
806 Dim_opt::swap_dimension(column);
810 if (_multiply_source_and_add(column, val)) {
811 Chain_opt::swap_pivots(column);
812 Dim_opt::swap_dimension(column);
816 if constexpr (Master_matrix::Option_list::is_z2) {
821 _multiply_source_and_add(column, val);
828template <
class Master_matrix,
class Support>
829inline void Naive_vector_column<Master_matrix,Support>::push_back(
const Entry& entry)
831 static_assert(Master_matrix::Option_list::is_of_boundary_type,
"`push_back` is not available for Chain matrices.");
833 GUDHI_CHECK(entry.get_row_index() > get_pivot(),
"The new row index has to be higher than the current pivot.");
835 if constexpr (Master_matrix::Option_list::is_z2) {
836 _insert_entry(entry.get_row_index(), column_);
838 _insert_entry(entry.get_element(), entry.get_row_index(), column_);
842template <
class Master_matrix,
class Support>
843inline Naive_vector_column<Master_matrix,Support>& Naive_vector_column<Master_matrix,Support>::operator=(
844 const Naive_vector_column& other)
846 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
848 Dim_opt::operator=(other);
849 Chain_opt::operator=(other);
851 auto tmpPool = entryPool_;
852 entryPool_ = other.entryPool_;
854 while (column_.size() > other.column_.size()) {
855 if (column_.back() ==
nullptr) {
856 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(column_.back());
857 tmpPool->destroy(column_.back());
862 column_.resize(other.column_.size(),
nullptr);
864 for (
const Entry* entry : other.column_) {
865 if (column_[i] !=
nullptr) {
866 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(column_[i]);
867 tmpPool->destroy(column_[i]);
869 if constexpr (Master_matrix::Option_list::is_z2) {
870 _update_entry(entry->get_row_index(), i++);
872 _update_entry(entry->get_element(), entry->get_row_index(), i++);
876 operators_ = other.operators_;
881template <
class Master_matrix,
class Support>
882inline void Naive_vector_column<Master_matrix,Support>::_delete_entry(Entry* entry)
884 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
885 entryPool_->destroy(entry);
888template <
class Master_matrix,
class Support>
889inline void Naive_vector_column<Master_matrix,Support>::_delete_entry(
typename Column_support::iterator& it)
895template <
class Master_matrix,
class Support>
896inline typename Naive_vector_column<Master_matrix,Support>::Entry* Naive_vector_column<Master_matrix,Support>::_insert_entry(
897 const Field_element& value, ID_index rowIndex, Column_support& column)
899 if constexpr (Master_matrix::Option_list::has_row_access) {
900 Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex);
901 newEntry->set_element(value);
902 column.push_back(newEntry);
903 RA_opt::insert_entry(rowIndex, newEntry);
906 Entry* newEntry = entryPool_->construct(rowIndex);
907 column.push_back(newEntry);
908 newEntry->set_element(value);
913template <
class Master_matrix,
class Support>
914inline void Naive_vector_column<Master_matrix,Support>::_insert_entry(ID_index rowIndex, Column_support& column)
916 if constexpr (Master_matrix::Option_list::has_row_access) {
917 Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex);
918 column.push_back(newEntry);
919 RA_opt::insert_entry(rowIndex, newEntry);
921 column.push_back(entryPool_->construct(rowIndex));
925template <
class Master_matrix,
class Support>
926inline void Naive_vector_column<Master_matrix, Support>::_update_entry(
const Field_element& value,
930 if constexpr (Master_matrix::Option_list::has_row_access) {
931 Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex);
932 newEntry->set_element(value);
933 column_[position] = newEntry;
934 RA_opt::insert_entry(rowIndex, newEntry);
936 column_[position] = entryPool_->construct(rowIndex);
937 column_[position]->set_element(value);
941template <
class Master_matrix,
class Support>
942inline void Naive_vector_column<Master_matrix,Support>::_update_entry(ID_index rowIndex, Index position)
944 if constexpr (Master_matrix::Option_list::has_row_access) {
945 Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex);
946 column_[position] = newEntry;
947 RA_opt::insert_entry(rowIndex, newEntry);
949 column_[position] = entryPool_->construct(rowIndex);
953template <
class Master_matrix,
class Support>
954template <
class Entry_range>
955inline bool Naive_vector_column<Master_matrix,Support>::_add(
const Entry_range& column)
957 if (column.begin() == column.end())
return false;
958 if (column_.empty()) {
959 column_.resize(column.size());
961 for (
const Entry& entry : column) {
962 if constexpr (Master_matrix::Option_list::is_z2) {
963 _update_entry(entry.get_row_index(), i++);
965 _update_entry(entry.get_element(), entry.get_row_index(), i++);
971 Column_support newColumn;
972 newColumn.reserve(column_.size() + column.size());
974 auto pivotIsZeroed = _generic_add_to_column(
977 [&](Entry* entryTarget) { newColumn.push_back(entryTarget); },
978 [&](
typename Entry_range::const_iterator& itSource,
979 [[maybe_unused]]
const typename Column_support::iterator& itTarget) {
980 if constexpr (Master_matrix::Option_list::is_z2) {
981 _insert_entry(itSource->get_row_index(), newColumn);
983 _insert_entry(itSource->get_element(), itSource->get_row_index(), newColumn);
986 [&](Field_element& targetElement,
typename Entry_range::const_iterator& itSource) {
987 if constexpr (!Master_matrix::Option_list::is_z2)
988 operators_->add_inplace(targetElement, itSource->get_element());
990 [&](Entry* entryTarget) { newColumn.push_back(entryTarget); },
991 [&](
typename Column_support::iterator& itTarget) {
992 while (itTarget != column_.end()) {
993 newColumn.push_back(*itTarget);
998 column_.swap(newColumn);
1000 return pivotIsZeroed;
1003template <
class Master_matrix,
class Support>
1004template <
class Entry_range>
1005inline bool Naive_vector_column<Master_matrix,Support>::_multiply_target_and_add(
const Field_element& val,
1006 const Entry_range& column)
1009 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
1010 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
1016 if (column_.empty()) {
1017 column_.resize(column.size());
1019 for (
const Entry& entry : column) {
1020 if constexpr (Master_matrix::Option_list::is_z2) {
1021 _update_entry(entry.get_row_index(), i++);
1023 _update_entry(entry.get_element(), entry.get_row_index(), i++);
1029 Column_support newColumn;
1030 newColumn.reserve(column_.size() + column.size());
1032 auto pivotIsZeroed = _generic_add_to_column(
1035 [&](Entry* entryTarget) {
1036 operators_->multiply_inplace(entryTarget->get_element(), val);
1037 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entryTarget);
1038 newColumn.push_back(entryTarget);
1040 [&](
typename Entry_range::const_iterator& itSource,
const typename Column_support::iterator& itTarget) {
1041 _insert_entry(itSource->get_element(), itSource->get_row_index(), newColumn);
1043 [&](Field_element& targetElement,
typename Entry_range::const_iterator& itSource) {
1044 operators_->multiply_and_add_inplace_front(targetElement, val, itSource->get_element());
1046 [&](Entry* entryTarget) { newColumn.push_back(entryTarget); },
1047 [&](
typename Column_support::iterator& itTarget) {
1048 while (itTarget != column_.end()) {
1049 operators_->multiply_inplace((*itTarget)->get_element(), val);
1050 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(**itTarget);
1051 newColumn.push_back(*itTarget);
1056 column_.swap(newColumn);
1058 return pivotIsZeroed;
1061template <
class Master_matrix,
class Support>
1062template <
class Entry_range>
1063inline bool Naive_vector_column<Master_matrix,Support>::_multiply_source_and_add(
const Entry_range& column,
1064 const Field_element& val)
1066 if (val == 0u || column.begin() == column.end()) {
1070 Column_support newColumn;
1071 newColumn.reserve(column_.size() + column.size());
1073 auto pivotIsZeroed = _generic_add_to_column(
1076 [&](Entry* entryTarget) { newColumn.push_back(entryTarget); },
1077 [&](
typename Entry_range::const_iterator& itSource,
const typename Column_support::iterator& itTarget) {
1078 Entry* newEntry = _insert_entry(itSource->get_element(), itSource->get_row_index(), newColumn);
1079 operators_->multiply_inplace(newEntry->get_element(), val);
1080 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*newEntry);
1082 [&](Field_element& targetElement,
typename Entry_range::const_iterator& itSource) {
1083 operators_->multiply_and_add_inplace_back(itSource->get_element(), val, targetElement);
1085 [&](Entry* entryTarget) { newColumn.push_back(entryTarget); },
1086 [&](
typename Column_support::iterator& itTarget) {
1087 while (itTarget != column_.end()) {
1088 newColumn.push_back(*itTarget);
1093 column_.swap(newColumn);
1095 return pivotIsZeroed;
1109template <
class Master_matrix,
class Support>
1110struct std::hash<
Gudhi::persistence_matrix::Naive_vector_column<Master_matrix,Support> > {
1112 return Gudhi::persistence_matrix::hash_column(column);
Column class following the PersistenceMatrixColumn concept.
Definition: naive_vector_column.h:51
Contains helper methods for column addition and column hasher.
Contains different versions of Gudhi::persistence_matrix::Entry factories.
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