WaveBlocksND
tiny_multi_index.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <iostream>
4 #include <array>
5 #include <cassert>
6 #include <stdexcept>
7 #include <string>
8 #include <initializer_list>
9 #include <limits>
10 
11 #include "../../types.hpp"
12 
13 
14 namespace waveblocks {
15  namespace wavepackets {
16  namespace shapes {
46  template<class UINT, dim_t D>
48  {
49  friend struct std::less<waveblocks::wavepackets::shapes::TinyMultiIndex<UINT,D> >;
50  friend struct std::hash<waveblocks::wavepackets::shapes::TinyMultiIndex<UINT,D> >;
51  friend struct std::equal_to<waveblocks::wavepackets::shapes::TinyMultiIndex<UINT,D> >;
52 
53  private:
54 
58  static int limit(dim_t axis)
59  {
60  (void) axis; //supress -Wunused-parameter
61 
62  UINT l = (UINT(1)<<BITS_PER_ENTRY)-1;
63  if (l > std::numeric_limits<int>::max())
64  return std::numeric_limits<int>::max();
65  else
66  return (int)l;
67  }
68 
69  public:
70  UINT values_ = 0;
71 
72  const static std::size_t BITS_PER_ENTRY = (8*sizeof(UINT))/D;
73 
74  class Entry
75  {
76  private:
77  UINT &values_;
78 
79  //care: real index is [index_ - (D-1)]
80  std::size_t index_;
81 
82  inline UINT offset() const
83  {
84  return BITS_PER_ENTRY*index_;
85  }
86 
87  inline UINT mask() const
88  {
89  return (UINT(1)<<BITS_PER_ENTRY)-1;
90  }
91 
92  inline int get() const
93  {
94  return (values_ >> offset()) & mask();
95  }
96 
97  inline void set(int value)
98  {
99  assert (value >= 0 && UINT(value) <= mask());
100 
101  values_ &= ~(mask() << offset());
102  values_ |= (UINT(value) & mask()) << offset();
103  }
104 
105  public:
106  Entry(UINT &values, std::size_t index) : values_(values), index_(index) {}
107 
108  Entry &operator=(int value)
109  {
110  set(value);
111  return *this;
112  }
113 
114  Entry &operator=(const Entry &entry)
115  {
116  set(entry.get());
117  return *this;
118  }
119 
120  Entry &operator+=(int value)
121  {
122  value = get() + value;
123  set(value);
124  return *this;
125  }
126 
127  Entry &operator-=(int value)
128  {
129  value = get() - value;
130  set(value);
131  return *this;
132  }
133 
134  Entry &operator*=(int value)
135  {
136  value = get() * value;
137  set(value);
138  return *this;
139  }
140 
141  Entry &operator/=(int value)
142  {
143  value = get() / value;
144  set(value);
145  return *this;
146  }
147 
148  Entry &operator%=(int value)
149  {
150  value = get() % value;
151  set(value);
152  return *this;
153  }
154 
155  operator int() const
156  {
157  return get();
158  }
159  };
160 
162  : values_(0)
163  { }
164 
166  : values_(that.values_)
167  { }
168 
169  TinyMultiIndex(const std::array<int,D> &that)
170  {
171  for (dim_t d = 0; d < D; d++)
172  operator[](d) = that[d];
173  }
174 
175  TinyMultiIndex(std::initializer_list<int> list)
176  {
177  dim_t axis = 0;
178  for (typename std::initializer_list<int>::iterator it = list.begin(); it != list.end() && axis < D; it++) {
179  if (*it > limit(axis))
180  throw std::range_error("this multi-index implementation is unable to store a larger value than " + std::to_string(limit(axis)));
181 
182  operator[](axis++) = *it;
183  }
184  }
185 
187  {
188  values_ = that.values_;
189 
190  return *this;
191  }
192 
193  int operator[](dim_t index) const
194  {
195  return (values_ >> BITS_PER_ENTRY*((D-1)-index)) & ( (UINT(1)<<BITS_PER_ENTRY)-1 );
196  }
197 
199  {
200  return Entry(values_, (D-1)-index);
201  }
202 
203  bool operator==(const TinyMultiIndex &that) const
204  {
205  return values_ == that.values_;
206  }
207 
208  bool operator!=(const TinyMultiIndex &that) const
209  {
210  return values_ != that.values_;
211  }
212 
213  operator std::array<int,D>() const
214  {
215  std::array<int,D> copy;
216  for (dim_t d = 0; d < D; d++) {
217  copy[d] = operator[](d);
218  }
219  return copy;
220  }
221  };
222 
223  template<class UINT, dim_t D>
224  std::ostream &operator<<(std::ostream &out, const TinyMultiIndex<UINT, D> &index)
225  {
226  std::cout << "(";
227  for (dim_t i = 0; i < D-1; i++)
228  std::cout << index[i] << ", ";
229  if (D != 0)
230  std::cout << index[D-1];
231  std::cout << ")";
232  return out;
233  }
234  }
235  }
236 }
237 
238 
239 namespace std {
246  template<class UINT, waveblocks::dim_t D>
247  struct less< waveblocks::wavepackets::shapes::TinyMultiIndex<UINT,D> >
248  {
249  private:
251 
252  public:
253  typedef MultiIndex first_argument_type;
254  typedef MultiIndex second_argument_type;
255  typedef bool result_type;
256 
257  bool operator()(const MultiIndex &first, const MultiIndex &second) const
258  {
259  return first.values_ < second.values_;
260  }
261  };
262 
269  template<class UINT, waveblocks::dim_t D>
270  struct hash< waveblocks::wavepackets::shapes::TinyMultiIndex<UINT,D> >
271  {
272  private:
274 
275  public:
276  std::size_t operator()(const MultiIndex &index) const
277  {
278  return index.values_;
279  }
280  };
281 
288  template<class UINT, waveblocks::dim_t D>
289  struct equal_to< waveblocks::wavepackets::shapes::TinyMultiIndex<UINT,D> >
290  {
291  private:
293 
294  public:
295  typedef MultiIndex first_argument_type;
296  typedef MultiIndex second_argument_type;
297  typedef bool result_type;
298 
299  bool operator()(const MultiIndex &first, const MultiIndex &second) const
300  {
301  return first.values_ == second.values_;
302  }
303  };
304 }
Definition: tiny_multi_index.hpp:74
std::string to_string(T in)
Definition: to_string.hpp:10
Definition: coefficients_file_parser.cpp:10
TinyMultiIndex()
Definition: tiny_multi_index.hpp:161
int get() const
Definition: tiny_multi_index.hpp:92
static const std::size_t BITS_PER_ENTRY
Definition: tiny_multi_index.hpp:72
bool operator()(const MultiIndex &first, const MultiIndex &second) const
Definition: tiny_multi_index.hpp:299
Entry & operator+=(int value)
Definition: tiny_multi_index.hpp:120
waveblocks::wavepackets::shapes::TinyMultiIndex< UINT, D > MultiIndex
Definition: tiny_multi_index.hpp:250
MultiIndex second_argument_type
Definition: tiny_multi_index.hpp:254
UINT mask() const
Definition: tiny_multi_index.hpp:87
Definition: stdarray2stream.hpp:7
bool operator!=(const TinyMultiIndex &that) const
Definition: tiny_multi_index.hpp:208
UINT & values_
Definition: tiny_multi_index.hpp:77
Entry operator[](dim_t index)
Definition: tiny_multi_index.hpp:198
waveblocks::wavepackets::shapes::TinyMultiIndex< UINT, D > MultiIndex
Definition: tiny_multi_index.hpp:273
UINT offset() const
Definition: tiny_multi_index.hpp:82
bool operator()(const MultiIndex &first, const MultiIndex &second) const
Definition: tiny_multi_index.hpp:257
std::size_t index_
Definition: tiny_multi_index.hpp:80
TinyMultiIndex(const TinyMultiIndex &that)
Definition: tiny_multi_index.hpp:165
Entry & operator/=(int value)
Definition: tiny_multi_index.hpp:141
TinyMultiIndex(const std::array< int, D > &that)
Definition: tiny_multi_index.hpp:169
Entry & operator=(int value)
Definition: tiny_multi_index.hpp:108
Entry(UINT &values, std::size_t index)
Definition: tiny_multi_index.hpp:106
MultiIndex second_argument_type
Definition: tiny_multi_index.hpp:296
Entry & operator*=(int value)
Definition: tiny_multi_index.hpp:134
TinyMultiIndex(std::initializer_list< int > list)
Definition: tiny_multi_index.hpp:175
bool operator==(const TinyMultiIndex &that) const
Definition: tiny_multi_index.hpp:203
Entry & operator%=(int value)
Definition: tiny_multi_index.hpp:148
MultiIndex first_argument_type
Definition: tiny_multi_index.hpp:295
Entry & operator-=(int value)
Definition: tiny_multi_index.hpp:127
TinyMultiIndex & operator=(const TinyMultiIndex &that)
Definition: tiny_multi_index.hpp:186
MultiIndex first_argument_type
Definition: tiny_multi_index.hpp:253
static int limit(dim_t axis)
Definition: tiny_multi_index.hpp:58
std::size_t operator()(const MultiIndex &index) const
Definition: tiny_multi_index.hpp:276
Entry & operator=(const Entry &entry)
Definition: tiny_multi_index.hpp:114
int operator[](dim_t index) const
Definition: tiny_multi_index.hpp:193
int dim_t
Definition: types.hpp:16
Represents a multi-index using a single integer.
Definition: tiny_multi_index.hpp:47
waveblocks::wavepackets::shapes::TinyMultiIndex< UINT, D > MultiIndex
Definition: tiny_multi_index.hpp:292
UINT values_
Definition: tiny_multi_index.hpp:70