Documentation of CSL
symmetricCounter.h
Go to the documentation of this file.
1 // This file is part of MARTY.
2 //
3 // MARTY is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // MARTY is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with MARTY. If not, see <https://www.gnu.org/licenses/>.
15 
23 #ifndef SYMMETRICCOUNTER_H_INCLUDED
24 #define SYMMETRICCOUNTER_H_INCLUDED
25 
26 #include <iostream>
27 #include <vector>
28 #include <algorithm>
30 
31 template<class T>
33 
34  IMPLEMENTS_STD_VECTOR(T, counter);
35 
36  public:
37 
38  static constexpr char separator = '\'';
39 
40  symmetricCounter(size_t N)
41  :symmetricCounter(N, N)
42  {
43 
44  }
45 
46  symmetricCounter(size_t N, size_t t_max)
47  :max(t_max),
48  counter(N, 0)
49  {
50 
51  }
52 
53  symmetricCounter<T> operator++(int)
54  {
55  symmetricCounter<T> other(*this);
56  ++(*this);
57  return other;
58  }
59 
60  symmetricCounter<T>& operator++()
61  {
62  if (size() > 0 and increment(0)) {
63  adjust();
64  }
65 
66  return *this;
67  }
68 
69  static size_t combinatorial(size_t N, size_t m)
70  {
71  size_t num = 1;
72  size_t denom = 1;
73  for (size_t i = 1; i <= N; ++i) {
74  if (i > m)
75  num *= i;
76  if (i <= N - m)
77  denom *= i;
78  }
79 
80  return num / denom;
81  }
82 
83  size_t factor() const
84  {
85  auto copy = counter;
86  auto last = std::unique(copy.begin(), copy.end());
87  size_t factor = 1;
88  size_t N = counter.size();
89  for (auto el = copy.begin(); el != last; ++el) {
90  size_t m = std::count(counter.begin(), counter.end(), *el);
91  factor *= combinatorial(N, m);
92  N -= m;
93  }
94 
95  return factor;
96  }
97 
98  operator bool() const
99  {
100  for (const auto& value : counter)
101  if (value != 0)
102  return true;
103  return false;
104  }
105 
106  friend
107  std::ostream& operator<<(std::ostream& out, symmetricCounter<T> const& c)
108  {
109  out << c.factor();
110  out << ": ";
111  for (const auto& value : c)
112  out << value << symmetricCounter<T>::separator;
113  return out;
114  }
115 
116 
117  protected:
118 
119  bool increment(size_t pos)
120  {
121  ++counter[pos];
122  if (counter[pos] == max) {
123  counter[pos] = 0;
124  if (++pos != counter.size())
125  increment(pos);
126  return true;
127  }
128  return false;
129  }
130 
131  void adjust()
132  {
133  if (counter.size() < 2)
134  return;
135  T min = counter.back();
136  for (auto iter = counter.rbegin()+1; iter != counter.rend(); ++iter) {
137  if (*iter < min)
138  *iter = min;
139  else if (*iter > min)
140  min = *iter;
141  }
142  }
143 
144  private:
145 
146  size_t max;
147 
148  std::vector<T> counter;
149 };
150 
151 #endif
Definition: symmetricCounter.h:32
Definition: counter.h:32