18#ifndef PM_NAIVE_VECTOR_COLUMN_H
19#define PM_NAIVE_VECTOR_COLUMN_H
27#include <boost/range/iterator_range_core.hpp>
28#include <boost/iterator/indirect_iterator.hpp>
29#include <boost/container/small_vector.hpp>
48template <
class Master_matrix,
class Support>
49class Naive_vector_column :
public Master_matrix::Row_access_option,
50 public Master_matrix::Column_dimension_option,
51 public Master_matrix::Chain_column_option
54 using Master = Master_matrix;
55 using Index =
typename Master_matrix::Index;
56 using ID_index =
typename Master_matrix::ID_index;
57 using Dimension =
typename Master_matrix::Dimension;
58 using Field_element =
typename Master_matrix::Element;
59 using Entry =
typename Master_matrix::Matrix_entry;
60 using Column_settings =
typename Master_matrix::Column_settings;
63 using Field_operators =
typename Master_matrix::Field_operators;
64 using Column_support = Support;
65 using Entry_constructor =
typename Master_matrix::Entry_constructor;
68 using iterator = boost::indirect_iterator<typename Column_support::iterator>;
69 using const_iterator = boost::indirect_iterator<typename Column_support::const_iterator>;
70 using reverse_iterator = boost::indirect_iterator<typename Column_support::reverse_iterator>;
71 using const_reverse_iterator = boost::indirect_iterator<typename Column_support::const_reverse_iterator>;
72 using Content_range = boost::iterator_range<const_iterator>;
74 Naive_vector_column(Column_settings* colSettings =
nullptr);
75 template <
class Container =
typename Master_matrix::Boundary>
76 Naive_vector_column(
const Container& nonZeroRowIndices, Column_settings* colSettings);
77 template <
class Container =
typename Master_matrix::Boundary,
class Row_container>
78 Naive_vector_column(Index columnIndex,
79 const Container& nonZeroRowIndices,
80 Row_container* rowContainer,
81 Column_settings* colSettings);
82 template <
class Container =
typename Master_matrix::Boundary,
83 class = std::enable_if_t<!std::is_arithmetic_v<Container> > >
84 Naive_vector_column(
const Container& nonZeroRowIndices, Dimension dimension, Column_settings* colSettings);
85 template <
class Container =
typename Master_matrix::Boundary,
87 class = std::enable_if_t<!std::is_arithmetic_v<Container> > >
88 Naive_vector_column(Index columnIndex,
89 const Container& nonZeroRowIndices,
91 Row_container* rowContainer,
92 Column_settings* colSettings);
93 Naive_vector_column(ID_index idx, Dimension dimension, Column_settings* colSettings);
94 Naive_vector_column(ID_index idx,
97 Column_settings* colSettings);
98 template <
class Row_container>
99 Naive_vector_column(Index columnIndex,
102 Row_container* rowContainer,
103 Column_settings* colSettings);
104 template <
class Row_container>
105 Naive_vector_column(Index columnIndex,
109 Row_container* rowContainer,
110 Column_settings* colSettings);
111 Naive_vector_column(
const Naive_vector_column& column, Column_settings* colSettings =
nullptr);
112 template <
class Row_container>
113 Naive_vector_column(
const Naive_vector_column& column,
115 Row_container* rowContainer,
116 Column_settings* colSettings =
nullptr);
117 Naive_vector_column(Naive_vector_column&& column)
noexcept;
118 ~Naive_vector_column();
120 std::vector<Field_element> get_content(
int columnLength = -1)
const;
121 bool is_non_zero(ID_index rowIndex)
const;
122 [[nodiscard]]
bool is_empty()
const;
123 [[nodiscard]] std::size_t size()
const;
125 template <
class Row_index_map>
126 void reorder(
const Row_index_map& valueMap,
127 [[maybe_unused]] Index columnIndex = Master_matrix::template get_null_value<Index>());
129 void clear(ID_index rowIndex);
131 ID_index get_pivot()
const;
132 Field_element get_pivot_value()
const;
134 iterator begin()
noexcept;
135 const_iterator begin()
const noexcept;
136 iterator end()
noexcept;
137 const_iterator end()
const noexcept;
138 reverse_iterator rbegin()
noexcept;
139 const_reverse_iterator rbegin()
const noexcept;
140 reverse_iterator rend()
noexcept;
141 const_reverse_iterator rend()
const noexcept;
143 Content_range get_non_zero_content_range()
const;
145 template <
class Entry_range>
146 Naive_vector_column& operator+=(
const Entry_range& column);
147 Naive_vector_column& operator+=(Naive_vector_column& column);
149 Naive_vector_column& operator*=(
const Field_element& v);
152 template <
class Entry_range>
153 Naive_vector_column& multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
154 Naive_vector_column& multiply_target_and_add(
const Field_element& val, Naive_vector_column& column);
156 template <
class Entry_range>
157 Naive_vector_column& multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
158 Naive_vector_column& multiply_source_and_add(Naive_vector_column& column,
const Field_element& val);
160 void push_back(
const Entry& entry);
162 friend bool operator==(
const Naive_vector_column& c1,
const Naive_vector_column& c2)
164 if (&c1 == &c2)
return true;
165 if (c1.column_.size() != c2.column_.size())
return false;
167 return std::equal(c1.column_.begin(),
171 [](
const Entry* e1,
const Entry* e2) {
172 return e1->get_row_index() == e2->get_row_index() && e1->get_element() == e2->get_element();
176 friend bool operator<(
const Naive_vector_column& c1,
const Naive_vector_column& c2)
178 if (&c1 == &c2)
return false;
180 return std::lexicographical_compare(c1.column_.begin(),
184 [](
const Entry* e1,
const Entry* e2) {
185 if (e1->get_row_index() != e2->get_row_index())
186 return e1->get_row_index() < e2->get_row_index();
187 if (e1->get_element() != e2->get_element())
188 return e1->get_element() < e2->get_element();
194 Naive_vector_column& operator=(
const Naive_vector_column& other);
195 Naive_vector_column& operator=(Naive_vector_column&& other)
noexcept;
197 friend void swap(Naive_vector_column& col1, Naive_vector_column& col2)
noexcept
199 swap(
static_cast<typename Master_matrix::Row_access_option&
>(col1),
200 static_cast<typename Master_matrix::Row_access_option&
>(col2));
201 swap(
static_cast<typename Master_matrix::Column_dimension_option&
>(col1),
202 static_cast<typename Master_matrix::Column_dimension_option&
>(col2));
203 swap(
static_cast<typename Master_matrix::Chain_column_option&
>(col1),
204 static_cast<typename Master_matrix::Chain_column_option&
>(col2));
205 col1.column_.swap(col2.column_);
206 std::swap(col1.operators_, col2.operators_);
207 std::swap(col1.entryPool_, col2.entryPool_);
211 using RA_opt =
typename Master_matrix::Row_access_option;
212 using Dim_opt =
typename Master_matrix::Column_dimension_option;
213 using Chain_opt =
typename Master_matrix::Chain_column_option;
215 Column_support column_;
216 Field_operators
const* operators_;
217 Entry_constructor* entryPool_;
219 template <
class Column,
class Entry_iterator,
typename F1,
typename F2,
typename F3,
typename F4>
220 friend void _generic_merge_entry_to_column(Column& targetColumn,
221 Entry_iterator& itSource,
222 typename Column::Column_support::iterator& itTarget,
227 bool& pivotIsZeroed);
228 template <
class Column,
class Entry_range,
typename F1,
typename F2,
typename F3,
typename F4,
typename F5>
229 friend bool _generic_add_to_column(
const Entry_range& source,
230 Column& targetColumn,
237 void _delete_entry(Entry* entry);
238 void _delete_entry(
typename Column_support::iterator& it);
239 Entry* _insert_entry(Column_support& column, ID_index rowIndex,
const Field_element& value);
240 void _update_entry(Index position, ID_index rowIndex,
const Field_element& value);
241 template <
class Entry_range>
242 bool _add(
const Entry_range& column);
243 template <
class Entry_range>
244 bool _multiply_target_and_add(
const Field_element& val,
const Entry_range& column);
245 template <
class Entry_range>
246 bool _multiply_source_and_add(
const Entry_range& column,
const Field_element& val);
249template <
class Master_matrix>
251template <
class Master_matrix>
252using Naive_small_vector_column =
255template <
class Master_matrix,
class Support>
256inline Naive_vector_column<Master_matrix, Support>::Naive_vector_column(Column_settings* colSettings)
260 operators_(Master_matrix::get_operator_ptr(colSettings)),
261 entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor))
264template <
class Master_matrix,
class Support>
265template <
class Container>
266inline Naive_vector_column<Master_matrix, Support>::Naive_vector_column(
const Container& nonZeroRowIndices,
267 Column_settings* colSettings)
268 : Naive_vector_column(nonZeroRowIndices,
269 nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1,
272 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
273 "Constructor not available for chain columns, please specify the dimension of the chain.");
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 : Naive_vector_column(columnIndex,
284 nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1,
288 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
289 "Constructor not available for chain columns, please specify the dimension of the chain.");
292template <
class Master_matrix,
class Support>
293template <
class Container,
class>
294inline Naive_vector_column<Master_matrix, Support>::Naive_vector_column(
const Container& nonZeroRowIndices,
296 Column_settings* colSettings)
299 Chain_opt(nonZeroRowIndices.begin() == nonZeroRowIndices.end()
300 ? Master_matrix::template get_null_value<ID_index>()
301 : Master_matrix::get_row_index(*std::prev(nonZeroRowIndices.end()))),
302 column_(nonZeroRowIndices.size(), nullptr),
303 operators_(Master_matrix::get_operator_ptr(colSettings)),
304 entryPool_(&(colSettings->entryConstructor))
307 for (
const auto&
id : nonZeroRowIndices) {
309 Master_matrix::get_row_index(
id),
310 Master_matrix::get_coefficient_value(Master_matrix::get_element(
id), operators_));
314template <
class Master_matrix,
class Support>
315template <
class Container,
class Row_container,
class>
316inline Naive_vector_column<Master_matrix, Support>::Naive_vector_column(Index columnIndex,
317 const Container& nonZeroRowIndices,
319 Row_container* rowContainer,
320 Column_settings* colSettings)
321 : RA_opt(columnIndex, rowContainer),
323 Chain_opt(nonZeroRowIndices.begin() == nonZeroRowIndices.end()
324 ? Master_matrix::template get_null_value<ID_index>()
325 : Master_matrix::get_row_index(*std::prev(nonZeroRowIndices.end()))),
326 column_(nonZeroRowIndices.size(), nullptr),
327 operators_(Master_matrix::get_operator_ptr(colSettings)),
328 entryPool_(&(colSettings->entryConstructor))
331 for (
const auto&
id : nonZeroRowIndices) {
333 Master_matrix::get_row_index(
id),
334 Master_matrix::get_coefficient_value(Master_matrix::get_element(
id), operators_));
338template <
class Master_matrix,
class Support>
339inline Naive_vector_column<Master_matrix, Support>::Naive_vector_column(ID_index idx,
341 Column_settings* colSettings)
347 entryPool_(&(colSettings->entryConstructor))
349 static_assert(Master_matrix::Option_list::is_z2,
350 "Constructor not available for Zp != Z2. Please specify the coefficient.");
351 _update_entry(0, idx, 1);
354template <
class Master_matrix,
class Support>
355inline Naive_vector_column<Master_matrix, Support>::Naive_vector_column(ID_index idx,
358 Column_settings* colSettings)
363 operators_(&(colSettings->operators)),
364 entryPool_(&(colSettings->entryConstructor))
366 static_assert(!Master_matrix::Option_list::is_z2,
367 "Constructor not available for Zp == Z2. Please do not specify any coefficient.");
368 _update_entry(0, idx, operators_->get_value(e));
371template <
class Master_matrix,
class Support>
372template <
class Row_container>
373inline Naive_vector_column<Master_matrix, Support>::Naive_vector_column(Index columnIndex,
376 Row_container* rowContainer,
377 Column_settings* colSettings)
378 : RA_opt(columnIndex, rowContainer),
383 entryPool_(&(colSettings->entryConstructor))
385 static_assert(Master_matrix::Option_list::is_z2,
386 "Constructor not available for Zp != Z2. Please specify the coefficient.");
387 _update_entry(0, idx, 1);
390template <
class Master_matrix,
class Support>
391template <
class Row_container>
392inline Naive_vector_column<Master_matrix, Support>::Naive_vector_column(Index columnIndex,
396 Row_container* rowContainer,
397 Column_settings* colSettings)
398 : RA_opt(columnIndex, rowContainer),
402 operators_(&(colSettings->operators)),
403 entryPool_(&(colSettings->entryConstructor))
405 static_assert(!Master_matrix::Option_list::is_z2,
406 "Constructor not available for Zp == Z2. Please do not specify any coefficient.");
407 _update_entry(0, idx, operators_->get_value(e));
410template <
class Master_matrix,
class Support>
411inline Naive_vector_column<Master_matrix, Support>::Naive_vector_column(
const Naive_vector_column& column,
412 Column_settings* colSettings)
414 Dim_opt(static_cast<const Dim_opt&>(column)),
415 Chain_opt(static_cast<const Chain_opt&>(column)),
416 column_(column.column_.size(), nullptr),
417 operators_(colSettings == nullptr ? column.operators_ : Master_matrix::get_operator_ptr(colSettings)),
418 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
420 static_assert(!Master_matrix::Option_list::has_row_access,
421 "Simple copy constructor not available when row access option enabled. Please specify the new column "
422 "index and the row container.");
425 for (
const Entry* entry : column.column_) {
426 _update_entry(i++, entry->get_row_index(), entry->get_element());
430template <
class Master_matrix,
class Support>
431template <
class Row_container>
432inline Naive_vector_column<Master_matrix, Support>::Naive_vector_column(
const Naive_vector_column& column,
434 Row_container* rowContainer,
435 Column_settings* colSettings)
436 : RA_opt(columnIndex, rowContainer),
437 Dim_opt(static_cast<const Dim_opt&>(column)),
438 Chain_opt(static_cast<const Chain_opt&>(column)),
439 column_(column.column_.size(), nullptr),
440 operators_(colSettings == nullptr ? column.operators_ : Master_matrix::get_operator_ptr(colSettings)),
441 entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
444 for (
const Entry* entry : column.column_) {
445 _update_entry(i++, entry->get_row_index(), entry->get_element());
449template <
class Master_matrix,
class Support>
450inline Naive_vector_column<Master_matrix, Support>::Naive_vector_column(
Naive_vector_column&& column) noexcept
451 : RA_opt(std::move(
static_cast<RA_opt&
>(column))),
452 Dim_opt(std::move(
static_cast<Dim_opt&
>(column))),
453 Chain_opt(std::move(
static_cast<Chain_opt&
>(column))),
454 column_(std::move(column.column_)),
455 operators_(std::exchange(column.operators_,
nullptr)),
456 entryPool_(std::exchange(column.entryPool_,
nullptr))
459template <
class Master_matrix,
class Support>
460inline Naive_vector_column<Master_matrix, Support>::~Naive_vector_column()
462 for (
auto* entry : column_) {
463 _delete_entry(entry);
467template <
class Master_matrix,
class Support>
468inline std::vector<typename Naive_vector_column<Master_matrix, Support>::Field_element>
469Naive_vector_column<Master_matrix, Support>::get_content(
int columnLength)
const
471 if (columnLength < 0 && column_.size() > 0)
472 columnLength = column_.back()->get_row_index() + 1;
473 else if (columnLength < 0)
474 return std::vector<Field_element>();
476 std::vector<Field_element> container(columnLength, 0);
477 for (
auto it = column_.begin(); it != column_.end() && (*it)->get_row_index() <
static_cast<ID_index
>(columnLength);
479 container[(*it)->get_row_index()] = Master_matrix::get_element(**it);
484template <
class Master_matrix,
class Support>
485inline bool Naive_vector_column<Master_matrix, Support>::is_non_zero(ID_index rowIndex)
const
487 Entry entry(rowIndex);
488 return std::binary_search(column_.begin(), column_.end(), &entry, [](
const Entry* a,
const Entry* b) {
489 return a->get_row_index() < b->get_row_index();
493template <
class Master_matrix,
class Support>
494inline bool Naive_vector_column<Master_matrix, Support>::is_empty()
const
496 return column_.empty();
499template <
class Master_matrix,
class Support>
500inline std::size_t Naive_vector_column<Master_matrix, Support>::size()
const
502 return column_.size();
505template <
class Master_matrix,
class Support>
506template <
class Row_index_map>
507inline void Naive_vector_column<Master_matrix, Support>::reorder(
const Row_index_map& valueMap,
508 [[maybe_unused]] Index columnIndex)
510 static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
511 "Method not available for chain columns.");
513 for (
Entry* entry : column_) {
514 if constexpr (Master_matrix::Option_list::has_row_access) {
515 RA_opt::unlink(entry);
516 if (columnIndex != Master_matrix::template get_null_value<Index>()) entry->set_column_index(columnIndex);
518 entry->set_row_index(valueMap.at(entry->get_row_index()));
519 if constexpr (Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access)
520 RA_opt::insert_entry(entry->get_row_index(), entry);
524 if constexpr (!Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) {
525 for (
Entry* entry : column_) {
526 RA_opt::insert_entry(entry->get_row_index(), entry);
530 std::sort(column_.begin(), column_.end(), [](
const Entry* c1,
const Entry* c2) { return *c1 < *c2; });
533template <
class Master_matrix,
class Support>
534inline void Naive_vector_column<Master_matrix, Support>::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* entry : column_) {
540 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
541 entryPool_->destroy(entry);
547template <
class Master_matrix,
class Support>
548inline void Naive_vector_column<Master_matrix, Support>::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 it = column_.begin();
554 while (it != column_.end() && (*it)->get_row_index() != rowIndex) ++it;
555 if (it != column_.end()) {
561template <
class Master_matrix,
class Support>
562inline typename Naive_vector_column<Master_matrix, Support>::ID_index
563Naive_vector_column<Master_matrix, Support>::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 return column_.empty() ? Master_matrix::template get_null_value<ID_index>() : column_.back()->get_row_index();
571 return Chain_opt::_get_pivot();
575template <
class Master_matrix,
class Support>
576inline typename Naive_vector_column<Master_matrix, Support>::Field_element
577Naive_vector_column<Master_matrix, Support>::get_pivot_value()
const
579 static_assert(Master_matrix::isNonBasic,
580 "Method not available for base columns.");
582 if constexpr (Master_matrix::Option_list::is_z2) {
585 if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
586 return column_.empty() ? Field_element() : column_.back()->get_element();
588 if (Chain_opt::_get_pivot() == Master_matrix::template get_null_value<ID_index>())
return Field_element();
589 for (
const Entry* entry : column_) {
590 if (entry->get_row_index() == Chain_opt::_get_pivot())
return entry->get_element();
592 return Field_element();
597template <
class Master_matrix,
class Support>
598inline typename Naive_vector_column<Master_matrix, Support>::iterator
599Naive_vector_column<Master_matrix, Support>::begin() noexcept
601 return column_.begin();
604template <
class Master_matrix,
class Support>
605inline typename Naive_vector_column<Master_matrix, Support>::const_iterator
606Naive_vector_column<Master_matrix, Support>::begin() const noexcept
608 return column_.begin();
611template <
class Master_matrix,
class Support>
612inline typename Naive_vector_column<Master_matrix, Support>::iterator
613Naive_vector_column<Master_matrix, Support>::end() noexcept
615 return column_.end();
618template <
class Master_matrix,
class Support>
619inline typename Naive_vector_column<Master_matrix, Support>::const_iterator
620Naive_vector_column<Master_matrix, Support>::end() const noexcept
622 return column_.end();
625template <
class Master_matrix,
class Support>
626inline typename Naive_vector_column<Master_matrix, Support>::reverse_iterator
627Naive_vector_column<Master_matrix, Support>::rbegin() noexcept
629 return column_.rbegin();
632template <
class Master_matrix,
class Support>
633inline typename Naive_vector_column<Master_matrix, Support>::const_reverse_iterator
634Naive_vector_column<Master_matrix, Support>::rbegin() const noexcept
636 return column_.rbegin();
639template <
class Master_matrix,
class Support>
640inline typename Naive_vector_column<Master_matrix, Support>::reverse_iterator
641Naive_vector_column<Master_matrix, Support>::rend() noexcept
643 return column_.rend();
646template <
class Master_matrix,
class Support>
647inline typename Naive_vector_column<Master_matrix, Support>::const_reverse_iterator
648Naive_vector_column<Master_matrix, Support>::rend() const noexcept
650 return column_.rend();
653template <
class Master_matrix,
class Support>
654inline typename Naive_vector_column<Master_matrix, Support>::Content_range
655Naive_vector_column<Master_matrix, Support>::get_non_zero_content_range()
const
657 return Content_range(column_.begin(), column_.end());
660template <
class Master_matrix,
class Support>
661template <
class Entry_range>
663 const Entry_range& column)
665 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Naive_vector_column>),
666 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
668 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
669 "For chain columns, the given column cannot be constant.");
676template <
class Master_matrix,
class Support>
680 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
683 Chain_opt::_swap_pivots(column);
684 Dim_opt::_swap_dimension(column);
693template <
class Master_matrix,
class Support>
695 const Field_element& v)
697 Field_element val = Master_matrix::get_coefficient_value(v, operators_);
699 if (val == Field_operators::get_additive_identity()) {
700 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
701 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
708 if (val == Field_operators::get_multiplicative_identity())
return *
this;
712 if constexpr (!Master_matrix::Option_list::is_z2) {
713 for (
Entry* entry : column_) {
714 operators_->multiply_inplace(entry->get_element(), val);
715 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entry);
722template <
class Master_matrix,
class Support>
723template <
class Entry_range>
725Naive_vector_column<Master_matrix, Support>::multiply_target_and_add(
const Field_element& val,
726 const Entry_range& column)
728 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Naive_vector_column>),
729 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
731 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
732 "For chain columns, the given column cannot be constant.");
734 _multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column);
739template <
class Master_matrix,
class Support>
741Naive_vector_column<Master_matrix, Support>::multiply_target_and_add(
const Field_element& val,
744 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
746 if (_multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column)) {
747 Chain_opt::_swap_pivots(column);
748 Dim_opt::_swap_dimension(column);
751 _multiply_target_and_add(Master_matrix::get_coefficient_value(val, operators_), column);
757template <
class Master_matrix,
class Support>
758template <
class Entry_range>
760Naive_vector_column<Master_matrix, Support>::multiply_source_and_add(
const Entry_range& column,
761 const Field_element& val)
763 static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Naive_vector_column>),
764 "For boundary columns, the range has to be a column of same type to help ensure the validity of the "
766 static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
767 "For chain columns, the given column cannot be constant.");
769 _multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_));
774template <
class Master_matrix,
class Support>
776Naive_vector_column<Master_matrix, Support>::multiply_source_and_add(
Naive_vector_column& column,
777 const Field_element& val)
779 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
781 if (_multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_))) {
782 Chain_opt::_swap_pivots(column);
783 Dim_opt::_swap_dimension(column);
786 _multiply_source_and_add(column, Master_matrix::get_coefficient_value(val, operators_));
792template <
class Master_matrix,
class Support>
793inline void Naive_vector_column<Master_matrix, Support>::push_back(
const Entry& entry)
795 static_assert(Master_matrix::Option_list::is_of_boundary_type,
"`push_back` is not available for Chain matrices.");
797 GUDHI_CHECK(entry.get_row_index() > get_pivot(),
798 std::invalid_argument(
"The new row index has to be higher than the current pivot."));
800 _insert_entry(column_, entry.get_row_index(), entry.get_element());
803template <
class Master_matrix,
class Support>
807 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
810 if (
this == &other)
return *
this;
812 Dim_opt::operator=(other);
813 Chain_opt::operator=(other);
815 auto tmpPool = entryPool_;
816 entryPool_ = other.entryPool_;
818 while (column_.size() > other.column_.size()) {
819 if (column_.back() ==
nullptr) {
820 tmpPool->destroy(column_.back());
825 column_.resize(other.column_.size(),
nullptr);
827 for (
const Entry* entry : other.column_) {
828 if (column_[i] !=
nullptr) {
829 tmpPool->destroy(column_[i]);
831 _update_entry(i++, entry->get_row_index(), entry->get_element());
834 operators_ = other.operators_;
839template <
class Master_matrix,
class Support>
843 static_assert(!Master_matrix::Option_list::has_row_access,
"= assignment not enabled with row access option.");
846 if (&column_ == &(other.column_))
return *
this;
848 Dim_opt::operator=(std::move(other));
849 Chain_opt::operator=(std::move(other));
851 for (
auto* entry : column_) {
852 if (entry !=
nullptr) _delete_entry(entry);
855 column_ = std::move(other.column_);
856 operators_ = std::exchange(other.operators_,
nullptr);
857 entryPool_ = std::exchange(other.entryPool_,
nullptr);
862template <
class Master_matrix,
class Support>
863inline void Naive_vector_column<Master_matrix, Support>::_delete_entry(
Entry* entry)
865 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
866 entryPool_->destroy(entry);
869template <
class Master_matrix,
class Support>
870inline void Naive_vector_column<Master_matrix, Support>::_delete_entry(
typename Column_support::iterator& it)
876template <
class Master_matrix,
class Support>
877inline typename Naive_vector_column<Master_matrix, Support>::Entry*
878Naive_vector_column<Master_matrix, Support>::_insert_entry(Column_support& column,
880 const Field_element& value)
883 if constexpr (Master_matrix::Option_list::has_row_access) {
884 newEntry = entryPool_->construct(RA_opt::get_column_index(), rowIndex);
886 newEntry = entryPool_->construct(rowIndex);
888 column.push_back(newEntry);
889 newEntry->set_element(value);
890 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::insert_entry(rowIndex, newEntry);
894template <
class Master_matrix,
class Support>
895inline void Naive_vector_column<Master_matrix, Support>::_update_entry(Index position,
897 const Field_element& value)
899 if constexpr (Master_matrix::Option_list::has_row_access) {
900 column_[position] = entryPool_->construct(RA_opt::get_column_index(), rowIndex);
902 column_[position] = entryPool_->construct(rowIndex);
904 column_[position]->set_element(value);
905 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::insert_entry(rowIndex, column_[position]);
908template <
class Master_matrix,
class Support>
909template <
class Entry_range>
910inline bool Naive_vector_column<Master_matrix, Support>::_add(
const Entry_range& column)
912 if (column.begin() == column.end())
return false;
913 if (column_.empty()) {
914 column_.resize(column.size());
916 for (
const Entry& entry : column) {
917 _update_entry(i++, entry.get_row_index(), entry.get_element());
922 Column_support newColumn;
923 newColumn.reserve(column_.size() + column.size());
925 auto pivotIsZeroed = _generic_add_to_column(
928 [&](
Entry* entryTarget) { newColumn.push_back(entryTarget); },
929 [&](
typename Entry_range::const_iterator& itSource,
930 [[maybe_unused]]
const typename Column_support::iterator& itTarget) {
931 _insert_entry(newColumn, itSource->get_row_index(), itSource->get_element());
933 [&](Field_element& targetElement,
typename Entry_range::const_iterator& itSource) {
934 if constexpr (!Master_matrix::Option_list::is_z2)
935 operators_->add_inplace(targetElement, itSource->get_element());
937 [&](
Entry* entryTarget) { newColumn.push_back(entryTarget); },
938 [&](
typename Column_support::iterator& itTarget) {
939 while (itTarget != column_.end()) {
940 newColumn.push_back(*itTarget);
945 column_.swap(newColumn);
947 return pivotIsZeroed;
950template <
class Master_matrix,
class Support>
951template <
class Entry_range>
952inline bool Naive_vector_column<Master_matrix, Support>::_multiply_target_and_add(
const Field_element& val,
953 const Entry_range& column)
955 if (val == Field_operators::get_additive_identity()) {
956 if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
957 throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
964 if (column_.empty() || val == Field_operators::get_multiplicative_identity()) {
970 if constexpr (!Master_matrix::Option_list::is_z2) {
971 Column_support newColumn;
972 newColumn.reserve(column_.size() + column.size());
974 auto pivotIsZeroed = _generic_add_to_column(
977 [&](
Entry* entryTarget) {
978 operators_->multiply_inplace(entryTarget->get_element(), val);
979 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entryTarget);
980 newColumn.push_back(entryTarget);
982 [&](
typename Entry_range::const_iterator& itSource,
const typename Column_support::iterator& itTarget) {
983 _insert_entry(newColumn, itSource->get_row_index(), itSource->get_element());
985 [&](Field_element& targetElement,
typename Entry_range::const_iterator& itSource) {
986 operators_->multiply_and_add_inplace_front(targetElement, val, itSource->get_element());
988 [&](
Entry* entryTarget) { newColumn.push_back(entryTarget); },
989 [&](
typename Column_support::iterator& itTarget) {
990 while (itTarget != column_.end()) {
991 operators_->multiply_inplace((*itTarget)->get_element(), val);
992 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(**itTarget);
993 newColumn.push_back(*itTarget);
998 column_.swap(newColumn);
1000 return pivotIsZeroed;
1006template <
class Master_matrix,
class Support>
1007template <
class Entry_range>
1008inline bool Naive_vector_column<Master_matrix, Support>::_multiply_source_and_add(
const Entry_range& column,
1009 const Field_element& val)
1011 if (val == Field_operators::get_additive_identity() || column.begin() == column.end()) {
1015 if (val == Field_operators::get_multiplicative_identity()) {
1016 return _add(column);
1021 if constexpr (!Master_matrix::Option_list::is_z2) {
1022 Column_support newColumn;
1023 newColumn.reserve(column_.size() + column.size());
1025 auto pivotIsZeroed = _generic_add_to_column(
1028 [&](
Entry* entryTarget) { newColumn.push_back(entryTarget); },
1029 [&](
typename Entry_range::const_iterator& itSource,
const typename Column_support::iterator& itTarget) {
1030 Entry* newEntry = _insert_entry(newColumn, itSource->get_row_index(), itSource->get_element());
1031 operators_->multiply_inplace(newEntry->get_element(), val);
1032 if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*newEntry);
1034 [&](Field_element& targetElement,
typename Entry_range::const_iterator& itSource) {
1035 operators_->multiply_and_add_inplace_back(itSource->get_element(), val, targetElement);
1037 [&](
Entry* entryTarget) { newColumn.push_back(entryTarget); },
1038 [&](
typename Column_support::iterator& itTarget) {
1039 while (itTarget != column_.end()) {
1040 newColumn.push_back(*itTarget);
1045 column_.swap(newColumn);
1047 return pivotIsZeroed;
1064template <
class Master_matrix,
class Support>
1065struct std::hash<
Gudhi::persistence_matrix::Naive_vector_column<Master_matrix, Support> > {
1068 return Gudhi::persistence_matrix::hash_column(column);
Matrix entry class. Stores by default only the row index it belongs to, but can also store its column...
Definition entry_types.h:163
Column class following the PersistenceMatrixColumn concept.
Definition naive_vector_column.h:52
Contains helper methods for column addition and column hasher.
Contains different versions of Gudhi::persistence_matrix::Entry factories.
Persistence matrix namespace.
Definition FieldOperators.h:18
Gudhi namespace.
Definition SimplicialComplexForAlpha.h:14