const_iterator

poly

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
#ifndef PolyType_h
#define PolyType_h

#include <boost/iterator/iterator_facade.hpp>
#include <boost/operators.hpp>
#include <iostream>
#include <list>
#include <set>

template <class T>
class poly;
template <class T>
poly<T> operator+(const poly<T>&, const char*);
template <class T>
poly<T> operator+(const char*, const poly<T>&);

template <class T>
class poly
    : boost::incrementable<
          poly<T>,
          boost::addable<
              poly<T>,
              boost::multipliable<poly<T>, boost::multipliable2<poly<T>, T, boost::less_than_comparable<poly<T> > > > > > {
  std::list<std::set<T> > columns;

public:
  class const_iterator;
  typedef T value_type;
  typedef typename std::list<std::set<T> >::iterator column_iterator;
  typedef typename std::list<std::set<T> >::const_iterator const_column_iterator;
  poly() {}
  poly(const T& t) { operator+=(t); }

  bool operator<(const poly& R) const {
    const_column_iterator column(columns.begin()), Rcolumn(R.columns.begin());
    while (column != columns.end() && Rcolumn != R.columns.end() && *column == *Rcolumn) {
      ++column;
      ++Rcolumn;
    }
    return column != columns.end() && Rcolumn != R.columns.end() && *column < *Rcolumn;
  }
  poly operator++() {
    columns.push_back(std::set<T>());
    return *this;
  }
  poly operator+=(const poly& R) {
    columns.insert(columns.end(), R.columns.begin(), R.columns.end());
    return *this;
  }
  poly operator+=(const T& r) {
    operator++();
    return operator*=(r);
  }
  poly operator*=(const T& r) {
    columns.back().insert(r);
    return *this;
  }
  poly operator*=(const poly& R) {
    columns.back().insert(R.begin(), R.end());
    return *this;
  }
  friend poly<T> operator+ <>(const poly<T>&, const char*);
  friend poly<T> operator+ <>(const char*, const poly<T>&);

  const_iterator begin() const { return const_iterator(*this); }
  const_iterator end() const { return const_iterator::end_of(*this); }

  auto const& getColumns() const { return columns; }
  auto& getColumns() { return columns; }

  size_t size() const {
    if (columns.empty())
      return 0;
    size_t size = 1;
    for (const_column_iterator column = columns.begin(); column != columns.end(); ++column)
      size *= column->size();
    return size;
  }

  class const_iterator : public boost::iterator_facade<const_iterator, T const, boost::bidirectional_traversal_tag, T> {
    friend class boost::iterator_core_access;

    std::list<typename std::set<T>::const_iterator> state;
    typename std::list<std::set<T> >::const_iterator begin, end;

    typedef typename std::list<typename std::set<T>::const_iterator>::iterator state_iterator;
    typedef typename std::list<typename std::set<T>::const_iterator>::const_iterator const_state_iterator;

    bool equal(const_iterator const& rhs) const { return std::equal(state.begin(), state.end(), rhs.state.begin()); }
    T dereference() const {
      T s;
      for (const_state_iterator istate = state.begin(); istate != state.end(); ++istate)
        s += **istate;
      return s;
    }
    void increment() {
      state_iterator istate = state.begin();
      const_column_iterator column = begin;
      while (column != end && ++*istate == column->end()) {
        ++istate;
        ++column;
      }
      if (column == end) {
        --column;
        --istate;
      }
      while (istate != state.begin()) {
        --istate;
        *istate = (--column)->begin();
      }
    }
    void decrement() {
      state_iterator istate = state.begin();
      const_column_iterator column = begin;
      while (column != end && *istate == column->begin()) {
        ++istate;
        ++column;
      }
      if (column != end)
        --*istate;
      while (istate != state.begin()) {
        --istate;
        *istate = --((--column)->end());
      }
    }

  public:
    const_iterator() {}
    const_iterator(const poly& p) : begin(p.getColumns().begin()), end(p.getColumns().end()) {
      const_column_iterator column = begin;
      while (column != end)
        state.push_back((column++)->begin());
    }
    static const_iterator end_of(const poly& p) {
      const_iterator it(p);
      if (p.size() != 0)
        *--(it.state.end()) = (--p.getColumns().end())->end();
      return it;
    }
  };
};

template <class T>
poly<T> operator+(const poly<T>& lhs, const char* rhs) {
  return lhs + poly<T>(rhs);
}
template <class T>
poly<T> operator+(const char* lhs, const poly<T>& rhs) {
  return poly<T>(lhs) + rhs;
}

template <class charT, class traits, class T>
inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& strm, const poly<T>& f) {
  for (auto const& column : f.getColumns()) {
    strm << "( ";
    for (auto const& entry : column)
      strm << entry << ", ";
    strm << " )" << std::endl;
  }
  return strm;
}

#endif