File indexing completed on 2024-09-07 04:35:08
0001 #ifndef PolyType_h
0002 #define PolyType_h
0003
0004 #include <boost/iterator/iterator_facade.hpp>
0005 #include <boost/operators.hpp>
0006 #include <iostream>
0007 #include <list>
0008 #include <set>
0009
0010 template <class T>
0011 class poly;
0012 template <class T>
0013 poly<T> operator+(const poly<T>&, const char*);
0014 template <class T>
0015 poly<T> operator+(const char*, const poly<T>&);
0016
0017 template <class T>
0018 class poly
0019 : boost::incrementable<
0020 poly<T>,
0021 boost::addable<
0022 poly<T>,
0023 boost::multipliable<poly<T>, boost::multipliable2<poly<T>, T, boost::less_than_comparable<poly<T> > > > > > {
0024 std::list<std::set<T> > columns;
0025
0026 public:
0027 class const_iterator;
0028 typedef T value_type;
0029 typedef typename std::list<std::set<T> >::iterator column_iterator;
0030 typedef typename std::list<std::set<T> >::const_iterator const_column_iterator;
0031 poly() {}
0032 poly(const T& t) { operator+=(t); }
0033
0034 bool operator<(const poly& R) const {
0035 const_column_iterator column(columns.begin()), Rcolumn(R.columns.begin());
0036 while (column != columns.end() && Rcolumn != R.columns.end() && *column == *Rcolumn) {
0037 ++column;
0038 ++Rcolumn;
0039 }
0040 return column != columns.end() && Rcolumn != R.columns.end() && *column < *Rcolumn;
0041 }
0042 poly operator++() {
0043 columns.push_back(std::set<T>());
0044 return *this;
0045 }
0046 poly operator+=(const poly& R) {
0047 columns.insert(columns.end(), R.columns.begin(), R.columns.end());
0048 return *this;
0049 }
0050 poly operator+=(const T& r) {
0051 operator++();
0052 return operator*=(r);
0053 }
0054 poly operator*=(const T& r) {
0055 columns.back().insert(r);
0056 return *this;
0057 }
0058 poly operator*=(const poly& R) {
0059 columns.back().insert(R.begin(), R.end());
0060 return *this;
0061 }
0062 friend poly<T> operator+ <>(const poly<T>&, const char*);
0063 friend poly<T> operator+ <>(const char*, const poly<T>&);
0064
0065 const_iterator begin() const { return const_iterator(*this); }
0066 const_iterator end() const { return const_iterator::end_of(*this); }
0067
0068 auto const& getColumns() const { return columns; }
0069 auto& getColumns() { return columns; }
0070
0071 size_t size() const {
0072 if (columns.empty())
0073 return 0;
0074 size_t size = 1;
0075 for (const_column_iterator column = columns.begin(); column != columns.end(); ++column)
0076 size *= column->size();
0077 return size;
0078 }
0079
0080 class const_iterator : public boost::iterator_facade<const_iterator, T const, boost::bidirectional_traversal_tag, T> {
0081 friend class boost::iterator_core_access;
0082
0083 std::list<typename std::set<T>::const_iterator> state;
0084 typename std::list<std::set<T> >::const_iterator begin, end;
0085
0086 typedef typename std::list<typename std::set<T>::const_iterator>::iterator state_iterator;
0087 typedef typename std::list<typename std::set<T>::const_iterator>::const_iterator const_state_iterator;
0088
0089 bool equal(const_iterator const& rhs) const { return std::equal(state.begin(), state.end(), rhs.state.begin()); }
0090 T dereference() const {
0091 T s;
0092 for (const_state_iterator istate = state.begin(); istate != state.end(); ++istate)
0093 s += **istate;
0094 return s;
0095 }
0096 void increment() {
0097 state_iterator istate = state.begin();
0098 const_column_iterator column = begin;
0099 while (column != end && ++*istate == column->end()) {
0100 ++istate;
0101 ++column;
0102 }
0103 if (column == end) {
0104 --column;
0105 --istate;
0106 }
0107 while (istate != state.begin()) {
0108 --istate;
0109 *istate = (--column)->begin();
0110 }
0111 }
0112 void decrement() {
0113 state_iterator istate = state.begin();
0114 const_column_iterator column = begin;
0115 while (column != end && *istate == column->begin()) {
0116 ++istate;
0117 ++column;
0118 }
0119 if (column != end)
0120 --*istate;
0121 while (istate != state.begin()) {
0122 --istate;
0123 *istate = --((--column)->end());
0124 }
0125 }
0126
0127 public:
0128 const_iterator() {}
0129 const_iterator(const poly& p) : begin(p.getColumns().begin()), end(p.getColumns().end()) {
0130 const_column_iterator column = begin;
0131 while (column != end)
0132 state.push_back((column++)->begin());
0133 }
0134 static const_iterator end_of(const poly& p) {
0135 const_iterator it(p);
0136 if (p.size() != 0)
0137 *--(it.state.end()) = (--p.getColumns().end())->end();
0138 return it;
0139 }
0140 };
0141 };
0142
0143 template <class T>
0144 poly<T> operator+(const poly<T>& lhs, const char* rhs) {
0145 return lhs + poly<T>(rhs);
0146 }
0147 template <class T>
0148 poly<T> operator+(const char* lhs, const poly<T>& rhs) {
0149 return poly<T>(lhs) + rhs;
0150 }
0151
0152 template <class charT, class traits, class T>
0153 inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& strm, const poly<T>& f) {
0154 for (auto const& column : f.getColumns()) {
0155 strm << "( ";
0156 for (auto const& entry : column)
0157 strm << entry << ", ";
0158 strm << " )" << std::endl;
0159 }
0160 return strm;
0161 }
0162
0163 #endif