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