18#ifndef PM_INTRUSIVE_LIST_COLUMN_H 
   19#define PM_INTRUSIVE_LIST_COLUMN_H 
   26#include <boost/intrusive/list.hpp> 
   32namespace persistence_matrix {
 
   45template <
class Master_matrix>
 
   51  using Master = Master_matrix;
 
   52  using Index = 
typename Master_matrix::Index;
 
   53  using ID_index = 
typename Master_matrix::ID_index;
 
   54  using Dimension = 
typename Master_matrix::Dimension;
 
   55  using Field_element = 
typename Master_matrix::Element;
 
   56  using Entry = 
typename Master_matrix::Matrix_entry;
 
   57  using Column_settings = 
typename Master_matrix::Column_settings;
 
   60  using Field_operators = 
typename Master_matrix::Field_operators;
 
   61  using Column_support =
 
   62      boost::intrusive::list<Entry,
 
   63                             boost::intrusive::constant_time_size<false>,
 
   64                             boost::intrusive::base_hook<typename Master_matrix::Base_hook_matrix_list_column> >;
 
   65  using Entry_constructor = 
typename Master_matrix::Entry_constructor;
 
   68  using iterator = 
typename Column_support::iterator;
 
   69  using const_iterator = 
typename Column_support::const_iterator;
 
   70  using reverse_iterator = 
typename Column_support::reverse_iterator;
 
   71  using const_reverse_iterator = 
typename Column_support::const_reverse_iterator;
 
   74  template <
class Container = 
typename Master_matrix::Boundary>
 
   76  template <
class Container = 
typename Master_matrix::Boundary, 
class Row_container>
 
   78                        const Container& nonZeroRowIndices,
 
   79                        Row_container* rowContainer,
 
   80                        Column_settings* colSettings);
 
   81  template <
class Container = 
typename Master_matrix::Boundary>
 
   82  Intrusive_list_column(
const Container& nonZeroChainRowIndices, Dimension dimension, Column_settings* colSettings);
 
   83  template <
class Container = 
typename Master_matrix::Boundary, 
class Row_container>
 
   85                        const Container& nonZeroChainRowIndices,
 
   87                        Row_container* rowContainer,
 
   88                        Column_settings* colSettings);
 
   90  template <
class Row_container>
 
   93                        Row_container* rowContainer,
 
   94                        Column_settings* colSettings = 
nullptr);
 
   98  std::vector<Field_element> get_content(
int columnLength = -1) 
const;
 
   99  bool is_non_zero(ID_index rowIndex) 
const;
 
  100  bool is_empty() 
const;
 
  101  std::size_t size() 
const;
 
  103  template <
class Row_index_map>
 
  104  void reorder(
const Row_index_map& valueMap,
 
  105               [[maybe_unused]] Index columnIndex = Master_matrix::template get_null_value<Index>());
 
  107  void clear(ID_index rowIndex);
 
  109  ID_index get_pivot() 
const;
 
  110  Field_element get_pivot_value() 
const;
 
  112  iterator begin() 
noexcept;
 
  113  const_iterator begin() 
const noexcept;
 
  114  iterator end() 
noexcept;
 
  115  const_iterator end() 
const noexcept;
 
  116  reverse_iterator rbegin() 
noexcept;
 
  117  const_reverse_iterator rbegin() 
const noexcept;
 
  118  reverse_iterator rend() 
noexcept;
 
  119  const_reverse_iterator rend() 
const noexcept;
 
  121  template <
class Entry_range>
 
  128  template <
class Entry_range>
 
  132  template <
class Entry_range>
 
  136  void push_back(
const Entry& entry);
 
  139    if (&c1 == &c2) 
return true;
 
  141    if constexpr (Master_matrix::Option_list::is_z2) {
 
  142      return c1.column_ == c2.column_;
 
  144      auto it1 = c1.column_.begin();
 
  145      auto it2 = c2.column_.begin();
 
  146      if (c1.column_.size() != c2.column_.size()) 
return false;
 
  147      while (it1 != c1.column_.end() && it2 != c2.column_.end()) {
 
  148        if (it1->get_row_index() != it2->get_row_index() || it1->get_element() != it2->get_element()) 
return false;
 
  157    if (&c1 == &c2) 
return false;
 
  159    if constexpr (Master_matrix::Option_list::is_z2) {
 
  160      return c1.column_ < c2.column_;
 
  162      auto it1 = c1.column_.begin();
 
  163      auto it2 = c2.column_.begin();
 
  164      while (it1 != c1.column_.end() && it2 != c2.column_.end()) {
 
  165        if (it1->get_row_index() != it2->get_row_index()) 
return it1->get_row_index() < it2->get_row_index();
 
  166        if (it1->get_element() != it2->get_element()) 
return it1->get_element() < it2->get_element();
 
  170      return it2 != c2.column_.end();
 
  184    col1.column_.swap(col2.column_);
 
  185    std::swap(col1.operators_, col2.operators_);
 
  186    std::swap(col1.entryPool_, col2.entryPool_);
 
  196    New_cloner(Entry_constructor* entryPool) : entryPool_(entryPool) {};
 
  198    Entry* operator()(
const Entry& clone_this) { 
return entryPool_->construct(clone_this); }
 
  200    Entry_constructor* entryPool_;
 
  204  struct Delete_disposer {
 
  205    Delete_disposer() {};
 
  208    void operator()(Entry* delete_this) {
 
  209      if constexpr (Master_matrix::Option_list::has_row_access) col_->unlink(delete_this);
 
  210      col_->entryPool_->destroy(delete_this);
 
  216  Field_operators* operators_;
 
  217  Entry_constructor* entryPool_;
 
  218  Column_support column_;
 
  220  template <
class Column, 
class Entry_iterator, 
typename F1, 
typename F2, 
typename F3, 
typename F4>
 
  221  friend void _generic_merge_entry_to_column(Column& targetColumn,
 
  222                                             Entry_iterator& itSource,
 
  223                                             typename Column::Column_support::iterator& itTarget,
 
  228                                             bool& pivotIsZeroed);
 
  229  template <
class Column, 
class Entry_range, 
typename F1, 
typename F2, 
typename F3, 
typename F4, 
typename F5>
 
  230  friend bool _generic_add_to_column(
const Entry_range& source,
 
  231                                     Column& targetColumn,
 
  237  template <
class Column, 
class Entry_range>
 
  238  friend bool _add_to_column(
const Entry_range& source, Column& targetColumn);
 
  239  template <
class Column, 
class Entry_range>
 
  240  friend bool _multiply_target_and_add_to_column(
const typename Column::Field_element& val,
 
  241                                                 const Entry_range& source,
 
  242                                                 Column& targetColumn);
 
  243  template <
class Column, 
class Entry_range>
 
  244  friend bool _multiply_source_and_add_to_column(
const typename Column::Field_element& val,
 
  245                                                 const Entry_range& source,
 
  246                                                 Column& targetColumn);
 
  248  void _delete_entry(iterator& it);
 
  249  Entry* _insert_entry(
const Field_element& value, ID_index rowIndex, 
const iterator& position);
 
  250  void _insert_entry(ID_index rowIndex, 
const iterator& position);
 
  251  template <
class Entry_range>
 
  252  bool _add(
const Entry_range& column);
 
  253  template <
class Entry_range>
 
  254  bool _multiply_target_and_add(
const Field_element& val, 
const Entry_range& column);
 
  255  template <
class Entry_range>
 
  256  bool _multiply_source_and_add(
const Entry_range& column, 
const Field_element& val);
 
  259template <
class Master_matrix>
 
  265      entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor)),
 
  268  if (colSettings == 
nullptr) 
return;  
 
  269  if constexpr (!Master_matrix::Option_list::is_z2) {
 
  270    operators_ = &(colSettings->operators);
 
  274template <
class Master_matrix>
 
  275template <
class Container>
 
  276inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(
const Container& nonZeroRowIndices,
 
  277                                                                   Column_settings* colSettings)
 
  279      Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
 
  282      entryPool_(&(colSettings->entryConstructor)),
 
  285  static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
 
  286                "Constructor not available for chain columns, please specify the dimension of the chain.");
 
  288  if constexpr (Master_matrix::Option_list::is_z2) {
 
  289    for (ID_index 
id : nonZeroRowIndices) {
 
  290      _insert_entry(
id, column_.end());
 
  293    operators_ = &(colSettings->operators);
 
  294    for (
const auto& p : nonZeroRowIndices) {
 
  295      _insert_entry(operators_->get_value(p.second), p.first, column_.end());
 
  300template <
class Master_matrix>
 
  301template <
class Container, 
class Row_container>
 
  302inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(Index columnIndex,
 
  303                                                                   const Container& nonZeroRowIndices,
 
  304                                                                   Row_container* rowContainer,
 
  305                                                                   Column_settings* colSettings)
 
  306    : RA_opt(columnIndex, rowContainer),
 
  307      Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
 
  309        if constexpr (Master_matrix::Option_list::is_z2) {
 
  310          return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
 
  311                     ? Master_matrix::template get_null_value<ID_index>()
 
  312                     : *
std::prev(nonZeroRowIndices.end());
 
  314          return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
 
  315                     ? Master_matrix::template get_null_value<ID_index>()
 
  316                     : 
std::prev(nonZeroRowIndices.end())->first;
 
  320      entryPool_(&(colSettings->entryConstructor)),
 
  323  static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
 
  324                "Constructor not available for chain columns, please specify the dimension of the chain.");
 
  326  if constexpr (Master_matrix::Option_list::is_z2) {
 
  327    for (ID_index 
id : nonZeroRowIndices) {
 
  328      _insert_entry(
id, column_.end());
 
  331    operators_ = &(colSettings->operators);
 
  332    for (
const auto& p : nonZeroRowIndices) {
 
  333      _insert_entry(operators_->get_value(p.second), p.first, column_.end());
 
  338template <
class Master_matrix>
 
  339template <
class Container>
 
  340inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(
const Container& nonZeroRowIndices,
 
  342                                                                   Column_settings* colSettings)
 
  346        if constexpr (Master_matrix::Option_list::is_z2) {
 
  347          return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
 
  348                     ? Master_matrix::template get_null_value<ID_index>()
 
  349                     : *
std::prev(nonZeroRowIndices.end());
 
  351          return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
 
  352                     ? Master_matrix::template get_null_value<ID_index>()
 
  353                     : 
std::prev(nonZeroRowIndices.end())->first;
 
  357      entryPool_(&(colSettings->entryConstructor)),
 
  360  if constexpr (Master_matrix::Option_list::is_z2) {
 
  361    for (ID_index 
id : nonZeroRowIndices) {
 
  362      _insert_entry(
id, column_.end());
 
  365    operators_ = &(colSettings->operators);
 
  366    for (
const auto& p : nonZeroRowIndices) {
 
  367      _insert_entry(operators_->get_value(p.second), p.first, column_.end());
 
  372template <
class Master_matrix>
 
  373template <
class Container, 
class Row_container>
 
  374inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(Index columnIndex,
 
  375                                                                   const Container& nonZeroRowIndices,
 
  377                                                                   Row_container* rowContainer,
 
  378                                                                   Column_settings* colSettings)
 
  379    : RA_opt(columnIndex, rowContainer),
 
  382        if constexpr (Master_matrix::Option_list::is_z2) {
 
  383          return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
 
  384                     ? Master_matrix::template get_null_value<ID_index>()
 
  385                     : *
std::prev(nonZeroRowIndices.end());
 
  387          return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
 
  388                     ? Master_matrix::template get_null_value<ID_index>()
 
  389                     : 
std::prev(nonZeroRowIndices.end())->first;
 
  393      entryPool_(&(colSettings->entryConstructor)),
 
  396  if constexpr (Master_matrix::Option_list::is_z2) {
 
  397    for (ID_index 
id : nonZeroRowIndices) {
 
  398      _insert_entry(
id, column_.end());
 
  401    operators_ = &(colSettings->operators);
 
  402    for (
const auto& p : nonZeroRowIndices) {
 
  403      _insert_entry(operators_->get_value(p.second), p.first, column_.end());
 
  408template <
class Master_matrix>
 
  409inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(
const Intrusive_list_column& column,
 
  410                                                                   Column_settings* colSettings)
 
  412      Dim_opt(static_cast<const Dim_opt&>(column)),
 
  413      Chain_opt(static_cast<const Chain_opt&>(column)),
 
  414      operators_(colSettings == nullptr ? column.operators_ : nullptr),
 
  415      entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)),
 
  418  static_assert(!Master_matrix::Option_list::has_row_access,
 
  419                "Simple copy constructor not available when row access option enabled. Please specify the new column " 
  420                "index and the row container.");
 
  421  if constexpr (!Master_matrix::Option_list::is_z2) {
 
  422    if (colSettings != 
nullptr) operators_ = &(colSettings->operators);
 
  425  column_.clone_from(column.column_, New_cloner(entryPool_), Delete_disposer(
this));
 
  428template <
class Master_matrix>
 
  429template <
class Row_container>
 
  430inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(
const Intrusive_list_column& column,
 
  432                                                                   Row_container* rowContainer,
 
  433                                                                   Column_settings* colSettings)
 
  434    : RA_opt(columnIndex, rowContainer),
 
  435      Dim_opt(static_cast<const Dim_opt&>(column)),
 
  436      Chain_opt(static_cast<const Chain_opt&>(column)),
 
  437      operators_(colSettings == nullptr ? column.operators_ : nullptr),
 
  438      entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor)),
 
  441  if constexpr (!Master_matrix::Option_list::is_z2) {
 
  442    if (colSettings != 
nullptr) operators_ = &(colSettings->operators);
 
  445  for (
const Entry& entry : column.column_) {
 
  446    if constexpr (Master_matrix::Option_list::is_z2) {
 
  447      _insert_entry(entry.get_row_index(), column_.end());
 
  449      _insert_entry(entry.get_element(), entry.get_row_index(), column_.end());
 
  454template <
class Master_matrix>
 
  455inline Intrusive_list_column<Master_matrix>::Intrusive_list_column(Intrusive_list_column&& column) noexcept
 
  456    : RA_opt(std::move(
static_cast<RA_opt&
>(column))),
 
  457      Dim_opt(std::move(
static_cast<Dim_opt&
>(column))),
 
  458      Chain_opt(std::move(
static_cast<Chain_opt&
>(column))),
 
  459      operators_(std::exchange(column.operators_, 
nullptr)),
 
  460      entryPool_(std::exchange(column.entryPool_, 
nullptr)),
 
  461      column_(std::move(column.column_))
 
  464template <
class Master_matrix>
 
  465inline Intrusive_list_column<Master_matrix>::~Intrusive_list_column()
 
  467  column_.clear_and_dispose(Delete_disposer(
this));
 
  470template <
class Master_matrix>
 
  471inline std::vector<typename Intrusive_list_column<Master_matrix>::Field_element>
 
  472Intrusive_list_column<Master_matrix>::get_content(
int columnLength)
 const 
  474  if (columnLength < 0 && column_.size() > 0)
 
  475    columnLength = column_.back().get_row_index() + 1;
 
  476  else if (columnLength < 0)
 
  477    return std::vector<Field_element>();
 
  479  std::vector<Field_element> container(columnLength);
 
  480  for (
auto it = column_.begin(); it != column_.end() && it->get_row_index() < 
static_cast<ID_index
>(columnLength);
 
  482    if constexpr (Master_matrix::Option_list::is_z2) {
 
  483      container[it->get_row_index()] = 1;
 
  485      container[it->get_row_index()] = it->get_element();
 
  491template <
class Master_matrix>
 
  492inline bool Intrusive_list_column<Master_matrix>::is_non_zero(ID_index rowIndex)
 const 
  497  for (
const Entry& entry : column_)
 
  498    if (entry.get_row_index() == rowIndex) 
return true;
 
  503template <
class Master_matrix>
 
  504inline bool Intrusive_list_column<Master_matrix>::is_empty()
 const 
  506  return column_.empty();
 
  509template <
class Master_matrix>
 
  510inline std::size_t Intrusive_list_column<Master_matrix>::size()
 const 
  512  return column_.size();
 
  515template <
class Master_matrix>
 
  516template <
class Row_index_map>
 
  517inline void Intrusive_list_column<Master_matrix>::reorder(
const Row_index_map& valueMap,
 
  518                                                          [[maybe_unused]] Index columnIndex)
 
  520  static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
 
  521                "Method not available for chain columns.");
 
  523  for (
auto it = column_.begin(); it != column_.end(); ++it) {
 
  524    Entry* entry = &(*it);
 
  525    if constexpr (Master_matrix::Option_list::has_row_access) {
 
  526      RA_opt::unlink(entry);
 
  527      if (columnIndex != Master_matrix::template get_null_value<Index>()) entry->set_column_index(columnIndex);
 
  529    entry->set_row_index(valueMap.at(entry->get_row_index()));
 
  530    if constexpr (Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access)
 
  531      RA_opt::insert_entry(entry->get_row_index(), entry);
 
  535  if constexpr (!Master_matrix::Option_list::has_intrusive_rows && Master_matrix::Option_list::has_row_access) {
 
  536    for (
auto it = column_.begin(); it != column_.end(); ++it) {
 
  537      Entry* entry = &(*it);
 
  538      RA_opt::insert_entry(entry->get_row_index(), entry);
 
  545template <
class Master_matrix>
 
  546inline void Intrusive_list_column<Master_matrix>::clear()
 
  548  static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
 
  549                "Method not available for chain columns as a base element should not be empty.");
 
  551  column_.clear_and_dispose(Delete_disposer(
this));
 
  554template <
class Master_matrix>
 
  555inline void Intrusive_list_column<Master_matrix>::clear(ID_index rowIndex)
 
  557  static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
 
  558                "Method not available for chain columns.");
 
  560  auto it = column_.begin();
 
  561  while (it != column_.end() && it->get_row_index() != rowIndex) it++;
 
  562  if (it != column_.end()) _delete_entry(it);
 
  565template <
class Master_matrix>
 
  566inline typename Intrusive_list_column<Master_matrix>::ID_index Intrusive_list_column<Master_matrix>::get_pivot()
 const 
  568  static_assert(Master_matrix::isNonBasic,
 
  569                "Method not available for base columns.");  
 
  571  if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
 
  572    if (column_.empty()) 
return Master_matrix::template get_null_value<ID_index>();
 
  573    return column_.back().get_row_index();
 
  575    return Chain_opt::get_pivot();
 
  579template <
class Master_matrix>
 
  580inline typename Intrusive_list_column<Master_matrix>::Field_element
 
  581Intrusive_list_column<Master_matrix>::get_pivot_value()
 const 
  583  static_assert(Master_matrix::isNonBasic,
 
  584                "Method not available for base columns.");  
 
  586  if constexpr (Master_matrix::Option_list::is_z2) {
 
  589    if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
 
  590      if (column_.empty()) 
return 0;
 
  591      return column_.back().get_element();
 
  593      if (Chain_opt::get_pivot() == Master_matrix::template get_null_value<ID_index>()) 
return Field_element();
 
  594      for (
const Entry& entry : column_) {
 
  595        if (entry.get_row_index() == Chain_opt::get_pivot()) 
return entry.get_element();
 
  597      return Field_element();  
 
  602template <
class Master_matrix>
 
  603inline typename Intrusive_list_column<Master_matrix>::iterator Intrusive_list_column<Master_matrix>::begin() noexcept
 
  605  return column_.begin();
 
  608template <
class Master_matrix>
 
  609inline typename Intrusive_list_column<Master_matrix>::const_iterator Intrusive_list_column<Master_matrix>::begin()
 
  612  return column_.begin();
 
  615template <
class Master_matrix>
 
  616inline typename Intrusive_list_column<Master_matrix>::iterator Intrusive_list_column<Master_matrix>::end() noexcept
 
  618  return column_.end();
 
  621template <
class Master_matrix>
 
  622inline typename Intrusive_list_column<Master_matrix>::const_iterator Intrusive_list_column<Master_matrix>::end()
 
  625  return column_.end();
 
  628template <
class Master_matrix>
 
  629inline typename Intrusive_list_column<Master_matrix>::reverse_iterator
 
  630Intrusive_list_column<Master_matrix>::rbegin() noexcept
 
  632  return column_.rbegin();
 
  635template <
class Master_matrix>
 
  636inline typename Intrusive_list_column<Master_matrix>::const_reverse_iterator
 
  637Intrusive_list_column<Master_matrix>::rbegin() const noexcept
 
  639  return column_.rbegin();
 
  642template <
class Master_matrix>
 
  643inline typename Intrusive_list_column<Master_matrix>::reverse_iterator
 
  644Intrusive_list_column<Master_matrix>::rend() noexcept
 
  646  return column_.rend();
 
  649template <
class Master_matrix>
 
  650inline typename Intrusive_list_column<Master_matrix>::const_reverse_iterator
 
  651Intrusive_list_column<Master_matrix>::rend() const noexcept
 
  653  return column_.rend();
 
  656template <
class Master_matrix>
 
  657template <
class Entry_range>
 
  658inline Intrusive_list_column<Master_matrix>& Intrusive_list_column<Master_matrix>::operator+=(
const Entry_range& column)
 
  660  static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Intrusive_list_column>),
 
  661                "For boundary columns, the range has to be a column of same type to help ensure the validity of the " 
  663  static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
 
  664                "For chain columns, the given column cannot be constant.");
 
  671template <
class Master_matrix>
 
  672inline Intrusive_list_column<Master_matrix>& Intrusive_list_column<Master_matrix>::operator+=(
 
  673    Intrusive_list_column& column)
 
  675  if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
 
  678      Chain_opt::swap_pivots(column);
 
  679      Dim_opt::swap_dimension(column);
 
  688template <
class Master_matrix>
 
  689inline Intrusive_list_column<Master_matrix>& Intrusive_list_column<Master_matrix>::operator*=(
const Field_element& val)
 
  691  if constexpr (Master_matrix::Option_list::is_z2) {
 
  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.");
 
  700    Field_element realVal = operators_->get_value(val);
 
  702    if (realVal == Field_operators::get_additive_identity()) {
 
  703      if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
 
  704        throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
 
  711    if (realVal == Field_operators::get_multiplicative_identity()) 
return *
this;
 
  713    for (Entry& entry : column_) {
 
  714      operators_->multiply_inplace(entry.get_element(), realVal);
 
  715      if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(entry);
 
  722template <
class Master_matrix>
 
  723template <
class Entry_range>
 
  724inline Intrusive_list_column<Master_matrix>& Intrusive_list_column<Master_matrix>::multiply_target_and_add(
 
  725    const Field_element& val,
 
  726    const Entry_range& column)
 
  728  static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Intrusive_list_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  if constexpr (Master_matrix::Option_list::is_z2) {
 
  742    _multiply_target_and_add(val, column);
 
  748template <
class Master_matrix>
 
  749inline Intrusive_list_column<Master_matrix>& Intrusive_list_column<Master_matrix>::multiply_target_and_add(
 
  750    const Field_element& val,
 
  751    Intrusive_list_column& column)
 
  753  if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
 
  755    if constexpr (Master_matrix::Option_list::is_z2) {
 
  758          Chain_opt::swap_pivots(column);
 
  759          Dim_opt::swap_dimension(column);
 
  762        throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
 
  765      if (_multiply_target_and_add(val, column)) {
 
  766        Chain_opt::swap_pivots(column);
 
  767        Dim_opt::swap_dimension(column);
 
  771    if constexpr (Master_matrix::Option_list::is_z2) {
 
  779      _multiply_target_and_add(val, column);
 
  786template <
class Master_matrix>
 
  787template <
class Entry_range>
 
  788inline Intrusive_list_column<Master_matrix>& Intrusive_list_column<Master_matrix>::multiply_source_and_add(
 
  789    const Entry_range& column,
 
  790    const Field_element& val)
 
  792  static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Intrusive_list_column>),
 
  793                "For boundary columns, the range has to be a column of same type to help ensure the validity of the " 
  795  static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
 
  796                "For chain columns, the given column cannot be constant.");
 
  798  if constexpr (Master_matrix::Option_list::is_z2) {
 
  803    _multiply_source_and_add(column, val);
 
  809template <
class Master_matrix>
 
  810inline Intrusive_list_column<Master_matrix>& Intrusive_list_column<Master_matrix>::multiply_source_and_add(
 
  811    Intrusive_list_column& column,
 
  812    const Field_element& val)
 
  814  if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
 
  816    if constexpr (Master_matrix::Option_list::is_z2) {
 
  819          Chain_opt::swap_pivots(column);
 
  820          Dim_opt::swap_dimension(column);
 
  824      if (_multiply_source_and_add(column, val)) {
 
  825        Chain_opt::swap_pivots(column);
 
  826        Dim_opt::swap_dimension(column);
 
  830    if constexpr (Master_matrix::Option_list::is_z2) {
 
  835      _multiply_source_and_add(column, val);
 
  842template <
class Master_matrix>
 
  843inline void Intrusive_list_column<Master_matrix>::push_back(
const Entry& entry)
 
  845  static_assert(Master_matrix::Option_list::is_of_boundary_type, 
"`push_back` is not available for Chain matrices.");
 
  847  GUDHI_CHECK(entry.get_row_index() > get_pivot(), 
"The new row index has to be higher than the current pivot.");
 
  849  if constexpr (Master_matrix::Option_list::is_z2) {
 
  850    _insert_entry(entry.get_row_index(), column_.end());
 
  852    _insert_entry(entry.get_element(), entry.get_row_index(), column_.end());
 
  856template <
class Master_matrix>
 
  857inline Intrusive_list_column<Master_matrix>& Intrusive_list_column<Master_matrix>::operator=(
 
  858    const Intrusive_list_column& other)
 
  860  static_assert(!Master_matrix::Option_list::has_row_access, 
"= assignment not enabled with row access option.");
 
  862  Dim_opt::operator=(other);
 
  863  Chain_opt::operator=(other);
 
  866  column_.clear_and_dispose(Delete_disposer(
this));
 
  867  operators_ = other.operators_;
 
  868  entryPool_ = other.entryPool_;
 
  869  column_.clone_from(other.column_, New_cloner(entryPool_), Delete_disposer(
this));
 
  874template <
class Master_matrix>
 
  875inline void Intrusive_list_column<Master_matrix>::_delete_entry(iterator& it)
 
  877  it = column_.erase_and_dispose(it, Delete_disposer(
this));
 
  880template <
class Master_matrix>
 
  881inline typename Intrusive_list_column<Master_matrix>::Entry* Intrusive_list_column<Master_matrix>::_insert_entry(
 
  882    const Field_element& value,
 
  884    const iterator& position)
 
  886  if constexpr (Master_matrix::Option_list::has_row_access) {
 
  887    Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex);
 
  888    newEntry->set_element(value);
 
  889    column_.insert(position, *newEntry);
 
  890    RA_opt::insert_entry(rowIndex, newEntry);
 
  893    Entry* newEntry = entryPool_->construct(rowIndex);
 
  894    newEntry->set_element(value);
 
  895    column_.insert(position, *newEntry);
 
  900template <
class Master_matrix>
 
  901inline void Intrusive_list_column<Master_matrix>::_insert_entry(ID_index rowIndex, 
const iterator& position)
 
  903  if constexpr (Master_matrix::Option_list::has_row_access) {
 
  904    Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex);
 
  905    column_.insert(position, *newEntry);
 
  906    RA_opt::insert_entry(rowIndex, newEntry);
 
  908    Entry* newEntry = entryPool_->construct(rowIndex);
 
  909    column_.insert(position, *newEntry);
 
  913template <
class Master_matrix>
 
  914template <
class Entry_range>
 
  915inline bool Intrusive_list_column<Master_matrix>::_add(
const Entry_range& column)
 
  917  return _add_to_column(column, *
this);
 
  920template <
class Master_matrix>
 
  921template <
class Entry_range>
 
  922inline bool Intrusive_list_column<Master_matrix>::_multiply_target_and_add(
const Field_element& val,
 
  923                                                                           const Entry_range& column)
 
  925  return _multiply_target_and_add_to_column(val, column, *
this);
 
  928template <
class Master_matrix>
 
  929template <
class Entry_range>
 
  930inline bool Intrusive_list_column<Master_matrix>::_multiply_source_and_add(
const Entry_range& column,
 
  931                                                                           const Field_element& val)
 
  933  return _multiply_source_and_add_to_column(val, column, *
this);
 
  947template <
class Master_matrix>
 
  948struct std::hash<
Gudhi::persistence_matrix::Intrusive_list_column<Master_matrix> > {
 
  950    return Gudhi::persistence_matrix::hash_column(column);
 
Column class following the PersistenceMatrixColumn concept.
Definition: intrusive_list_column.h:49
 
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