Caffe2 - C++ API
A deep learning, cross platform ML framework
flat_hash_map.h
1 // Taken from https://github.com/skarupke/flat_hash_map/blob/2c4687431f978f02a3780e24b8b701d22aa32d9c/flat_hash_map.hpp
2 // with fixes applied:
3 // - https://github.com/skarupke/flat_hash_map/pull/25
4 // - https://github.com/skarupke/flat_hash_map/pull/26
5 // - replace size_t with uint64_t to fix it for 32bit
6 // - add "GCC diagnostic" pragma to ignore -Wshadow
7 // - make sherwood_v3_table::convertible_to_iterator public because GCC5 seems to have issues with it otherwise
8 // - fix compiler warnings in operator templated_iterator<const value_type>
9 
10 // Copyright Malte Skarupke 2017.
11 // Distributed under the Boost Software License, Version 1.0.
12 // (See http://www.boost.org/LICENSE_1_0.txt)
13 
14 #pragma once
15 
16 #include <cstdint>
17 #include <cstddef>
18 #include <functional>
19 #include <cmath>
20 #include <algorithm>
21 #include <iterator>
22 #include <utility>
23 #include <type_traits>
24 
25 #ifndef _MSC_VER
26 #pragma GCC diagnostic push
27 #pragma GCC diagnostic ignored "-Wshadow"
28 #endif
29 
30 #ifdef _MSC_VER
31 #define SKA_NOINLINE(...) __declspec(noinline) __VA_ARGS__
32 #else
33 #define SKA_NOINLINE(...) __VA_ARGS__ __attribute__((noinline))
34 #endif
35 
36 namespace ska
37 {
38 struct prime_number_hash_policy;
39 struct power_of_two_hash_policy;
40 struct fibonacci_hash_policy;
41 
42 namespace detailv3
43 {
44 template<typename Result, typename Functor>
45 struct functor_storage : Functor
46 {
47  functor_storage() = default;
48  functor_storage(const Functor & functor)
49  : Functor(functor)
50  {
51  }
52  template<typename... Args>
53  Result operator()(Args &&... args)
54  {
55  return static_cast<Functor &>(*this)(std::forward<Args>(args)...);
56  }
57  template<typename... Args>
58  Result operator()(Args &&... args) const
59  {
60  return static_cast<const Functor &>(*this)(std::forward<Args>(args)...);
61  }
62 };
63 template<typename Result, typename... Args>
64 struct functor_storage<Result, Result (*)(Args...)>
65 {
66  typedef Result (*function_ptr)(Args...);
67  function_ptr function;
68  functor_storage(function_ptr function)
69  : function(function)
70  {
71  }
72  Result operator()(Args... args) const
73  {
74  return function(std::forward<Args>(args)...);
75  }
76  operator function_ptr &()
77  {
78  return function;
79  }
80  operator const function_ptr &()
81  {
82  return function;
83  }
84 };
85 template<typename key_type, typename value_type, typename hasher>
86 struct KeyOrValueHasher : functor_storage<uint64_t, hasher>
87 {
89  KeyOrValueHasher() = default;
90  KeyOrValueHasher(const hasher & hash)
91  : hasher_storage(hash)
92  {
93  }
94  uint64_t operator()(const key_type & key)
95  {
96  return static_cast<hasher_storage &>(*this)(key);
97  }
98  uint64_t operator()(const key_type & key) const
99  {
100  return static_cast<const hasher_storage &>(*this)(key);
101  }
102  uint64_t operator()(const value_type & value)
103  {
104  return static_cast<hasher_storage &>(*this)(value.first);
105  }
106  uint64_t operator()(const value_type & value) const
107  {
108  return static_cast<const hasher_storage &>(*this)(value.first);
109  }
110  template<typename F, typename S>
111  uint64_t operator()(const std::pair<F, S> & value)
112  {
113  return static_cast<hasher_storage &>(*this)(value.first);
114  }
115  template<typename F, typename S>
116  uint64_t operator()(const std::pair<F, S> & value) const
117  {
118  return static_cast<const hasher_storage &>(*this)(value.first);
119  }
120 };
121 template<typename key_type, typename value_type, typename key_equal>
122 struct KeyOrValueEquality : functor_storage<bool, key_equal>
123 {
125  KeyOrValueEquality() = default;
126  KeyOrValueEquality(const key_equal & equality)
127  : equality_storage(equality)
128  {
129  }
130  bool operator()(const key_type & lhs, const key_type & rhs)
131  {
132  return static_cast<equality_storage &>(*this)(lhs, rhs);
133  }
134  bool operator()(const key_type & lhs, const value_type & rhs)
135  {
136  return static_cast<equality_storage &>(*this)(lhs, rhs.first);
137  }
138  bool operator()(const value_type & lhs, const key_type & rhs)
139  {
140  return static_cast<equality_storage &>(*this)(lhs.first, rhs);
141  }
142  bool operator()(const value_type & lhs, const value_type & rhs)
143  {
144  return static_cast<equality_storage &>(*this)(lhs.first, rhs.first);
145  }
146  template<typename F, typename S>
147  bool operator()(const key_type & lhs, const std::pair<F, S> & rhs)
148  {
149  return static_cast<equality_storage &>(*this)(lhs, rhs.first);
150  }
151  template<typename F, typename S>
152  bool operator()(const std::pair<F, S> & lhs, const key_type & rhs)
153  {
154  return static_cast<equality_storage &>(*this)(lhs.first, rhs);
155  }
156  template<typename F, typename S>
157  bool operator()(const value_type & lhs, const std::pair<F, S> & rhs)
158  {
159  return static_cast<equality_storage &>(*this)(lhs.first, rhs.first);
160  }
161  template<typename F, typename S>
162  bool operator()(const std::pair<F, S> & lhs, const value_type & rhs)
163  {
164  return static_cast<equality_storage &>(*this)(lhs.first, rhs.first);
165  }
166  template<typename FL, typename SL, typename FR, typename SR>
167  bool operator()(const std::pair<FL, SL> & lhs, const std::pair<FR, SR> & rhs)
168  {
169  return static_cast<equality_storage &>(*this)(lhs.first, rhs.first);
170  }
171 };
172 static constexpr int8_t min_lookups = 4;
173 template<typename T>
175 {
177  {
178  }
179  sherwood_v3_entry(int8_t distance_from_desired)
180  : distance_from_desired(distance_from_desired)
181  {
182  }
184  {
185  }
186 
187  bool has_value() const
188  {
189  return distance_from_desired >= 0;
190  }
191  bool is_empty() const
192  {
193  return distance_from_desired < 0;
194  }
195  bool is_at_desired_position() const
196  {
197  return distance_from_desired <= 0;
198  }
199  template<typename... Args>
200  void emplace(int8_t distance, Args &&... args)
201  {
202  new (std::addressof(value)) T(std::forward<Args>(args)...);
203  distance_from_desired = distance;
204  }
205 
206  void destroy_value()
207  {
208  value.~T();
209  distance_from_desired = -1;
210  }
211 
212  int8_t distance_from_desired = -1;
213  static constexpr int8_t special_end_value = 0;
214  union { T value; };
215 };
216 
217 inline int8_t log2(uint64_t value)
218 {
219  static constexpr int8_t table[64] =
220  {
221  63, 0, 58, 1, 59, 47, 53, 2,
222  60, 39, 48, 27, 54, 33, 42, 3,
223  61, 51, 37, 40, 49, 18, 28, 20,
224  55, 30, 34, 11, 43, 14, 22, 4,
225  62, 57, 46, 52, 38, 26, 32, 41,
226  50, 36, 17, 19, 29, 10, 13, 21,
227  56, 45, 25, 31, 35, 16, 9, 12,
228  44, 24, 15, 8, 23, 7, 6, 5
229  };
230  value |= value >> 1;
231  value |= value >> 2;
232  value |= value >> 4;
233  value |= value >> 8;
234  value |= value >> 16;
235  value |= value >> 32;
236  return table[((value - (value >> 1)) * 0x07EDD5E59A4E28C2) >> 58];
237 }
238 
239 template<typename T, bool>
241 {
242  void operator()(T & lhs, const T & rhs)
243  {
244  lhs = rhs;
245  }
246  void operator()(T & lhs, T && rhs)
247  {
248  lhs = std::move(rhs);
249  }
250 };
251 template<typename T>
252 struct AssignIfTrue<T, false>
253 {
254  void operator()(T &, const T &)
255  {
256  }
257  void operator()(T &, T &&)
258  {
259  }
260 };
261 
262 inline uint64_t next_power_of_two(uint64_t i)
263 {
264  --i;
265  i |= i >> 1;
266  i |= i >> 2;
267  i |= i >> 4;
268  i |= i >> 8;
269  i |= i >> 16;
270  i |= i >> 32;
271  ++i;
272  return i;
273 }
274 
275 // Implementation taken from http://en.cppreference.com/w/cpp/types/void_t
276 // (it takes CWG1558 into account and also works for older compilers)
277 template<typename... Ts> struct make_void { typedef void type;};
278 template<typename... Ts> using void_t = typename make_void<Ts...>::type;
279 
280 template<typename T, typename = void>
282 {
283  typedef fibonacci_hash_policy type;
284 };
285 template<typename T>
286 struct HashPolicySelector<T, void_t<typename T::hash_policy>>
287 {
288  typedef typename T::hash_policy type;
289 };
290 
291 template<typename T, typename FindKey, typename ArgumentHash, typename Hasher, typename ArgumentEqual, typename Equal, typename ArgumentAlloc, typename EntryAlloc>
292 class sherwood_v3_table : private EntryAlloc, private Hasher, private Equal
293 {
295  using AllocatorTraits = std::allocator_traits<EntryAlloc>;
296  using EntryPointer = typename AllocatorTraits::pointer;
297 
298 public:
300 
301  using value_type = T;
302  using size_type = uint64_t;
303  using difference_type = std::ptrdiff_t;
304  using hasher = ArgumentHash;
305  using key_equal = ArgumentEqual;
306  using allocator_type = EntryAlloc;
307  using reference = value_type &;
308  using const_reference = const value_type &;
309  using pointer = value_type *;
310  using const_pointer = const value_type *;
311 
313  {
314  }
315  explicit sherwood_v3_table(size_type bucket_count, const ArgumentHash & hash = ArgumentHash(), const ArgumentEqual & equal = ArgumentEqual(), const ArgumentAlloc & alloc = ArgumentAlloc())
316  : EntryAlloc(alloc), Hasher(hash), Equal(equal)
317  {
318  rehash(bucket_count);
319  }
320  sherwood_v3_table(size_type bucket_count, const ArgumentAlloc & alloc)
321  : sherwood_v3_table(bucket_count, ArgumentHash(), ArgumentEqual(), alloc)
322  {
323  }
324  sherwood_v3_table(size_type bucket_count, const ArgumentHash & hash, const ArgumentAlloc & alloc)
325  : sherwood_v3_table(bucket_count, hash, ArgumentEqual(), alloc)
326  {
327  }
328  explicit sherwood_v3_table(const ArgumentAlloc & alloc)
329  : EntryAlloc(alloc)
330  {
331  }
332  template<typename It>
333  sherwood_v3_table(It first, It last, size_type bucket_count = 0, const ArgumentHash & hash = ArgumentHash(), const ArgumentEqual & equal = ArgumentEqual(), const ArgumentAlloc & alloc = ArgumentAlloc())
334  : sherwood_v3_table(bucket_count, hash, equal, alloc)
335  {
336  insert(first, last);
337  }
338  template<typename It>
339  sherwood_v3_table(It first, It last, size_type bucket_count, const ArgumentAlloc & alloc)
340  : sherwood_v3_table(first, last, bucket_count, ArgumentHash(), ArgumentEqual(), alloc)
341  {
342  }
343  template<typename It>
344  sherwood_v3_table(It first, It last, size_type bucket_count, const ArgumentHash & hash, const ArgumentAlloc & alloc)
345  : sherwood_v3_table(first, last, bucket_count, hash, ArgumentEqual(), alloc)
346  {
347  }
348  sherwood_v3_table(std::initializer_list<T> il, size_type bucket_count = 0, const ArgumentHash & hash = ArgumentHash(), const ArgumentEqual & equal = ArgumentEqual(), const ArgumentAlloc & alloc = ArgumentAlloc())
349  : sherwood_v3_table(bucket_count, hash, equal, alloc)
350  {
351  if (bucket_count == 0)
352  rehash(il.size());
353  insert(il.begin(), il.end());
354  }
355  sherwood_v3_table(std::initializer_list<T> il, size_type bucket_count, const ArgumentAlloc & alloc)
356  : sherwood_v3_table(il, bucket_count, ArgumentHash(), ArgumentEqual(), alloc)
357  {
358  }
359  sherwood_v3_table(std::initializer_list<T> il, size_type bucket_count, const ArgumentHash & hash, const ArgumentAlloc & alloc)
360  : sherwood_v3_table(il, bucket_count, hash, ArgumentEqual(), alloc)
361  {
362  }
363  sherwood_v3_table(const sherwood_v3_table & other)
364  : sherwood_v3_table(other, AllocatorTraits::select_on_container_copy_construction(other.get_allocator()))
365  {
366  }
367  sherwood_v3_table(const sherwood_v3_table & other, const ArgumentAlloc & alloc)
368  : EntryAlloc(alloc), Hasher(other), Equal(other), _max_load_factor(other._max_load_factor)
369  {
370  rehash_for_other_container(other);
371  try
372  {
373  insert(other.begin(), other.end());
374  }
375  catch(...)
376  {
377  clear();
378  deallocate_data(entries, num_slots_minus_one, max_lookups);
379  throw;
380  }
381  }
382  sherwood_v3_table(sherwood_v3_table && other) noexcept
383  : EntryAlloc(std::move(other)), Hasher(std::move(other)), Equal(std::move(other))
384  {
385  swap_pointers(other);
386  }
387  sherwood_v3_table(sherwood_v3_table && other, const ArgumentAlloc & alloc) noexcept
388  : EntryAlloc(alloc), Hasher(std::move(other)), Equal(std::move(other))
389  {
390  swap_pointers(other);
391  }
392  sherwood_v3_table & operator=(const sherwood_v3_table & other)
393  {
394  if (this == std::addressof(other))
395  return *this;
396 
397  clear();
398  if (AllocatorTraits::propagate_on_container_copy_assignment::value)
399  {
400  if (static_cast<EntryAlloc &>(*this) != static_cast<const EntryAlloc &>(other))
401  {
402  reset_to_empty_state();
403  }
405  }
406  _max_load_factor = other._max_load_factor;
407  static_cast<Hasher &>(*this) = other;
408  static_cast<Equal &>(*this) = other;
409  rehash_for_other_container(other);
410  insert(other.begin(), other.end());
411  return *this;
412  }
413  sherwood_v3_table & operator=(sherwood_v3_table && other) noexcept
414  {
415  if (this == std::addressof(other))
416  return *this;
417  else if (AllocatorTraits::propagate_on_container_move_assignment::value)
418  {
419  clear();
420  reset_to_empty_state();
422  swap_pointers(other);
423  }
424  else if (static_cast<EntryAlloc &>(*this) == static_cast<EntryAlloc &>(other))
425  {
426  swap_pointers(other);
427  }
428  else
429  {
430  clear();
431  _max_load_factor = other._max_load_factor;
432  rehash_for_other_container(other);
433  for (T & elem : other)
434  emplace(std::move(elem));
435  other.clear();
436  }
437  static_cast<Hasher &>(*this) = std::move(other);
438  static_cast<Equal &>(*this) = std::move(other);
439  return *this;
440  }
441  ~sherwood_v3_table()
442  {
443  clear();
444  deallocate_data(entries, num_slots_minus_one, max_lookups);
445  }
446 
447  const allocator_type & get_allocator() const
448  {
449  return static_cast<const allocator_type &>(*this);
450  }
451  const ArgumentEqual & key_eq() const
452  {
453  return static_cast<const ArgumentEqual &>(*this);
454  }
455  const ArgumentHash & hash_function() const
456  {
457  return static_cast<const ArgumentHash &>(*this);
458  }
459 
460  template<typename ValueType>
462  {
463  templated_iterator() = default;
464  templated_iterator(EntryPointer current)
465  : current(current)
466  {
467  }
468  EntryPointer current = EntryPointer();
469 
470  using iterator_category = std::forward_iterator_tag;
471  using value_type = ValueType;
472  using difference_type = ptrdiff_t;
473  using pointer = ValueType *;
474  using reference = ValueType &;
475 
476  friend bool operator==(const templated_iterator & lhs, const templated_iterator & rhs)
477  {
478  return lhs.current == rhs.current;
479  }
480  friend bool operator!=(const templated_iterator & lhs, const templated_iterator & rhs)
481  {
482  return !(lhs == rhs);
483  }
484 
485  templated_iterator & operator++()
486  {
487  do
488  {
489  ++current;
490  }
491  while(current->is_empty());
492  return *this;
493  }
494  templated_iterator operator++(int)
495  {
496  templated_iterator copy(*this);
497  ++*this;
498  return copy;
499  }
500 
501  ValueType & operator*() const
502  {
503  return current->value;
504  }
505  ValueType * operator->() const
506  {
507  return std::addressof(current->value);
508  }
509 
510  // the template automatically disables the operator when value_type is already
511  // const, because that would cause a lot of compiler warnings otherwise.
512  template<class target_type = const value_type, class = typename std::enable_if<std::is_same<target_type, const value_type>::value && !std::is_same<target_type, value_type>::value>::type>
513  operator templated_iterator<target_type>() const
514  {
515  return { current };
516  }
517  };
520 
521  iterator begin()
522  {
523  for (EntryPointer it = entries;; ++it)
524  {
525  if (it->has_value())
526  return { it };
527  }
528  }
529  const_iterator begin() const
530  {
531  for (EntryPointer it = entries;; ++it)
532  {
533  if (it->has_value())
534  return { it };
535  }
536  }
537  const_iterator cbegin() const
538  {
539  return begin();
540  }
541  iterator end()
542  {
543  return { entries + static_cast<ptrdiff_t>(num_slots_minus_one + max_lookups) };
544  }
545  const_iterator end() const
546  {
547  return { entries + static_cast<ptrdiff_t>(num_slots_minus_one + max_lookups) };
548  }
549  const_iterator cend() const
550  {
551  return end();
552  }
553 
554  iterator find(const FindKey & key)
555  {
556  uint64_t index = hash_policy.index_for_hash(hash_object(key), num_slots_minus_one);
557  EntryPointer it = entries + ptrdiff_t(index);
558  for (int8_t distance = 0; it->distance_from_desired >= distance; ++distance, ++it)
559  {
560  if (compares_equal(key, it->value))
561  return { it };
562  }
563  return end();
564  }
565  const_iterator find(const FindKey & key) const
566  {
567  return const_cast<sherwood_v3_table *>(this)->find(key);
568  }
569  uint64_t count(const FindKey & key) const
570  {
571  return find(key) == end() ? 0 : 1;
572  }
573  std::pair<iterator, iterator> equal_range(const FindKey & key)
574  {
575  iterator found = find(key);
576  if (found == end())
577  return { found, found };
578  else
579  return { found, std::next(found) };
580  }
581  std::pair<const_iterator, const_iterator> equal_range(const FindKey & key) const
582  {
583  const_iterator found = find(key);
584  if (found == end())
585  return { found, found };
586  else
587  return { found, std::next(found) };
588  }
589 
590  template<typename Key, typename... Args>
591  std::pair<iterator, bool> emplace(Key && key, Args &&... args)
592  {
593  uint64_t index = hash_policy.index_for_hash(hash_object(key), num_slots_minus_one);
594  EntryPointer current_entry = entries + ptrdiff_t(index);
595  int8_t distance_from_desired = 0;
596  for (; current_entry->distance_from_desired >= distance_from_desired; ++current_entry, ++distance_from_desired)
597  {
598  if (compares_equal(key, current_entry->value))
599  return { { current_entry }, false };
600  }
601  return emplace_new_key(distance_from_desired, current_entry, std::forward<Key>(key), std::forward<Args>(args)...);
602  }
603 
604  std::pair<iterator, bool> insert(const value_type & value)
605  {
606  return emplace(value);
607  }
608  std::pair<iterator, bool> insert(value_type && value)
609  {
610  return emplace(std::move(value));
611  }
612  template<typename... Args>
613  iterator emplace_hint(const_iterator, Args &&... args)
614  {
615  return emplace(std::forward<Args>(args)...).first;
616  }
617  iterator insert(const_iterator, const value_type & value)
618  {
619  return emplace(value).first;
620  }
621  iterator insert(const_iterator, value_type && value)
622  {
623  return emplace(std::move(value)).first;
624  }
625 
626  template<typename It>
627  void insert(It begin, It end)
628  {
629  for (; begin != end; ++begin)
630  {
631  emplace(*begin);
632  }
633  }
634  void insert(std::initializer_list<value_type> il)
635  {
636  insert(il.begin(), il.end());
637  }
638 
639  void rehash(uint64_t num_buckets)
640  {
641  num_buckets = std::max(num_buckets, static_cast<uint64_t>(std::ceil(num_elements / static_cast<double>(_max_load_factor))));
642  if (num_buckets == 0)
643  {
644  reset_to_empty_state();
645  return;
646  }
647  auto new_prime_index = hash_policy.next_size_over(num_buckets);
648  if (num_buckets == bucket_count())
649  return;
650  int8_t new_max_lookups = compute_max_lookups(num_buckets);
651  EntryPointer new_buckets(AllocatorTraits::allocate(*this, num_buckets + new_max_lookups));
652  EntryPointer special_end_item = new_buckets + static_cast<ptrdiff_t>(num_buckets + new_max_lookups - 1);
653  for (EntryPointer it = new_buckets; it != special_end_item; ++it)
654  it->distance_from_desired = -1;
655  special_end_item->distance_from_desired = Entry::special_end_value;
656  std::swap(entries, new_buckets);
657  std::swap(num_slots_minus_one, num_buckets);
658  --num_slots_minus_one;
659  hash_policy.commit(new_prime_index);
660  int8_t old_max_lookups = max_lookups;
661  max_lookups = new_max_lookups;
662  num_elements = 0;
663  for (EntryPointer it = new_buckets, end = it + static_cast<ptrdiff_t>(num_buckets + old_max_lookups); it != end; ++it)
664  {
665  if (it->has_value())
666  {
667  emplace(std::move(it->value));
668  it->destroy_value();
669  }
670  }
671  deallocate_data(new_buckets, num_buckets, old_max_lookups);
672  }
673 
674  void reserve(uint64_t num_elements)
675  {
676  uint64_t required_buckets = num_buckets_for_reserve(num_elements);
677  if (required_buckets > bucket_count())
678  rehash(required_buckets);
679  }
680 
681  // the return value is a type that can be converted to an iterator
682  // the reason for doing this is that it's not free to find the
683  // iterator pointing at the next element. if you care about the
684  // next iterator, turn the return value into an iterator
686  {
687  EntryPointer current = to_erase.current;
688  current->destroy_value();
689  --num_elements;
690  for (EntryPointer next = current + ptrdiff_t(1); !next->is_at_desired_position(); ++current, ++next)
691  {
692  current->emplace(next->distance_from_desired - 1, std::move(next->value));
693  next->destroy_value();
694  }
695  return { to_erase.current };
696  }
697 
698  iterator erase(const_iterator begin_it, const_iterator end_it)
699  {
700  if (begin_it == end_it)
701  return { begin_it.current };
702  for (EntryPointer it = begin_it.current, end = end_it.current; it != end; ++it)
703  {
704  if (it->has_value())
705  {
706  it->destroy_value();
707  --num_elements;
708  }
709  }
710  if (end_it == this->end())
711  return this->end();
712  ptrdiff_t num_to_move = std::min(static_cast<ptrdiff_t>(end_it.current->distance_from_desired), end_it.current - begin_it.current);
713  EntryPointer to_return = end_it.current - num_to_move;
714  for (EntryPointer it = end_it.current; !it->is_at_desired_position();)
715  {
716  EntryPointer target = it - num_to_move;
717  target->emplace(it->distance_from_desired - num_to_move, std::move(it->value));
718  it->destroy_value();
719  ++it;
720  num_to_move = std::min(static_cast<ptrdiff_t>(it->distance_from_desired), num_to_move);
721  }
722  return { to_return };
723  }
724 
725  uint64_t erase(const FindKey & key)
726  {
727  auto found = find(key);
728  if (found == end())
729  return 0;
730  else
731  {
732  erase(found);
733  return 1;
734  }
735  }
736 
737  void clear()
738  {
739  for (EntryPointer it = entries, end = it + static_cast<ptrdiff_t>(num_slots_minus_one + max_lookups); it != end; ++it)
740  {
741  if (it->has_value())
742  it->destroy_value();
743  }
744  num_elements = 0;
745  }
746 
747  void shrink_to_fit()
748  {
749  rehash_for_other_container(*this);
750  }
751 
752  void swap(sherwood_v3_table & other)
753  {
754  using std::swap;
755  swap_pointers(other);
756  swap(static_cast<ArgumentHash &>(*this), static_cast<ArgumentHash &>(other));
757  swap(static_cast<ArgumentEqual &>(*this), static_cast<ArgumentEqual &>(other));
758  if (AllocatorTraits::propagate_on_container_swap::value)
759  swap(static_cast<EntryAlloc &>(*this), static_cast<EntryAlloc &>(other));
760  }
761 
762  uint64_t size() const
763  {
764  return num_elements;
765  }
766  uint64_t max_size() const
767  {
768  return (AllocatorTraits::max_size(*this)) / sizeof(Entry);
769  }
770  uint64_t bucket_count() const
771  {
772  return num_slots_minus_one ? num_slots_minus_one + 1 : 0;
773  }
774  size_type max_bucket_count() const
775  {
776  return (AllocatorTraits::max_size(*this) - min_lookups) / sizeof(Entry);
777  }
778  uint64_t bucket(const FindKey & key) const
779  {
780  return hash_policy.index_for_hash(hash_object(key), num_slots_minus_one);
781  }
782  float load_factor() const
783  {
784  uint64_t buckets = bucket_count();
785  if (buckets)
786  return static_cast<float>(num_elements) / bucket_count();
787  else
788  return 0;
789  }
790  void max_load_factor(float value)
791  {
792  _max_load_factor = value;
793  }
794  float max_load_factor() const
795  {
796  return _max_load_factor;
797  }
798 
799  bool empty() const
800  {
801  return num_elements == 0;
802  }
803 
804 private:
805  EntryPointer entries = empty_default_table();
806  uint64_t num_slots_minus_one = 0;
807  typename HashPolicySelector<ArgumentHash>::type hash_policy;
808  int8_t max_lookups = detailv3::min_lookups - 1;
809  float _max_load_factor = 0.5f;
810  uint64_t num_elements = 0;
811 
812  EntryPointer empty_default_table()
813  {
814  EntryPointer result = AllocatorTraits::allocate(*this, detailv3::min_lookups);
815  EntryPointer special_end_item = result + static_cast<ptrdiff_t>(detailv3::min_lookups - 1);
816  for (EntryPointer it = result; it != special_end_item; ++it)
817  it->distance_from_desired = -1;
818  special_end_item->distance_from_desired = Entry::special_end_value;
819  return result;
820  }
821 
822  static int8_t compute_max_lookups(uint64_t num_buckets)
823  {
824  int8_t desired = detailv3::log2(num_buckets);
825  return std::max(detailv3::min_lookups, desired);
826  }
827 
828  uint64_t num_buckets_for_reserve(uint64_t num_elements) const
829  {
830  return static_cast<uint64_t>(std::ceil(num_elements / std::min(0.5, static_cast<double>(_max_load_factor))));
831  }
832  void rehash_for_other_container(const sherwood_v3_table & other)
833  {
834  rehash(std::min(num_buckets_for_reserve(other.size()), other.bucket_count()));
835  }
836 
837  void swap_pointers(sherwood_v3_table & other)
838  {
839  using std::swap;
840  swap(hash_policy, other.hash_policy);
841  swap(entries, other.entries);
842  swap(num_slots_minus_one, other.num_slots_minus_one);
843  swap(num_elements, other.num_elements);
844  swap(max_lookups, other.max_lookups);
845  swap(_max_load_factor, other._max_load_factor);
846  }
847 
848  template<typename Key, typename... Args>
849  SKA_NOINLINE(std::pair<iterator, bool>) emplace_new_key(int8_t distance_from_desired, EntryPointer current_entry, Key && key, Args &&... args)
850  {
851  using std::swap;
852  if (num_slots_minus_one == 0 || distance_from_desired == max_lookups || num_elements + 1 > (num_slots_minus_one + 1) * static_cast<double>(_max_load_factor))
853  {
854  grow();
855  return emplace(std::forward<Key>(key), std::forward<Args>(args)...);
856  }
857  else if (current_entry->is_empty())
858  {
859  current_entry->emplace(distance_from_desired, std::forward<Key>(key), std::forward<Args>(args)...);
860  ++num_elements;
861  return { { current_entry }, true };
862  }
863  value_type to_insert(std::forward<Key>(key), std::forward<Args>(args)...);
864  swap(distance_from_desired, current_entry->distance_from_desired);
865  swap(to_insert, current_entry->value);
866  iterator result = { current_entry };
867  for (++distance_from_desired, ++current_entry;; ++current_entry)
868  {
869  if (current_entry->is_empty())
870  {
871  current_entry->emplace(distance_from_desired, std::move(to_insert));
872  ++num_elements;
873  return { result, true };
874  }
875  else if (current_entry->distance_from_desired < distance_from_desired)
876  {
877  swap(distance_from_desired, current_entry->distance_from_desired);
878  swap(to_insert, current_entry->value);
879  ++distance_from_desired;
880  }
881  else
882  {
883  ++distance_from_desired;
884  if (distance_from_desired == max_lookups)
885  {
886  swap(to_insert, result.current->value);
887  grow();
888  return emplace(std::move(to_insert));
889  }
890  }
891  }
892  }
893 
894  void grow()
895  {
896  rehash(std::max(uint64_t(4), 2 * bucket_count()));
897  }
898 
899  void deallocate_data(EntryPointer begin, uint64_t num_slots_minus_one, int8_t max_lookups)
900  {
901  AllocatorTraits::deallocate(*this, begin, num_slots_minus_one + max_lookups + 1);
902  }
903 
904  void reset_to_empty_state()
905  {
906  deallocate_data(entries, num_slots_minus_one, max_lookups);
907  entries = empty_default_table();
908  num_slots_minus_one = 0;
909  hash_policy.reset();
910  max_lookups = detailv3::min_lookups - 1;
911  }
912 
913  template<typename U>
914  uint64_t hash_object(const U & key)
915  {
916  return static_cast<Hasher &>(*this)(key);
917  }
918  template<typename U>
919  uint64_t hash_object(const U & key) const
920  {
921  return static_cast<const Hasher &>(*this)(key);
922  }
923  template<typename L, typename R>
924  bool compares_equal(const L & lhs, const R & rhs)
925  {
926  return static_cast<Equal &>(*this)(lhs, rhs);
927  }
928 
929 public:
931  {
932  EntryPointer it;
933 
934  operator iterator()
935  {
936  if (it->has_value())
937  return { it };
938  else
939  return ++iterator{it};
940  }
941  operator const_iterator()
942  {
943  if (it->has_value())
944  return { it };
945  else
946  return ++const_iterator{it};
947  }
948  };
949 
950 };
951 }
952 
954 {
955  static uint64_t mod0(uint64_t) { return 0llu; }
956  static uint64_t mod2(uint64_t hash) { return hash % 2llu; }
957  static uint64_t mod3(uint64_t hash) { return hash % 3llu; }
958  static uint64_t mod5(uint64_t hash) { return hash % 5llu; }
959  static uint64_t mod7(uint64_t hash) { return hash % 7llu; }
960  static uint64_t mod11(uint64_t hash) { return hash % 11llu; }
961  static uint64_t mod13(uint64_t hash) { return hash % 13llu; }
962  static uint64_t mod17(uint64_t hash) { return hash % 17llu; }
963  static uint64_t mod23(uint64_t hash) { return hash % 23llu; }
964  static uint64_t mod29(uint64_t hash) { return hash % 29llu; }
965  static uint64_t mod37(uint64_t hash) { return hash % 37llu; }
966  static uint64_t mod47(uint64_t hash) { return hash % 47llu; }
967  static uint64_t mod59(uint64_t hash) { return hash % 59llu; }
968  static uint64_t mod73(uint64_t hash) { return hash % 73llu; }
969  static uint64_t mod97(uint64_t hash) { return hash % 97llu; }
970  static uint64_t mod127(uint64_t hash) { return hash % 127llu; }
971  static uint64_t mod151(uint64_t hash) { return hash % 151llu; }
972  static uint64_t mod197(uint64_t hash) { return hash % 197llu; }
973  static uint64_t mod251(uint64_t hash) { return hash % 251llu; }
974  static uint64_t mod313(uint64_t hash) { return hash % 313llu; }
975  static uint64_t mod397(uint64_t hash) { return hash % 397llu; }
976  static uint64_t mod499(uint64_t hash) { return hash % 499llu; }
977  static uint64_t mod631(uint64_t hash) { return hash % 631llu; }
978  static uint64_t mod797(uint64_t hash) { return hash % 797llu; }
979  static uint64_t mod1009(uint64_t hash) { return hash % 1009llu; }
980  static uint64_t mod1259(uint64_t hash) { return hash % 1259llu; }
981  static uint64_t mod1597(uint64_t hash) { return hash % 1597llu; }
982  static uint64_t mod2011(uint64_t hash) { return hash % 2011llu; }
983  static uint64_t mod2539(uint64_t hash) { return hash % 2539llu; }
984  static uint64_t mod3203(uint64_t hash) { return hash % 3203llu; }
985  static uint64_t mod4027(uint64_t hash) { return hash % 4027llu; }
986  static uint64_t mod5087(uint64_t hash) { return hash % 5087llu; }
987  static uint64_t mod6421(uint64_t hash) { return hash % 6421llu; }
988  static uint64_t mod8089(uint64_t hash) { return hash % 8089llu; }
989  static uint64_t mod10193(uint64_t hash) { return hash % 10193llu; }
990  static uint64_t mod12853(uint64_t hash) { return hash % 12853llu; }
991  static uint64_t mod16193(uint64_t hash) { return hash % 16193llu; }
992  static uint64_t mod20399(uint64_t hash) { return hash % 20399llu; }
993  static uint64_t mod25717(uint64_t hash) { return hash % 25717llu; }
994  static uint64_t mod32401(uint64_t hash) { return hash % 32401llu; }
995  static uint64_t mod40823(uint64_t hash) { return hash % 40823llu; }
996  static uint64_t mod51437(uint64_t hash) { return hash % 51437llu; }
997  static uint64_t mod64811(uint64_t hash) { return hash % 64811llu; }
998  static uint64_t mod81649(uint64_t hash) { return hash % 81649llu; }
999  static uint64_t mod102877(uint64_t hash) { return hash % 102877llu; }
1000  static uint64_t mod129607(uint64_t hash) { return hash % 129607llu; }
1001  static uint64_t mod163307(uint64_t hash) { return hash % 163307llu; }
1002  static uint64_t mod205759(uint64_t hash) { return hash % 205759llu; }
1003  static uint64_t mod259229(uint64_t hash) { return hash % 259229llu; }
1004  static uint64_t mod326617(uint64_t hash) { return hash % 326617llu; }
1005  static uint64_t mod411527(uint64_t hash) { return hash % 411527llu; }
1006  static uint64_t mod518509(uint64_t hash) { return hash % 518509llu; }
1007  static uint64_t mod653267(uint64_t hash) { return hash % 653267llu; }
1008  static uint64_t mod823117(uint64_t hash) { return hash % 823117llu; }
1009  static uint64_t mod1037059(uint64_t hash) { return hash % 1037059llu; }
1010  static uint64_t mod1306601(uint64_t hash) { return hash % 1306601llu; }
1011  static uint64_t mod1646237(uint64_t hash) { return hash % 1646237llu; }
1012  static uint64_t mod2074129(uint64_t hash) { return hash % 2074129llu; }
1013  static uint64_t mod2613229(uint64_t hash) { return hash % 2613229llu; }
1014  static uint64_t mod3292489(uint64_t hash) { return hash % 3292489llu; }
1015  static uint64_t mod4148279(uint64_t hash) { return hash % 4148279llu; }
1016  static uint64_t mod5226491(uint64_t hash) { return hash % 5226491llu; }
1017  static uint64_t mod6584983(uint64_t hash) { return hash % 6584983llu; }
1018  static uint64_t mod8296553(uint64_t hash) { return hash % 8296553llu; }
1019  static uint64_t mod10453007(uint64_t hash) { return hash % 10453007llu; }
1020  static uint64_t mod13169977(uint64_t hash) { return hash % 13169977llu; }
1021  static uint64_t mod16593127(uint64_t hash) { return hash % 16593127llu; }
1022  static uint64_t mod20906033(uint64_t hash) { return hash % 20906033llu; }
1023  static uint64_t mod26339969(uint64_t hash) { return hash % 26339969llu; }
1024  static uint64_t mod33186281(uint64_t hash) { return hash % 33186281llu; }
1025  static uint64_t mod41812097(uint64_t hash) { return hash % 41812097llu; }
1026  static uint64_t mod52679969(uint64_t hash) { return hash % 52679969llu; }
1027  static uint64_t mod66372617(uint64_t hash) { return hash % 66372617llu; }
1028  static uint64_t mod83624237(uint64_t hash) { return hash % 83624237llu; }
1029  static uint64_t mod105359939(uint64_t hash) { return hash % 105359939llu; }
1030  static uint64_t mod132745199(uint64_t hash) { return hash % 132745199llu; }
1031  static uint64_t mod167248483(uint64_t hash) { return hash % 167248483llu; }
1032  static uint64_t mod210719881(uint64_t hash) { return hash % 210719881llu; }
1033  static uint64_t mod265490441(uint64_t hash) { return hash % 265490441llu; }
1034  static uint64_t mod334496971(uint64_t hash) { return hash % 334496971llu; }
1035  static uint64_t mod421439783(uint64_t hash) { return hash % 421439783llu; }
1036  static uint64_t mod530980861(uint64_t hash) { return hash % 530980861llu; }
1037  static uint64_t mod668993977(uint64_t hash) { return hash % 668993977llu; }
1038  static uint64_t mod842879579(uint64_t hash) { return hash % 842879579llu; }
1039  static uint64_t mod1061961721(uint64_t hash) { return hash % 1061961721llu; }
1040  static uint64_t mod1337987929(uint64_t hash) { return hash % 1337987929llu; }
1041  static uint64_t mod1685759167(uint64_t hash) { return hash % 1685759167llu; }
1042  static uint64_t mod2123923447(uint64_t hash) { return hash % 2123923447llu; }
1043  static uint64_t mod2675975881(uint64_t hash) { return hash % 2675975881llu; }
1044  static uint64_t mod3371518343(uint64_t hash) { return hash % 3371518343llu; }
1045  static uint64_t mod4247846927(uint64_t hash) { return hash % 4247846927llu; }
1046  static uint64_t mod5351951779(uint64_t hash) { return hash % 5351951779llu; }
1047  static uint64_t mod6743036717(uint64_t hash) { return hash % 6743036717llu; }
1048  static uint64_t mod8495693897(uint64_t hash) { return hash % 8495693897llu; }
1049  static uint64_t mod10703903591(uint64_t hash) { return hash % 10703903591llu; }
1050  static uint64_t mod13486073473(uint64_t hash) { return hash % 13486073473llu; }
1051  static uint64_t mod16991387857(uint64_t hash) { return hash % 16991387857llu; }
1052  static uint64_t mod21407807219(uint64_t hash) { return hash % 21407807219llu; }
1053  static uint64_t mod26972146961(uint64_t hash) { return hash % 26972146961llu; }
1054  static uint64_t mod33982775741(uint64_t hash) { return hash % 33982775741llu; }
1055  static uint64_t mod42815614441(uint64_t hash) { return hash % 42815614441llu; }
1056  static uint64_t mod53944293929(uint64_t hash) { return hash % 53944293929llu; }
1057  static uint64_t mod67965551447(uint64_t hash) { return hash % 67965551447llu; }
1058  static uint64_t mod85631228929(uint64_t hash) { return hash % 85631228929llu; }
1059  static uint64_t mod107888587883(uint64_t hash) { return hash % 107888587883llu; }
1060  static uint64_t mod135931102921(uint64_t hash) { return hash % 135931102921llu; }
1061  static uint64_t mod171262457903(uint64_t hash) { return hash % 171262457903llu; }
1062  static uint64_t mod215777175787(uint64_t hash) { return hash % 215777175787llu; }
1063  static uint64_t mod271862205833(uint64_t hash) { return hash % 271862205833llu; }
1064  static uint64_t mod342524915839(uint64_t hash) { return hash % 342524915839llu; }
1065  static uint64_t mod431554351609(uint64_t hash) { return hash % 431554351609llu; }
1066  static uint64_t mod543724411781(uint64_t hash) { return hash % 543724411781llu; }
1067  static uint64_t mod685049831731(uint64_t hash) { return hash % 685049831731llu; }
1068  static uint64_t mod863108703229(uint64_t hash) { return hash % 863108703229llu; }
1069  static uint64_t mod1087448823553(uint64_t hash) { return hash % 1087448823553llu; }
1070  static uint64_t mod1370099663459(uint64_t hash) { return hash % 1370099663459llu; }
1071  static uint64_t mod1726217406467(uint64_t hash) { return hash % 1726217406467llu; }
1072  static uint64_t mod2174897647073(uint64_t hash) { return hash % 2174897647073llu; }
1073  static uint64_t mod2740199326961(uint64_t hash) { return hash % 2740199326961llu; }
1074  static uint64_t mod3452434812973(uint64_t hash) { return hash % 3452434812973llu; }
1075  static uint64_t mod4349795294267(uint64_t hash) { return hash % 4349795294267llu; }
1076  static uint64_t mod5480398654009(uint64_t hash) { return hash % 5480398654009llu; }
1077  static uint64_t mod6904869625999(uint64_t hash) { return hash % 6904869625999llu; }
1078  static uint64_t mod8699590588571(uint64_t hash) { return hash % 8699590588571llu; }
1079  static uint64_t mod10960797308051(uint64_t hash) { return hash % 10960797308051llu; }
1080  static uint64_t mod13809739252051(uint64_t hash) { return hash % 13809739252051llu; }
1081  static uint64_t mod17399181177241(uint64_t hash) { return hash % 17399181177241llu; }
1082  static uint64_t mod21921594616111(uint64_t hash) { return hash % 21921594616111llu; }
1083  static uint64_t mod27619478504183(uint64_t hash) { return hash % 27619478504183llu; }
1084  static uint64_t mod34798362354533(uint64_t hash) { return hash % 34798362354533llu; }
1085  static uint64_t mod43843189232363(uint64_t hash) { return hash % 43843189232363llu; }
1086  static uint64_t mod55238957008387(uint64_t hash) { return hash % 55238957008387llu; }
1087  static uint64_t mod69596724709081(uint64_t hash) { return hash % 69596724709081llu; }
1088  static uint64_t mod87686378464759(uint64_t hash) { return hash % 87686378464759llu; }
1089  static uint64_t mod110477914016779(uint64_t hash) { return hash % 110477914016779llu; }
1090  static uint64_t mod139193449418173(uint64_t hash) { return hash % 139193449418173llu; }
1091  static uint64_t mod175372756929481(uint64_t hash) { return hash % 175372756929481llu; }
1092  static uint64_t mod220955828033581(uint64_t hash) { return hash % 220955828033581llu; }
1093  static uint64_t mod278386898836457(uint64_t hash) { return hash % 278386898836457llu; }
1094  static uint64_t mod350745513859007(uint64_t hash) { return hash % 350745513859007llu; }
1095  static uint64_t mod441911656067171(uint64_t hash) { return hash % 441911656067171llu; }
1096  static uint64_t mod556773797672909(uint64_t hash) { return hash % 556773797672909llu; }
1097  static uint64_t mod701491027718027(uint64_t hash) { return hash % 701491027718027llu; }
1098  static uint64_t mod883823312134381(uint64_t hash) { return hash % 883823312134381llu; }
1099  static uint64_t mod1113547595345903(uint64_t hash) { return hash % 1113547595345903llu; }
1100  static uint64_t mod1402982055436147(uint64_t hash) { return hash % 1402982055436147llu; }
1101  static uint64_t mod1767646624268779(uint64_t hash) { return hash % 1767646624268779llu; }
1102  static uint64_t mod2227095190691797(uint64_t hash) { return hash % 2227095190691797llu; }
1103  static uint64_t mod2805964110872297(uint64_t hash) { return hash % 2805964110872297llu; }
1104  static uint64_t mod3535293248537579(uint64_t hash) { return hash % 3535293248537579llu; }
1105  static uint64_t mod4454190381383713(uint64_t hash) { return hash % 4454190381383713llu; }
1106  static uint64_t mod5611928221744609(uint64_t hash) { return hash % 5611928221744609llu; }
1107  static uint64_t mod7070586497075177(uint64_t hash) { return hash % 7070586497075177llu; }
1108  static uint64_t mod8908380762767489(uint64_t hash) { return hash % 8908380762767489llu; }
1109  static uint64_t mod11223856443489329(uint64_t hash) { return hash % 11223856443489329llu; }
1110  static uint64_t mod14141172994150357(uint64_t hash) { return hash % 14141172994150357llu; }
1111  static uint64_t mod17816761525534927(uint64_t hash) { return hash % 17816761525534927llu; }
1112  static uint64_t mod22447712886978529(uint64_t hash) { return hash % 22447712886978529llu; }
1113  static uint64_t mod28282345988300791(uint64_t hash) { return hash % 28282345988300791llu; }
1114  static uint64_t mod35633523051069991(uint64_t hash) { return hash % 35633523051069991llu; }
1115  static uint64_t mod44895425773957261(uint64_t hash) { return hash % 44895425773957261llu; }
1116  static uint64_t mod56564691976601587(uint64_t hash) { return hash % 56564691976601587llu; }
1117  static uint64_t mod71267046102139967(uint64_t hash) { return hash % 71267046102139967llu; }
1118  static uint64_t mod89790851547914507(uint64_t hash) { return hash % 89790851547914507llu; }
1119  static uint64_t mod113129383953203213(uint64_t hash) { return hash % 113129383953203213llu; }
1120  static uint64_t mod142534092204280003(uint64_t hash) { return hash % 142534092204280003llu; }
1121  static uint64_t mod179581703095829107(uint64_t hash) { return hash % 179581703095829107llu; }
1122  static uint64_t mod226258767906406483(uint64_t hash) { return hash % 226258767906406483llu; }
1123  static uint64_t mod285068184408560057(uint64_t hash) { return hash % 285068184408560057llu; }
1124  static uint64_t mod359163406191658253(uint64_t hash) { return hash % 359163406191658253llu; }
1125  static uint64_t mod452517535812813007(uint64_t hash) { return hash % 452517535812813007llu; }
1126  static uint64_t mod570136368817120201(uint64_t hash) { return hash % 570136368817120201llu; }
1127  static uint64_t mod718326812383316683(uint64_t hash) { return hash % 718326812383316683llu; }
1128  static uint64_t mod905035071625626043(uint64_t hash) { return hash % 905035071625626043llu; }
1129  static uint64_t mod1140272737634240411(uint64_t hash) { return hash % 1140272737634240411llu; }
1130  static uint64_t mod1436653624766633509(uint64_t hash) { return hash % 1436653624766633509llu; }
1131  static uint64_t mod1810070143251252131(uint64_t hash) { return hash % 1810070143251252131llu; }
1132  static uint64_t mod2280545475268481167(uint64_t hash) { return hash % 2280545475268481167llu; }
1133  static uint64_t mod2873307249533267101(uint64_t hash) { return hash % 2873307249533267101llu; }
1134  static uint64_t mod3620140286502504283(uint64_t hash) { return hash % 3620140286502504283llu; }
1135  static uint64_t mod4561090950536962147(uint64_t hash) { return hash % 4561090950536962147llu; }
1136  static uint64_t mod5746614499066534157(uint64_t hash) { return hash % 5746614499066534157llu; }
1137  static uint64_t mod7240280573005008577(uint64_t hash) { return hash % 7240280573005008577llu; }
1138  static uint64_t mod9122181901073924329(uint64_t hash) { return hash % 9122181901073924329llu; }
1139  static uint64_t mod11493228998133068689(uint64_t hash) { return hash % 11493228998133068689llu; }
1140  static uint64_t mod14480561146010017169(uint64_t hash) { return hash % 14480561146010017169llu; }
1141  static uint64_t mod18446744073709551557(uint64_t hash) { return hash % 18446744073709551557llu; }
1142 
1143  using mod_function = uint64_t (*)(uint64_t);
1144 
1145  mod_function next_size_over(uint64_t & size) const
1146  {
1147  // prime numbers generated by the following method:
1148  // 1. start with a prime p = 2
1149  // 2. go to wolfram alpha and get p = NextPrime(2 * p)
1150  // 3. repeat 2. until you overflow 64 bits
1151  // you now have large gaps which you would hit if somebody called reserve() with an unlucky number.
1152  // 4. to fill the gaps for every prime p go to wolfram alpha and get ClosestPrime(p * 2^(1/3)) and ClosestPrime(p * 2^(2/3)) and put those in the gaps
1153  // 5. get PrevPrime(2^64) and put it at the end
1154  static constexpr const uint64_t prime_list[] =
1155  {
1156  2llu, 3llu, 5llu, 7llu, 11llu, 13llu, 17llu, 23llu, 29llu, 37llu, 47llu,
1157  59llu, 73llu, 97llu, 127llu, 151llu, 197llu, 251llu, 313llu, 397llu,
1158  499llu, 631llu, 797llu, 1009llu, 1259llu, 1597llu, 2011llu, 2539llu,
1159  3203llu, 4027llu, 5087llu, 6421llu, 8089llu, 10193llu, 12853llu, 16193llu,
1160  20399llu, 25717llu, 32401llu, 40823llu, 51437llu, 64811llu, 81649llu,
1161  102877llu, 129607llu, 163307llu, 205759llu, 259229llu, 326617llu,
1162  411527llu, 518509llu, 653267llu, 823117llu, 1037059llu, 1306601llu,
1163  1646237llu, 2074129llu, 2613229llu, 3292489llu, 4148279llu, 5226491llu,
1164  6584983llu, 8296553llu, 10453007llu, 13169977llu, 16593127llu, 20906033llu,
1165  26339969llu, 33186281llu, 41812097llu, 52679969llu, 66372617llu,
1166  83624237llu, 105359939llu, 132745199llu, 167248483llu, 210719881llu,
1167  265490441llu, 334496971llu, 421439783llu, 530980861llu, 668993977llu,
1168  842879579llu, 1061961721llu, 1337987929llu, 1685759167llu, 2123923447llu,
1169  2675975881llu, 3371518343llu, 4247846927llu, 5351951779llu, 6743036717llu,
1170  8495693897llu, 10703903591llu, 13486073473llu, 16991387857llu,
1171  21407807219llu, 26972146961llu, 33982775741llu, 42815614441llu,
1172  53944293929llu, 67965551447llu, 85631228929llu, 107888587883llu,
1173  135931102921llu, 171262457903llu, 215777175787llu, 271862205833llu,
1174  342524915839llu, 431554351609llu, 543724411781llu, 685049831731llu,
1175  863108703229llu, 1087448823553llu, 1370099663459llu, 1726217406467llu,
1176  2174897647073llu, 2740199326961llu, 3452434812973llu, 4349795294267llu,
1177  5480398654009llu, 6904869625999llu, 8699590588571llu, 10960797308051llu,
1178  13809739252051llu, 17399181177241llu, 21921594616111llu, 27619478504183llu,
1179  34798362354533llu, 43843189232363llu, 55238957008387llu, 69596724709081llu,
1180  87686378464759llu, 110477914016779llu, 139193449418173llu,
1181  175372756929481llu, 220955828033581llu, 278386898836457llu,
1182  350745513859007llu, 441911656067171llu, 556773797672909llu,
1183  701491027718027llu, 883823312134381llu, 1113547595345903llu,
1184  1402982055436147llu, 1767646624268779llu, 2227095190691797llu,
1185  2805964110872297llu, 3535293248537579llu, 4454190381383713llu,
1186  5611928221744609llu, 7070586497075177llu, 8908380762767489llu,
1187  11223856443489329llu, 14141172994150357llu, 17816761525534927llu,
1188  22447712886978529llu, 28282345988300791llu, 35633523051069991llu,
1189  44895425773957261llu, 56564691976601587llu, 71267046102139967llu,
1190  89790851547914507llu, 113129383953203213llu, 142534092204280003llu,
1191  179581703095829107llu, 226258767906406483llu, 285068184408560057llu,
1192  359163406191658253llu, 452517535812813007llu, 570136368817120201llu,
1193  718326812383316683llu, 905035071625626043llu, 1140272737634240411llu,
1194  1436653624766633509llu, 1810070143251252131llu, 2280545475268481167llu,
1195  2873307249533267101llu, 3620140286502504283llu, 4561090950536962147llu,
1196  5746614499066534157llu, 7240280573005008577llu, 9122181901073924329llu,
1197  11493228998133068689llu, 14480561146010017169llu, 18446744073709551557llu
1198  };
1199  static constexpr uint64_t (* const mod_functions[])(uint64_t) =
1200  {
1201  &mod0, &mod2, &mod3, &mod5, &mod7, &mod11, &mod13, &mod17, &mod23, &mod29, &mod37,
1202  &mod47, &mod59, &mod73, &mod97, &mod127, &mod151, &mod197, &mod251, &mod313, &mod397,
1203  &mod499, &mod631, &mod797, &mod1009, &mod1259, &mod1597, &mod2011, &mod2539, &mod3203,
1204  &mod4027, &mod5087, &mod6421, &mod8089, &mod10193, &mod12853, &mod16193, &mod20399,
1205  &mod25717, &mod32401, &mod40823, &mod51437, &mod64811, &mod81649, &mod102877,
1206  &mod129607, &mod163307, &mod205759, &mod259229, &mod326617, &mod411527, &mod518509,
1207  &mod653267, &mod823117, &mod1037059, &mod1306601, &mod1646237, &mod2074129,
1208  &mod2613229, &mod3292489, &mod4148279, &mod5226491, &mod6584983, &mod8296553,
1209  &mod10453007, &mod13169977, &mod16593127, &mod20906033, &mod26339969, &mod33186281,
1210  &mod41812097, &mod52679969, &mod66372617, &mod83624237, &mod105359939, &mod132745199,
1211  &mod167248483, &mod210719881, &mod265490441, &mod334496971, &mod421439783,
1212  &mod530980861, &mod668993977, &mod842879579, &mod1061961721, &mod1337987929,
1213  &mod1685759167, &mod2123923447, &mod2675975881, &mod3371518343, &mod4247846927,
1214  &mod5351951779, &mod6743036717, &mod8495693897, &mod10703903591, &mod13486073473,
1215  &mod16991387857, &mod21407807219, &mod26972146961, &mod33982775741, &mod42815614441,
1216  &mod53944293929, &mod67965551447, &mod85631228929, &mod107888587883, &mod135931102921,
1217  &mod171262457903, &mod215777175787, &mod271862205833, &mod342524915839,
1218  &mod431554351609, &mod543724411781, &mod685049831731, &mod863108703229,
1219  &mod1087448823553, &mod1370099663459, &mod1726217406467, &mod2174897647073,
1220  &mod2740199326961, &mod3452434812973, &mod4349795294267, &mod5480398654009,
1221  &mod6904869625999, &mod8699590588571, &mod10960797308051, &mod13809739252051,
1222  &mod17399181177241, &mod21921594616111, &mod27619478504183, &mod34798362354533,
1223  &mod43843189232363, &mod55238957008387, &mod69596724709081, &mod87686378464759,
1224  &mod110477914016779, &mod139193449418173, &mod175372756929481, &mod220955828033581,
1225  &mod278386898836457, &mod350745513859007, &mod441911656067171, &mod556773797672909,
1226  &mod701491027718027, &mod883823312134381, &mod1113547595345903, &mod1402982055436147,
1227  &mod1767646624268779, &mod2227095190691797, &mod2805964110872297, &mod3535293248537579,
1228  &mod4454190381383713, &mod5611928221744609, &mod7070586497075177, &mod8908380762767489,
1229  &mod11223856443489329, &mod14141172994150357, &mod17816761525534927,
1230  &mod22447712886978529, &mod28282345988300791, &mod35633523051069991,
1231  &mod44895425773957261, &mod56564691976601587, &mod71267046102139967,
1232  &mod89790851547914507, &mod113129383953203213, &mod142534092204280003,
1233  &mod179581703095829107, &mod226258767906406483, &mod285068184408560057,
1234  &mod359163406191658253, &mod452517535812813007, &mod570136368817120201,
1235  &mod718326812383316683, &mod905035071625626043, &mod1140272737634240411,
1236  &mod1436653624766633509, &mod1810070143251252131, &mod2280545475268481167,
1237  &mod2873307249533267101, &mod3620140286502504283, &mod4561090950536962147,
1238  &mod5746614499066534157, &mod7240280573005008577, &mod9122181901073924329,
1239  &mod11493228998133068689, &mod14480561146010017169, &mod18446744073709551557
1240  };
1241  const uint64_t * found = std::lower_bound(std::begin(prime_list), std::end(prime_list) - 1, size);
1242  size = *found;
1243  return mod_functions[1 + found - prime_list];
1244  }
1245  void commit(mod_function new_mod_function)
1246  {
1247  current_mod_function = new_mod_function;
1248  }
1249  void reset()
1250  {
1251  current_mod_function = &mod0;
1252  }
1253 
1254  uint64_t index_for_hash(uint64_t hash, uint64_t /*num_slots_minus_one*/) const
1255  {
1256  return current_mod_function(hash);
1257  }
1258  uint64_t keep_in_range(uint64_t index, uint64_t num_slots_minus_one) const
1259  {
1260  return index > num_slots_minus_one ? current_mod_function(index) : index;
1261  }
1262 
1263 private:
1264  mod_function current_mod_function = &mod0;
1265 };
1266 
1268 {
1269  uint64_t index_for_hash(uint64_t hash, uint64_t num_slots_minus_one) const
1270  {
1271  return hash & num_slots_minus_one;
1272  }
1273  uint64_t keep_in_range(uint64_t index, uint64_t num_slots_minus_one) const
1274  {
1275  return index_for_hash(index, num_slots_minus_one);
1276  }
1277  int8_t next_size_over(uint64_t & size) const
1278  {
1279  size = detailv3::next_power_of_two(size);
1280  return 0;
1281  }
1282  void commit(int8_t)
1283  {
1284  }
1285  void reset()
1286  {
1287  }
1288 
1289 };
1290 
1292 {
1293  uint64_t index_for_hash(uint64_t hash, uint64_t /*num_slots_minus_one*/) const
1294  {
1295  return (11400714819323198485ull * hash) >> shift;
1296  }
1297  uint64_t keep_in_range(uint64_t index, uint64_t num_slots_minus_one) const
1298  {
1299  return index & num_slots_minus_one;
1300  }
1301 
1302  int8_t next_size_over(uint64_t & size) const
1303  {
1304  size = std::max(uint64_t(2), detailv3::next_power_of_two(size));
1305  return 64 - detailv3::log2(size);
1306  }
1307  void commit(int8_t shift)
1308  {
1309  this->shift = shift;
1310  }
1311  void reset()
1312  {
1313  shift = 63;
1314  }
1315 
1316 private:
1317  int8_t shift = 63;
1318 };
1319 
1320 template<typename K, typename V, typename H = std::hash<K>, typename E = std::equal_to<K>, typename A = std::allocator<std::pair<K, V> > >
1323  <
1324  std::pair<K, V>,
1325  K,
1326  H,
1327  detailv3::KeyOrValueHasher<K, std::pair<K, V>, H>,
1328  E,
1329  detailv3::KeyOrValueEquality<K, std::pair<K, V>, E>,
1330  A,
1331  typename std::allocator_traits<A>::template rebind_alloc<detailv3::sherwood_v3_entry<std::pair<K, V>>>
1332  >
1333 {
1335  <
1336  std::pair<K, V>,
1337  K,
1338  H,
1340  E,
1342  A,
1343  typename std::allocator_traits<A>::template rebind_alloc<detailv3::sherwood_v3_entry<std::pair<K, V>>>
1344  >;
1345 public:
1346 
1347  using key_type = K;
1348  using mapped_type = V;
1349 
1350  using Table::Table;
1351  flat_hash_map()
1352  {
1353  }
1354 
1355  inline V & operator[](const K & key)
1356  {
1357  return emplace(key, convertible_to_value()).first->second;
1358  }
1359  inline V & operator[](K && key)
1360  {
1361  return emplace(std::move(key), convertible_to_value()).first->second;
1362  }
1363  V & at(const K & key)
1364  {
1365  auto found = this->find(key);
1366  if (found == this->end())
1367  throw std::out_of_range("Argument passed to at() was not in the map.");
1368  return found->second;
1369  }
1370  const V & at(const K & key) const
1371  {
1372  auto found = this->find(key);
1373  if (found == this->end())
1374  throw std::out_of_range("Argument passed to at() was not in the map.");
1375  return found->second;
1376  }
1377 
1378  using Table::emplace;
1379  std::pair<typename Table::iterator, bool> emplace()
1380  {
1381  return emplace(key_type(), convertible_to_value());
1382  }
1383  template<typename M>
1384  std::pair<typename Table::iterator, bool> insert_or_assign(const key_type & key, M && m)
1385  {
1386  auto emplace_result = emplace(key, std::forward<M>(m));
1387  if (!emplace_result.second)
1388  emplace_result.first->second = std::forward<M>(m);
1389  return emplace_result;
1390  }
1391  template<typename M>
1392  std::pair<typename Table::iterator, bool> insert_or_assign(key_type && key, M && m)
1393  {
1394  auto emplace_result = emplace(std::move(key), std::forward<M>(m));
1395  if (!emplace_result.second)
1396  emplace_result.first->second = std::forward<M>(m);
1397  return emplace_result;
1398  }
1399  template<typename M>
1400  typename Table::iterator insert_or_assign(typename Table::const_iterator, const key_type & key, M && m)
1401  {
1402  return insert_or_assign(key, std::forward<M>(m)).first;
1403  }
1404  template<typename M>
1405  typename Table::iterator insert_or_assign(typename Table::const_iterator, key_type && key, M && m)
1406  {
1407  return insert_or_assign(std::move(key), std::forward<M>(m)).first;
1408  }
1409 
1410  friend bool operator==(const flat_hash_map & lhs, const flat_hash_map & rhs)
1411  {
1412  if (lhs.size() != rhs.size())
1413  return false;
1414  for (const typename Table::value_type & value : lhs)
1415  {
1416  auto found = rhs.find(value.first);
1417  if (found == rhs.end())
1418  return false;
1419  else if (value.second != found->second)
1420  return false;
1421  }
1422  return true;
1423  }
1424  friend bool operator!=(const flat_hash_map & lhs, const flat_hash_map & rhs)
1425  {
1426  return !(lhs == rhs);
1427  }
1428 
1429 private:
1430  struct convertible_to_value
1431  {
1432  operator V() const
1433  {
1434  return V();
1435  }
1436  };
1437 };
1438 
1439 template<typename T, typename H = std::hash<T>, typename E = std::equal_to<T>, typename A = std::allocator<T> >
1442  <
1443  T,
1444  T,
1445  H,
1446  detailv3::functor_storage<uint64_t, H>,
1447  E,
1448  detailv3::functor_storage<bool, E>,
1449  A,
1450  typename std::allocator_traits<A>::template rebind_alloc<detailv3::sherwood_v3_entry<T>>
1451  >
1452 {
1454  <
1455  T,
1456  T,
1457  H,
1459  E,
1461  A,
1462  typename std::allocator_traits<A>::template rebind_alloc<detailv3::sherwood_v3_entry<T>>
1463  >;
1464 public:
1465 
1466  using key_type = T;
1467 
1468  using Table::Table;
1469  flat_hash_set()
1470  {
1471  }
1472 
1473  template<typename... Args>
1474  std::pair<typename Table::iterator, bool> emplace(Args &&... args)
1475  {
1476  return Table::emplace(T(std::forward<Args>(args)...));
1477  }
1478  std::pair<typename Table::iterator, bool> emplace(const key_type & arg)
1479  {
1480  return Table::emplace(arg);
1481  }
1482  std::pair<typename Table::iterator, bool> emplace(key_type & arg)
1483  {
1484  return Table::emplace(arg);
1485  }
1486  std::pair<typename Table::iterator, bool> emplace(const key_type && arg)
1487  {
1488  return Table::emplace(std::move(arg));
1489  }
1490  std::pair<typename Table::iterator, bool> emplace(key_type && arg)
1491  {
1492  return Table::emplace(std::move(arg));
1493  }
1494 
1495  friend bool operator==(const flat_hash_set & lhs, const flat_hash_set & rhs)
1496  {
1497  if (lhs.size() != rhs.size())
1498  return false;
1499  for (const T & value : lhs)
1500  {
1501  if (rhs.find(value) == rhs.end())
1502  return false;
1503  }
1504  return true;
1505  }
1506  friend bool operator!=(const flat_hash_set & lhs, const flat_hash_set & rhs)
1507  {
1508  return !(lhs == rhs);
1509  }
1510 };
1511 
1512 
1513 template<typename T>
1514 struct power_of_two_std_hash : std::hash<T>
1515 {
1517 };
1518 
1519 } // end namespace ska
1520 
1521 #ifndef _MSC_VER
1522 #pragma GCC diagnostic pop
1523 #endif
Definition: static.cpp:76
Definition: any.cpp:108
Definition: static.cpp:52
Flush-To-Zero and Denormals-Are-Zero mode.