youtokentome 0.1.0

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