18#ifndef PM_UNORDERED_SET_COLUMN_H 
   19#define PM_UNORDERED_SET_COLUMN_H 
   27#include <boost/iterator/indirect_iterator.hpp> 
   28#if BOOST_VERSION >= 108100 
   29#include <boost/unordered/unordered_flat_set.hpp> 
   31#include <unordered_set> 
   37namespace persistence_matrix {
 
   42struct EntryPointerHash {
 
   43  size_t operator()(
const Entry* c)
 const { 
return std::hash<Entry>()(*c); }
 
   47struct EntryPointerEq {
 
   48  bool operator()(
const Entry* c1, 
const Entry* c2)
 const { 
return *c1 == *c2; }
 
   63template <
class Master_matrix>
 
   69  using Master = Master_matrix;
 
   70  using Index = 
typename Master_matrix::Index;
 
   71  using ID_index = 
typename Master_matrix::ID_index;
 
   72  using Dimension = 
typename Master_matrix::Dimension;
 
   73  using Field_element = 
typename Master_matrix::Element;
 
   74  using Entry = 
typename Master_matrix::Matrix_entry;
 
   75  using Column_settings = 
typename Master_matrix::Column_settings;
 
   78  using Field_operators = 
typename Master_matrix::Field_operators;
 
   79  using Entry_constructor = 
typename Master_matrix::Entry_constructor;
 
   81  struct EntryPointerComp {
 
   82    bool operator()(
const Entry* c1, 
const Entry* c2)
 const { 
return *c1 < *c2; }
 
   85#if BOOST_VERSION >= 108100 
   86  using Column_support = boost::unordered_flat_set<Entry*, EntryPointerHash<Entry>, EntryPointerEq<Entry>>;
 
   88  using Column_support = std::unordered_set<Entry*, EntryPointerHash<Entry>, EntryPointerEq<Entry>>;
 
   92  using iterator = boost::indirect_iterator<typename Column_support::iterator>;
 
   93  using const_iterator = boost::indirect_iterator<typename Column_support::const_iterator>;
 
   96  template <
class Container = 
typename Master_matrix::Boundary>
 
   98  template <
class Container = 
typename Master_matrix::Boundary, 
class Row_container>
 
  100                       const Container& nonZeroRowIndices,
 
  101                       Row_container* rowContainer,
 
  102                       Column_settings* colSettings);
 
  103  template <
class Container = 
typename Master_matrix::Boundary>
 
  104  Unordered_set_column(
const Container& nonZeroChainRowIndices, Dimension dimension, Column_settings* colSettings);
 
  105  template <
class Container = 
typename Master_matrix::Boundary, 
class Row_container>
 
  107                       const Container& nonZeroChainRowIndices,
 
  109                       Row_container* rowContainer,
 
  110                       Column_settings* colSettings);
 
  112  template <
class Row_container>
 
  115                       Row_container* rowContainer,
 
  116                       Column_settings* colSettings = 
nullptr);
 
  120  std::vector<Field_element> get_content(
int columnLength = -1) 
const;
 
  121  bool is_non_zero(ID_index rowIndex) 
const;
 
  122  bool is_empty() 
const;
 
  123  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;
 
  139  template <
class Entry_range>
 
  146  template <
class Entry_range>
 
  147  Unordered_set_column& multiply_target_and_add(
const Field_element& val, 
const Entry_range& column);
 
  150  template <
class Entry_range>
 
  151  Unordered_set_column& multiply_source_and_add(
const Entry_range& column, 
const Field_element& val);
 
  154  void push_back(
const Entry& entry);
 
  157    if (&c1 == &c2) 
return true;
 
  158    if (c1.column_.size() != c2.column_.size()) 
return false;
 
  160    for (Entry* entry : c1.column_) {
 
  161      auto it = c2.column_.find(entry);
 
  162      if (it == c2.column_.end()) 
return false;
 
  163      if constexpr (!Master_matrix::Option_list::is_z2)
 
  164        if ((*it)->get_element() != entry->get_element()) 
return false;
 
  170    if (&c1 == &c2) 
return false;
 
  172    using ID_index = Unordered_set_column<Master_matrix>::ID_index;
 
  174        typename std::conditional<Master_matrix::Option_list::is_z2,
 
  176                                  std::pair<ID_index, unsigned int>
 
  179    auto it1 = c1.column_.begin();
 
  180    auto it2 = c2.column_.begin();
 
  181    std::set<Entry_rep> entries1, entries2;
 
  182    while (it1 != c1.column_.end() && it2 != c2.column_.end()) {
 
  183      if constexpr (Master_matrix::Option_list::is_z2) {
 
  184        entries1.insert((*it1)->get_row_index());
 
  185        entries2.insert((*it2)->get_row_index());
 
  187        entries1.emplace((*it1)->get_row_index(), (*it1)->get_element());
 
  188        entries2.emplace((*it2)->get_row_index(), (*it2)->get_element());
 
  193    while (it1 != c1.column_.end()) {
 
  194      if constexpr (Master_matrix::Option_list::is_z2) {
 
  195        entries1.insert((*it1)->get_row_index());
 
  197        entries1.emplace((*it1)->get_row_index(), (*it1)->get_element());
 
  201    while (it2 != c2.column_.end()) {
 
  202      if constexpr (Master_matrix::Option_list::is_z2) {
 
  203        entries2.insert((*it2)->get_row_index());
 
  205        entries2.emplace((*it2)->get_row_index(), (*it2)->get_element());
 
  209    return entries1 < entries2;
 
  222    col1.column_.swap(col2.column_);
 
  223    std::swap(col1.operators_, col2.operators_);
 
  224    std::swap(col1.entryPool_, col2.entryPool_);
 
  232  Column_support column_;
 
  233  Field_operators* operators_;
 
  234  Entry_constructor* entryPool_;
 
  236  void _delete_entry(
typename Column_support::iterator& it);
 
  237  Entry* _insert_entry(
const Field_element& value, ID_index rowIndex);
 
  238  void _insert_entry(ID_index rowIndex);
 
  239  template <
class Entry_range>
 
  240  bool _add(
const Entry_range& column);
 
  241  template <
class Entry_range>
 
  242  bool _multiply_target_and_add(
const Field_element& val, 
const Entry_range& column);
 
  243  template <
class Entry_range>
 
  244  bool _multiply_source_and_add(
const Entry_range& column, 
const Field_element& val);
 
  245  template <
class Entry_range, 
typename F1, 
typename F2>
 
  246  bool _generic_add(
const Entry_range& source, F1&& process_source, F2&& update_target);
 
  249template <
class Master_matrix>
 
  255      entryPool_(colSettings == nullptr ? nullptr : &(colSettings->entryConstructor))
 
  257  if (operators_ == 
nullptr && entryPool_ == 
nullptr)
 
  259  if constexpr (!Master_matrix::Option_list::is_z2) {
 
  260    operators_ = &(colSettings->operators);
 
  264template <
class Master_matrix>
 
  265template <
class Container>
 
  266inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Container& nonZeroRowIndices,
 
  267                                                                 Column_settings* colSettings)
 
  269      Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
 
  271      column_(nonZeroRowIndices.size()),
 
  273      entryPool_(&(colSettings->entryConstructor))
 
  275  static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
 
  276                "Constructor not available for chain columns, please specify the dimension of the chain.");
 
  278  if constexpr (Master_matrix::Option_list::is_z2) {
 
  279    for (ID_index 
id : nonZeroRowIndices) {
 
  283    operators_ = &(colSettings->operators);
 
  284    for (
const auto& p : nonZeroRowIndices) {
 
  285      _insert_entry(operators_->get_value(p.second), p.first);
 
  290template <
class Master_matrix>
 
  291template <
class Container, 
class Row_container>
 
  292inline Unordered_set_column<Master_matrix>::Unordered_set_column(Index columnIndex,
 
  293                                                                 const Container& nonZeroRowIndices,
 
  294                                                                 Row_container* rowContainer,
 
  295                                                                 Column_settings* colSettings)
 
  296    : RA_opt(columnIndex, rowContainer),
 
  297      Dim_opt(nonZeroRowIndices.size() == 0 ? 0 : nonZeroRowIndices.size() - 1),
 
  299        if constexpr (Master_matrix::Option_list::is_z2) {
 
  300          return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
 
  301                     ? Master_matrix::template get_null_value<ID_index>()
 
  302                     : *
std::prev(nonZeroRowIndices.end());
 
  304          return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
 
  305                     ? Master_matrix::template get_null_value<ID_index>()
 
  306                     : 
std::prev(nonZeroRowIndices.end())->first;
 
  309      column_(nonZeroRowIndices.size()),
 
  311      entryPool_(&(colSettings->entryConstructor))
 
  313  static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
 
  314                "Constructor not available for chain columns, please specify the dimension of the chain.");
 
  316  if constexpr (Master_matrix::Option_list::is_z2) {
 
  317    for (ID_index 
id : nonZeroRowIndices) {
 
  321    operators_ = &(colSettings->operators);
 
  322    for (
const auto& p : nonZeroRowIndices) {
 
  323      _insert_entry(operators_->get_value(p.second), p.first);
 
  328template <
class Master_matrix>
 
  329template <
class Container>
 
  330inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Container& nonZeroRowIndices,
 
  332                                                                 Column_settings* colSettings)
 
  336        if constexpr (Master_matrix::Option_list::is_z2) {
 
  337          return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
 
  338                     ? Master_matrix::template get_null_value<ID_index>()
 
  339                     : *
std::prev(nonZeroRowIndices.end());
 
  341          return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
 
  342                     ? Master_matrix::template get_null_value<ID_index>()
 
  343                     : 
std::prev(nonZeroRowIndices.end())->first;
 
  346      column_(nonZeroRowIndices.size()),
 
  348      entryPool_(&(colSettings->entryConstructor))
 
  350  if constexpr (Master_matrix::Option_list::is_z2) {
 
  351    for (ID_index 
id : nonZeroRowIndices) {
 
  355    operators_ = &(colSettings->operators);
 
  356    for (
const auto& p : nonZeroRowIndices) {
 
  357      _insert_entry(operators_->get_value(p.second), p.first);
 
  362template <
class Master_matrix>
 
  363template <
class Container, 
class Row_container>
 
  364inline Unordered_set_column<Master_matrix>::Unordered_set_column(Index columnIndex,
 
  365                                                                 const Container& nonZeroRowIndices,
 
  367                                                                 Row_container* rowContainer,
 
  368                                                                 Column_settings* colSettings)
 
  369    : RA_opt(columnIndex, rowContainer),
 
  372        if constexpr (Master_matrix::Option_list::is_z2) {
 
  373          return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
 
  374                     ? Master_matrix::template get_null_value<ID_index>()
 
  375                     : *
std::prev(nonZeroRowIndices.end());
 
  377          return nonZeroRowIndices.begin() == nonZeroRowIndices.end()
 
  378                     ? Master_matrix::template get_null_value<ID_index>()
 
  379                     : 
std::prev(nonZeroRowIndices.end())->first;
 
  382      column_(nonZeroRowIndices.size()),
 
  384      entryPool_(&(colSettings->entryConstructor))
 
  386  if constexpr (Master_matrix::Option_list::is_z2) {
 
  387    for (ID_index 
id : nonZeroRowIndices) {
 
  391    operators_ = &(colSettings->operators);
 
  392    for (
const auto& p : nonZeroRowIndices) {
 
  393      _insert_entry(operators_->get_value(p.second), p.first);
 
  398template <
class Master_matrix>
 
  399inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Unordered_set_column& column,
 
  400                                                                 Column_settings* colSettings)
 
  402      Dim_opt(static_cast<const Dim_opt&>(column)),
 
  403      Chain_opt(static_cast<const Chain_opt&>(column)),
 
  404      column_(column.column_.bucket_count()),
 
  405      operators_(colSettings == nullptr ? column.operators_ : nullptr),
 
  406      entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
 
  408  static_assert(!Master_matrix::Option_list::has_row_access,
 
  409                "Simple copy constructor not available when row access option enabled. Please specify the new column " 
  410                "index and the row container.");
 
  412  if constexpr (!Master_matrix::Option_list::is_z2) {
 
  413    if (colSettings != 
nullptr) operators_ = &(colSettings->operators);
 
  416  for (
const Entry* entry : column.column_) {
 
  417    if constexpr (Master_matrix::Option_list::is_z2) {
 
  418      _insert_entry(entry->get_row_index());
 
  420      _insert_entry(entry->get_element(), entry->get_row_index());
 
  425template <
class Master_matrix>
 
  426template <
class Row_container>
 
  427inline Unordered_set_column<Master_matrix>::Unordered_set_column(
const Unordered_set_column& column,
 
  429                                                                 Row_container* rowContainer,
 
  430                                                                 Column_settings* colSettings)
 
  431    : RA_opt(columnIndex, rowContainer),
 
  432      Dim_opt(static_cast<const Dim_opt&>(column)),
 
  433      Chain_opt(static_cast<const Chain_opt&>(column)),
 
  434      column_(column.column_.bucket_count()),
 
  435      operators_(colSettings == nullptr ? column.operators_ : nullptr),
 
  436      entryPool_(colSettings == nullptr ? column.entryPool_ : &(colSettings->entryConstructor))
 
  438  if constexpr (!Master_matrix::Option_list::is_z2) {
 
  439    if (colSettings != 
nullptr) operators_ = &(colSettings->operators);
 
  442  for (
const Entry* entry : column.column_) {
 
  443    if constexpr (Master_matrix::Option_list::is_z2) {
 
  444      _insert_entry(entry->get_row_index());
 
  446      _insert_entry(entry->get_element(), entry->get_row_index());
 
  451template <
class Master_matrix>
 
  452inline Unordered_set_column<Master_matrix>::Unordered_set_column(Unordered_set_column&& column) noexcept
 
  453    : RA_opt(std::move(
static_cast<RA_opt&
>(column))),
 
  454      Dim_opt(std::move(
static_cast<Dim_opt&
>(column))),
 
  455      Chain_opt(std::move(
static_cast<Chain_opt&
>(column))),
 
  456      column_(std::move(column.column_)),
 
  457      operators_(std::exchange(column.operators_, 
nullptr)),
 
  458      entryPool_(std::exchange(column.entryPool_, 
nullptr))
 
  461template <
class Master_matrix>
 
  462inline Unordered_set_column<Master_matrix>::~Unordered_set_column()
 
  464  for (
auto* entry : column_) {
 
  465    if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
 
  466    entryPool_->destroy(entry);
 
  470template <
class Master_matrix>
 
  471inline std::vector<typename Unordered_set_column<Master_matrix>::Field_element>
 
  472Unordered_set_column<Master_matrix>::get_content(
int columnLength)
 const 
  474  if (columnLength < 0 && column_.size() > 0)
 
  475    columnLength = (*std::max_element(column_.begin(), column_.end(), EntryPointerComp()))->get_row_index() + 1;
 
  476  else if (columnLength < 0)
 
  477    return std::vector<Field_element>();
 
  479  std::vector<Field_element> container(columnLength, 0);
 
  480  for (
auto it = column_.begin(); it != column_.end(); ++it) {
 
  481    if ((*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();
 
  492template <
class Master_matrix>
 
  493inline bool Unordered_set_column<Master_matrix>::is_non_zero(ID_index rowIndex)
 const 
  495  Entry entry(rowIndex);
 
  496  return column_.find(&entry) != column_.end();
 
  499template <
class Master_matrix>
 
  500inline bool Unordered_set_column<Master_matrix>::is_empty()
 const 
  502  return column_.empty();
 
  505template <
class Master_matrix>
 
  506inline std::size_t Unordered_set_column<Master_matrix>::size()
 const 
  508  return column_.size();
 
  511template <
class Master_matrix>
 
  512template <
class Row_index_map>
 
  513inline void Unordered_set_column<Master_matrix>::reorder(
const Row_index_map& valueMap,
 
  514                                                         [[maybe_unused]] Index columnIndex)
 
  516  static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
 
  517                "Method not available for chain columns.");
 
  519  Column_support newSet;
 
  521  for (Entry* entry : column_) {
 
  522    if constexpr (Master_matrix::Option_list::has_row_access) {
 
  523      RA_opt::unlink(entry);
 
  524      if (columnIndex != Master_matrix::template get_null_value<Index>()) entry->set_column_index(columnIndex);
 
  526    entry->set_row_index(valueMap.at(entry->get_row_index()));
 
  527    newSet.insert(entry);
 
  528    if constexpr (Master_matrix::Option_list::has_row_access &&
 
  529                  Master_matrix::Option_list::has_intrusive_rows)  
 
  530      RA_opt::insert_entry(entry->get_row_index(), entry);
 
  534  if constexpr (Master_matrix::Option_list::has_row_access && !Master_matrix::Option_list::has_intrusive_rows) {  
 
  535    for (Entry* entry : newSet) {
 
  536      RA_opt::insert_entry(entry->get_row_index(), entry);
 
  540  column_.swap(newSet);
 
  543template <
class Master_matrix>
 
  544inline void Unordered_set_column<Master_matrix>::clear()
 
  546  static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
 
  547                "Method not available for chain columns as a base element should not be empty.");
 
  549  for (
auto* entry : column_) {
 
  550    if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
 
  551    entryPool_->destroy(entry);
 
  557template <
class Master_matrix>
 
  558inline void Unordered_set_column<Master_matrix>::clear(ID_index rowIndex)
 
  560  static_assert(!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type,
 
  561                "Method not available for chain columns.");
 
  563  auto entry = entryPool_->construct(rowIndex);
 
  564  auto it = column_.find(entry);
 
  565  if (it != column_.end()) {
 
  568  entryPool_->destroy(entry);
 
  571template <
class Master_matrix>
 
  572inline typename Unordered_set_column<Master_matrix>::ID_index Unordered_set_column<Master_matrix>::get_pivot()
 const 
  574  static_assert(Master_matrix::isNonBasic,
 
  575                "Method not available for base columns.");  
 
  577  if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
 
  578    if (column_.empty()) 
return Master_matrix::template get_null_value<ID_index>();
 
  581    return (*std::max_element(column_.begin(), column_.end(), EntryPointerComp()))->get_row_index();
 
  583    return Chain_opt::get_pivot();
 
  587template <
class Master_matrix>
 
  588inline typename Unordered_set_column<Master_matrix>::Field_element
 
  589Unordered_set_column<Master_matrix>::get_pivot_value()
 const 
  591  static_assert(Master_matrix::isNonBasic,
 
  592                "Method not available for base columns.");  
 
  594  if constexpr (Master_matrix::Option_list::is_z2) {
 
  597    if constexpr (Master_matrix::Option_list::is_of_boundary_type) {
 
  598      if (column_.empty()) 
return 0;
 
  599      return (*std::max_element(column_.begin(), column_.end(), EntryPointerComp()))->get_element();
 
  601      if (Chain_opt::get_pivot() == Master_matrix::template get_null_value<ID_index>()) 
return Field_element();
 
  602      for (
const Entry* entry : column_) {
 
  603        if (entry->get_row_index() == Chain_opt::get_pivot()) 
return entry->get_element();
 
  605      return Field_element();  
 
  610template <
class Master_matrix>
 
  611inline typename Unordered_set_column<Master_matrix>::iterator Unordered_set_column<Master_matrix>::begin() noexcept
 
  613  return column_.begin();
 
  616template <
class Master_matrix>
 
  617inline typename Unordered_set_column<Master_matrix>::const_iterator Unordered_set_column<Master_matrix>::begin()
 
  620  return column_.begin();
 
  623template <
class Master_matrix>
 
  624inline typename Unordered_set_column<Master_matrix>::iterator Unordered_set_column<Master_matrix>::end() noexcept
 
  626  return column_.end();
 
  629template <
class Master_matrix>
 
  630inline typename Unordered_set_column<Master_matrix>::const_iterator Unordered_set_column<Master_matrix>::end()
 
  633  return column_.end();
 
  636template <
class Master_matrix>
 
  637template <
class Entry_range>
 
  638inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::operator+=(
const Entry_range& column)
 
  640  static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Unordered_set_column>),
 
  641                "For boundary columns, the range has to be a column of same type to help ensure the validity of the " 
  643  static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
 
  644                "For chain columns, the given column cannot be constant.");
 
  651template <
class Master_matrix>
 
  652inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::operator+=(
 
  653    Unordered_set_column& column)
 
  655  if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
 
  658      Chain_opt::swap_pivots(column);
 
  659      Dim_opt::swap_dimension(column);
 
  668template <
class Master_matrix>
 
  669inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::operator*=(
unsigned int v)
 
  671  if constexpr (Master_matrix::Option_list::is_z2) {
 
  673      if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
 
  674        throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
 
  680    Field_element val = operators_->get_value(v);
 
  682    if (val == Field_operators::get_additive_identity()) {
 
  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.");
 
  691    if (val == Field_operators::get_multiplicative_identity()) 
return *
this;
 
  693    for (Entry* entry : column_) {
 
  694      operators_->multiply_inplace(entry->get_element(), val);
 
  695      if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(*entry);
 
  702template <
class Master_matrix>
 
  703template <
class Entry_range>
 
  704inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::multiply_target_and_add(
 
  705    const Field_element& val,
 
  706    const Entry_range& column)
 
  708  static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Unordered_set_column>),
 
  709                "For boundary columns, the range has to be a column of same type to help ensure the validity of the " 
  711  static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
 
  712                "For chain columns, the given column cannot be constant.");
 
  714  if constexpr (Master_matrix::Option_list::is_z2) {
 
  722    _multiply_target_and_add(val, column);
 
  728template <
class Master_matrix>
 
  729inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::multiply_target_and_add(
 
  730    const Field_element& val,
 
  731    Unordered_set_column& column)
 
  733  if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
 
  735    if constexpr (Master_matrix::Option_list::is_z2) {
 
  738          Chain_opt::swap_pivots(column);
 
  739          Dim_opt::swap_dimension(column);
 
  742        throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
 
  745      if (_multiply_target_and_add(val, column)) {
 
  746        Chain_opt::swap_pivots(column);
 
  747        Dim_opt::swap_dimension(column);
 
  751    if constexpr (Master_matrix::Option_list::is_z2) {
 
  759      _multiply_target_and_add(val, column);
 
  766template <
class Master_matrix>
 
  767template <
class Entry_range>
 
  768inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::multiply_source_and_add(
 
  769    const Entry_range& column,
 
  770    const Field_element& val)
 
  772  static_assert((!Master_matrix::isNonBasic || std::is_same_v<Entry_range, Unordered_set_column>),
 
  773                "For boundary columns, the range has to be a column of same type to help ensure the validity of the " 
  775  static_assert((!Master_matrix::isNonBasic || Master_matrix::Option_list::is_of_boundary_type),
 
  776                "For chain columns, the given column cannot be constant.");
 
  778  if constexpr (Master_matrix::Option_list::is_z2) {
 
  783    _multiply_source_and_add(column, val);
 
  789template <
class Master_matrix>
 
  790inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::multiply_source_and_add(
 
  791    Unordered_set_column& column,
 
  792    const Field_element& val)
 
  794  if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
 
  796    if constexpr (Master_matrix::Option_list::is_z2) {
 
  799          Chain_opt::swap_pivots(column);
 
  800          Dim_opt::swap_dimension(column);
 
  804      if (_multiply_source_and_add(column, val)) {
 
  805        Chain_opt::swap_pivots(column);
 
  806        Dim_opt::swap_dimension(column);
 
  810    if constexpr (Master_matrix::Option_list::is_z2) {
 
  815      _multiply_source_and_add(column, val);
 
  822template <
class Master_matrix>
 
  823inline void Unordered_set_column<Master_matrix>::push_back(
const Entry& entry)
 
  825  static_assert(Master_matrix::Option_list::is_of_boundary_type, 
"`push_back` is not available for Chain matrices.");
 
  827  GUDHI_CHECK(entry.get_row_index() > get_pivot(), 
"The new row index has to be higher than the current pivot.");
 
  829  if constexpr (Master_matrix::Option_list::is_z2) {
 
  830    _insert_entry(entry.get_row_index());
 
  832    _insert_entry(entry.get_element(), entry.get_row_index());
 
  836template <
class Master_matrix>
 
  837inline Unordered_set_column<Master_matrix>& Unordered_set_column<Master_matrix>::operator=(
 
  838    const Unordered_set_column& other)
 
  840  static_assert(!Master_matrix::Option_list::has_row_access, 
"= assignment not enabled with row access option.");
 
  842  Dim_opt::operator=(other);
 
  843  Chain_opt::operator=(other);
 
  845  for (
auto* entry : column_) {
 
  846    if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(entry);
 
  847    entryPool_->destroy(entry);
 
  851  operators_ = other.operators_;
 
  852  entryPool_ = other.entryPool_;
 
  854  for (
const Entry* entry : other.column_) {
 
  855    if constexpr (Master_matrix::Option_list::is_z2) {
 
  856      _insert_entry(entry->get_row_index());
 
  858      _insert_entry(entry->get_element(), entry->get_row_index());
 
  865template <
class Master_matrix>
 
  866inline void Unordered_set_column<Master_matrix>::_delete_entry(
typename Column_support::iterator& it)
 
  868  if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::unlink(*it);
 
  869  entryPool_->destroy(*it);
 
  875template <
class Master_matrix>
 
  876inline typename Unordered_set_column<Master_matrix>::Entry* Unordered_set_column<Master_matrix>::_insert_entry(
 
  877    const Field_element& value,
 
  880  if constexpr (Master_matrix::Option_list::has_row_access) {
 
  881    Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex);
 
  882    newEntry->set_element(value);
 
  883    column_.insert(newEntry);
 
  884    RA_opt::insert_entry(rowIndex, newEntry);
 
  887    Entry* newEntry = entryPool_->construct(rowIndex);
 
  888    newEntry->set_element(value);
 
  889    column_.insert(newEntry);
 
  894template <
class Master_matrix>
 
  895inline void Unordered_set_column<Master_matrix>::_insert_entry(ID_index rowIndex)
 
  897  if constexpr (Master_matrix::Option_list::has_row_access) {
 
  898    Entry* newEntry = entryPool_->construct(RA_opt::columnIndex_, rowIndex);
 
  899    column_.insert(newEntry);
 
  900    RA_opt::insert_entry(rowIndex, newEntry);
 
  902    Entry* newEntry = entryPool_->construct(rowIndex);
 
  903    column_.insert(newEntry);
 
  907template <
class Master_matrix>
 
  908template <
class Entry_range>
 
  909inline bool Unordered_set_column<Master_matrix>::_add(
const Entry_range& column)
 
  913      [&](
const Entry& oldEntry, Entry* newEntry) {
 
  914        if constexpr (!Master_matrix::Option_list::is_z2) newEntry->set_element(oldEntry.get_element());
 
  916      [&](Entry* targetEntry, 
const Entry& sourceEntry) {
 
  917        if constexpr (!Master_matrix::Option_list::is_z2)
 
  918          operators_->add_inplace(targetEntry->get_element(), sourceEntry.get_element());
 
  922template <
class Master_matrix>
 
  923template <
class Entry_range>
 
  924inline bool Unordered_set_column<Master_matrix>::_multiply_target_and_add(
const Field_element& val,
 
  925                                                                          const Entry_range& column)
 
  928    if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
 
  929      throw std::invalid_argument(
"A chain column should not be multiplied by 0.");
 
  933      for (
const Entry& v : column) {
 
  934        _insert_entry(v.get_element(), v.get_row_index());
 
  946template <
class Master_matrix>
 
  947template <
class Entry_range>
 
  948inline bool Unordered_set_column<Master_matrix>::_multiply_source_and_add(
const Entry_range& column,
 
  949                                                                          const Field_element& val)
 
  957      [&](
const Entry& oldEntry, Entry* newEntry) {
 
  958        newEntry->set_element(oldEntry.get_element());
 
  959        operators_->multiply_inplace(newEntry->get_element(), val);
 
  961      [&](Entry* targetEntry, 
const Entry& sourceEntry) {
 
  962        operators_->multiply_and_add_inplace_back(sourceEntry.get_element(), val, targetEntry->get_element());
 
  966template <
class Master_matrix>
 
  967template <
class Entry_range, 
typename F1, 
typename F2>
 
  968inline bool Unordered_set_column<Master_matrix>::_generic_add(
const Entry_range& source,
 
  972  bool pivotIsZeroed = 
false;
 
  974  for (
const Entry& entry : source) {
 
  976    if constexpr (Master_matrix::Option_list::has_row_access) {
 
  977      newEntry = entryPool_->construct(RA_opt::columnIndex_, entry.get_row_index());
 
  979      newEntry = entryPool_->construct(entry.get_row_index());
 
  981    auto res = column_.insert(newEntry);
 
  983      process_source(entry, newEntry);
 
  984      if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::insert_entry(entry.get_row_index(), newEntry);
 
  986      entryPool_->destroy(newEntry);
 
  987      if constexpr (Master_matrix::Option_list::is_z2) {
 
  988        if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
 
  989          if (entry.get_row_index() == Chain_opt::get_pivot()) pivotIsZeroed = 
true;
 
  991        _delete_entry(res.first);
 
  993        update_target(*res.first, entry);
 
  994        if ((*res.first)->get_element() == Field_operators::get_additive_identity()) {
 
  995          if constexpr (Master_matrix::isNonBasic && !Master_matrix::Option_list::is_of_boundary_type) {
 
  996            if ((*res.first)->get_row_index() == Chain_opt::get_pivot()) pivotIsZeroed = 
true;
 
  998          _delete_entry(res.first);
 
 1000          if constexpr (Master_matrix::Option_list::has_row_access) RA_opt::update_entry(**res.first);
 
 1006  return pivotIsZeroed;
 
 1020template <
class Master_matrix>
 
 1021struct std::hash<
Gudhi::persistence_matrix::Unordered_set_column<Master_matrix>> {
 
 1024    std::size_t seed = 0;
 
 1025    for (
const auto& entry : column) {
 
 1026      seed ^= std::hash<unsigned int>()(entry.get_row_index() * 
static_cast<unsigned int>(entry.get_element()));
 
Column class following the PersistenceMatrixColumn concept.
Definition: unordered_set_column.h:67
 
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