Merge pull request #3310 from robinsonb5-PRs/master
[yosys.git] / kernel / hashlib.h
1 // This is free and unencumbered software released into the public domain.
2 //
3 // Anyone is free to copy, modify, publish, use, compile, sell, or
4 // distribute this software, either in source code form or as a compiled
5 // binary, for any purpose, commercial or non-commercial, and by any
6 // means.
7
8 // -------------------------------------------------------
9 // Written by Claire Xenia Wolf <claire@yosyshq.com> in 2014
10 // -------------------------------------------------------
11
12 #ifndef HASHLIB_H
13 #define HASHLIB_H
14
15 #include <stdexcept>
16 #include <algorithm>
17 #include <string>
18 #include <vector>
19
20 namespace hashlib {
21
22 const int hashtable_size_trigger = 2;
23 const int hashtable_size_factor = 3;
24
25 // The XOR version of DJB2
26 inline unsigned int mkhash(unsigned int a, unsigned int b) {
27 return ((a << 5) + a) ^ b;
28 }
29
30 // traditionally 5381 is used as starting value for the djb2 hash
31 const unsigned int mkhash_init = 5381;
32
33 // The ADD version of DJB2
34 // (use this version for cache locality in b)
35 inline unsigned int mkhash_add(unsigned int a, unsigned int b) {
36 return ((a << 5) + a) + b;
37 }
38
39 inline unsigned int mkhash_xorshift(unsigned int a) {
40 if (sizeof(a) == 4) {
41 a ^= a << 13;
42 a ^= a >> 17;
43 a ^= a << 5;
44 } else if (sizeof(a) == 8) {
45 a ^= a << 13;
46 a ^= a >> 7;
47 a ^= a << 17;
48 } else
49 throw std::runtime_error("mkhash_xorshift() only implemented for 32 bit and 64 bit ints");
50 return a;
51 }
52
53 template<typename T> struct hash_ops {
54 static inline bool cmp(const T &a, const T &b) {
55 return a == b;
56 }
57 static inline unsigned int hash(const T &a) {
58 return a.hash();
59 }
60 };
61
62 struct hash_int_ops {
63 template<typename T>
64 static inline bool cmp(T a, T b) {
65 return a == b;
66 }
67 };
68
69 template<> struct hash_ops<bool> : hash_int_ops
70 {
71 static inline unsigned int hash(bool a) {
72 return a ? 1 : 0;
73 }
74 };
75 template<> struct hash_ops<int32_t> : hash_int_ops
76 {
77 static inline unsigned int hash(int32_t a) {
78 return a;
79 }
80 };
81 template<> struct hash_ops<int64_t> : hash_int_ops
82 {
83 static inline unsigned int hash(int64_t a) {
84 return mkhash((unsigned int)(a), (unsigned int)(a >> 32));
85 }
86 };
87
88 template<> struct hash_ops<std::string> {
89 static inline bool cmp(const std::string &a, const std::string &b) {
90 return a == b;
91 }
92 static inline unsigned int hash(const std::string &a) {
93 unsigned int v = 0;
94 for (auto c : a)
95 v = mkhash(v, c);
96 return v;
97 }
98 };
99
100 template<typename P, typename Q> struct hash_ops<std::pair<P, Q>> {
101 static inline bool cmp(std::pair<P, Q> a, std::pair<P, Q> b) {
102 return a == b;
103 }
104 static inline unsigned int hash(std::pair<P, Q> a) {
105 return mkhash(hash_ops<P>::hash(a.first), hash_ops<Q>::hash(a.second));
106 }
107 };
108
109 template<typename... T> struct hash_ops<std::tuple<T...>> {
110 static inline bool cmp(std::tuple<T...> a, std::tuple<T...> b) {
111 return a == b;
112 }
113 template<size_t I = 0>
114 static inline typename std::enable_if<I == sizeof...(T), unsigned int>::type hash(std::tuple<T...>) {
115 return mkhash_init;
116 }
117 template<size_t I = 0>
118 static inline typename std::enable_if<I != sizeof...(T), unsigned int>::type hash(std::tuple<T...> a) {
119 typedef hash_ops<typename std::tuple_element<I, std::tuple<T...>>::type> element_ops_t;
120 return mkhash(hash<I+1>(a), element_ops_t::hash(std::get<I>(a)));
121 }
122 };
123
124 template<typename T> struct hash_ops<std::vector<T>> {
125 static inline bool cmp(std::vector<T> a, std::vector<T> b) {
126 return a == b;
127 }
128 static inline unsigned int hash(std::vector<T> a) {
129 unsigned int h = mkhash_init;
130 for (auto k : a)
131 h = mkhash(h, hash_ops<T>::hash(k));
132 return h;
133 }
134 };
135
136 struct hash_cstr_ops {
137 static inline bool cmp(const char *a, const char *b) {
138 for (int i = 0; a[i] || b[i]; i++)
139 if (a[i] != b[i])
140 return false;
141 return true;
142 }
143 static inline unsigned int hash(const char *a) {
144 unsigned int hash = mkhash_init;
145 while (*a)
146 hash = mkhash(hash, *(a++));
147 return hash;
148 }
149 };
150
151 struct hash_ptr_ops {
152 static inline bool cmp(const void *a, const void *b) {
153 return a == b;
154 }
155 static inline unsigned int hash(const void *a) {
156 return (uintptr_t)a;
157 }
158 };
159
160 struct hash_obj_ops {
161 static inline bool cmp(const void *a, const void *b) {
162 return a == b;
163 }
164 template<typename T>
165 static inline unsigned int hash(const T *a) {
166 return a ? a->hash() : 0;
167 }
168 };
169
170 template<typename T>
171 inline unsigned int mkhash(const T &v) {
172 return hash_ops<T>().hash(v);
173 }
174
175 inline int hashtable_size(int min_size)
176 {
177 static std::vector<int> zero_and_some_primes = {
178 0, 23, 29, 37, 47, 59, 79, 101, 127, 163, 211, 269, 337, 431, 541, 677,
179 853, 1069, 1361, 1709, 2137, 2677, 3347, 4201, 5261, 6577, 8231, 10289,
180 12889, 16127, 20161, 25219, 31531, 39419, 49277, 61603, 77017, 96281,
181 120371, 150473, 188107, 235159, 293957, 367453, 459317, 574157, 717697,
182 897133, 1121423, 1401791, 1752239, 2190299, 2737937, 3422429, 4278037,
183 5347553, 6684443, 8355563, 10444457, 13055587, 16319519, 20399411,
184 25499291, 31874149, 39842687, 49803361, 62254207, 77817767, 97272239,
185 121590311, 151987889, 189984863, 237481091, 296851369, 371064217
186 };
187
188 for (auto p : zero_and_some_primes)
189 if (p >= min_size) return p;
190
191 if (sizeof(int) == 4)
192 throw std::length_error("hash table exceeded maximum size. use a ILP64 abi for larger tables.");
193
194 for (auto p : zero_and_some_primes)
195 if (100129 * p > min_size) return 100129 * p;
196
197 throw std::length_error("hash table exceeded maximum size.");
198 }
199
200 template<typename K, typename T, typename OPS = hash_ops<K>> class dict;
201 template<typename K, int offset = 0, typename OPS = hash_ops<K>> class idict;
202 template<typename K, typename OPS = hash_ops<K>> class pool;
203 template<typename K, typename OPS = hash_ops<K>> class mfp;
204
205 template<typename K, typename T, typename OPS>
206 class dict
207 {
208 struct entry_t
209 {
210 std::pair<K, T> udata;
211 int next;
212
213 entry_t() { }
214 entry_t(const std::pair<K, T> &udata, int next) : udata(udata), next(next) { }
215 entry_t(std::pair<K, T> &&udata, int next) : udata(std::move(udata)), next(next) { }
216 bool operator<(const entry_t &other) const { return udata.first < other.udata.first; }
217 };
218
219 std::vector<int> hashtable;
220 std::vector<entry_t> entries;
221 OPS ops;
222
223 #ifdef NDEBUG
224 static inline void do_assert(bool) { }
225 #else
226 static inline void do_assert(bool cond) {
227 if (!cond) throw std::runtime_error("dict<> assert failed.");
228 }
229 #endif
230
231 int do_hash(const K &key) const
232 {
233 unsigned int hash = 0;
234 if (!hashtable.empty())
235 hash = ops.hash(key) % (unsigned int)(hashtable.size());
236 return hash;
237 }
238
239 void do_rehash()
240 {
241 hashtable.clear();
242 hashtable.resize(hashtable_size(entries.capacity() * hashtable_size_factor), -1);
243
244 for (int i = 0; i < int(entries.size()); i++) {
245 do_assert(-1 <= entries[i].next && entries[i].next < int(entries.size()));
246 int hash = do_hash(entries[i].udata.first);
247 entries[i].next = hashtable[hash];
248 hashtable[hash] = i;
249 }
250 }
251
252 int do_erase(int index, int hash)
253 {
254 do_assert(index < int(entries.size()));
255 if (hashtable.empty() || index < 0)
256 return 0;
257
258 int k = hashtable[hash];
259 do_assert(0 <= k && k < int(entries.size()));
260
261 if (k == index) {
262 hashtable[hash] = entries[index].next;
263 } else {
264 while (entries[k].next != index) {
265 k = entries[k].next;
266 do_assert(0 <= k && k < int(entries.size()));
267 }
268 entries[k].next = entries[index].next;
269 }
270
271 int back_idx = entries.size()-1;
272
273 if (index != back_idx)
274 {
275 int back_hash = do_hash(entries[back_idx].udata.first);
276
277 k = hashtable[back_hash];
278 do_assert(0 <= k && k < int(entries.size()));
279
280 if (k == back_idx) {
281 hashtable[back_hash] = index;
282 } else {
283 while (entries[k].next != back_idx) {
284 k = entries[k].next;
285 do_assert(0 <= k && k < int(entries.size()));
286 }
287 entries[k].next = index;
288 }
289
290 entries[index] = std::move(entries[back_idx]);
291 }
292
293 entries.pop_back();
294
295 if (entries.empty())
296 hashtable.clear();
297
298 return 1;
299 }
300
301 int do_lookup(const K &key, int &hash) const
302 {
303 if (hashtable.empty())
304 return -1;
305
306 if (entries.size() * hashtable_size_trigger > hashtable.size()) {
307 ((dict*)this)->do_rehash();
308 hash = do_hash(key);
309 }
310
311 int index = hashtable[hash];
312
313 while (index >= 0 && !ops.cmp(entries[index].udata.first, key)) {
314 index = entries[index].next;
315 do_assert(-1 <= index && index < int(entries.size()));
316 }
317
318 return index;
319 }
320
321 int do_insert(const K &key, int &hash)
322 {
323 if (hashtable.empty()) {
324 entries.emplace_back(std::pair<K, T>(key, T()), -1);
325 do_rehash();
326 hash = do_hash(key);
327 } else {
328 entries.emplace_back(std::pair<K, T>(key, T()), hashtable[hash]);
329 hashtable[hash] = entries.size() - 1;
330 }
331 return entries.size() - 1;
332 }
333
334 int do_insert(const std::pair<K, T> &value, int &hash)
335 {
336 if (hashtable.empty()) {
337 entries.emplace_back(value, -1);
338 do_rehash();
339 hash = do_hash(value.first);
340 } else {
341 entries.emplace_back(value, hashtable[hash]);
342 hashtable[hash] = entries.size() - 1;
343 }
344 return entries.size() - 1;
345 }
346
347 int do_insert(std::pair<K, T> &&rvalue, int &hash)
348 {
349 if (hashtable.empty()) {
350 auto key = rvalue.first;
351 entries.emplace_back(std::forward<std::pair<K, T>>(rvalue), -1);
352 do_rehash();
353 hash = do_hash(key);
354 } else {
355 entries.emplace_back(std::forward<std::pair<K, T>>(rvalue), hashtable[hash]);
356 hashtable[hash] = entries.size() - 1;
357 }
358 return entries.size() - 1;
359 }
360
361 public:
362 class const_iterator : public std::iterator<std::forward_iterator_tag, std::pair<K, T>>
363 {
364 friend class dict;
365 protected:
366 const dict *ptr;
367 int index;
368 const_iterator(const dict *ptr, int index) : ptr(ptr), index(index) { }
369 public:
370 const_iterator() { }
371 const_iterator operator++() { index--; return *this; }
372 const_iterator operator+=(int amt) { index -= amt; return *this; }
373 bool operator<(const const_iterator &other) const { return index > other.index; }
374 bool operator==(const const_iterator &other) const { return index == other.index; }
375 bool operator!=(const const_iterator &other) const { return index != other.index; }
376 const std::pair<K, T> &operator*() const { return ptr->entries[index].udata; }
377 const std::pair<K, T> *operator->() const { return &ptr->entries[index].udata; }
378 };
379
380 class iterator : public std::iterator<std::forward_iterator_tag, std::pair<K, T>>
381 {
382 friend class dict;
383 protected:
384 dict *ptr;
385 int index;
386 iterator(dict *ptr, int index) : ptr(ptr), index(index) { }
387 public:
388 iterator() { }
389 iterator operator++() { index--; return *this; }
390 iterator operator+=(int amt) { index -= amt; return *this; }
391 bool operator<(const iterator &other) const { return index > other.index; }
392 bool operator==(const iterator &other) const { return index == other.index; }
393 bool operator!=(const iterator &other) const { return index != other.index; }
394 std::pair<K, T> &operator*() { return ptr->entries[index].udata; }
395 std::pair<K, T> *operator->() { return &ptr->entries[index].udata; }
396 const std::pair<K, T> &operator*() const { return ptr->entries[index].udata; }
397 const std::pair<K, T> *operator->() const { return &ptr->entries[index].udata; }
398 operator const_iterator() const { return const_iterator(ptr, index); }
399 };
400
401 dict()
402 {
403 }
404
405 dict(const dict &other)
406 {
407 entries = other.entries;
408 do_rehash();
409 }
410
411 dict(dict &&other)
412 {
413 swap(other);
414 }
415
416 dict &operator=(const dict &other) {
417 entries = other.entries;
418 do_rehash();
419 return *this;
420 }
421
422 dict &operator=(dict &&other) {
423 clear();
424 swap(other);
425 return *this;
426 }
427
428 dict(const std::initializer_list<std::pair<K, T>> &list)
429 {
430 for (auto &it : list)
431 insert(it);
432 }
433
434 template<class InputIterator>
435 dict(InputIterator first, InputIterator last)
436 {
437 insert(first, last);
438 }
439
440 template<class InputIterator>
441 void insert(InputIterator first, InputIterator last)
442 {
443 for (; first != last; ++first)
444 insert(*first);
445 }
446
447 std::pair<iterator, bool> insert(const K &key)
448 {
449 int hash = do_hash(key);
450 int i = do_lookup(key, hash);
451 if (i >= 0)
452 return std::pair<iterator, bool>(iterator(this, i), false);
453 i = do_insert(key, hash);
454 return std::pair<iterator, bool>(iterator(this, i), true);
455 }
456
457 std::pair<iterator, bool> insert(const std::pair<K, T> &value)
458 {
459 int hash = do_hash(value.first);
460 int i = do_lookup(value.first, hash);
461 if (i >= 0)
462 return std::pair<iterator, bool>(iterator(this, i), false);
463 i = do_insert(value, hash);
464 return std::pair<iterator, bool>(iterator(this, i), true);
465 }
466
467 std::pair<iterator, bool> insert(std::pair<K, T> &&rvalue)
468 {
469 int hash = do_hash(rvalue.first);
470 int i = do_lookup(rvalue.first, hash);
471 if (i >= 0)
472 return std::pair<iterator, bool>(iterator(this, i), false);
473 i = do_insert(std::forward<std::pair<K, T>>(rvalue), hash);
474 return std::pair<iterator, bool>(iterator(this, i), true);
475 }
476
477 std::pair<iterator, bool> emplace(K const &key, T const &value)
478 {
479 int hash = do_hash(key);
480 int i = do_lookup(key, hash);
481 if (i >= 0)
482 return std::pair<iterator, bool>(iterator(this, i), false);
483 i = do_insert(std::make_pair(key, value), hash);
484 return std::pair<iterator, bool>(iterator(this, i), true);
485 }
486
487 std::pair<iterator, bool> emplace(K const &key, T &&rvalue)
488 {
489 int hash = do_hash(key);
490 int i = do_lookup(key, hash);
491 if (i >= 0)
492 return std::pair<iterator, bool>(iterator(this, i), false);
493 i = do_insert(std::make_pair(key, std::forward<T>(rvalue)), hash);
494 return std::pair<iterator, bool>(iterator(this, i), true);
495 }
496
497 std::pair<iterator, bool> emplace(K &&rkey, T const &value)
498 {
499 int hash = do_hash(rkey);
500 int i = do_lookup(rkey, hash);
501 if (i >= 0)
502 return std::pair<iterator, bool>(iterator(this, i), false);
503 i = do_insert(std::make_pair(std::forward<K>(rkey), value), hash);
504 return std::pair<iterator, bool>(iterator(this, i), true);
505 }
506
507 std::pair<iterator, bool> emplace(K &&rkey, T &&rvalue)
508 {
509 int hash = do_hash(rkey);
510 int i = do_lookup(rkey, hash);
511 if (i >= 0)
512 return std::pair<iterator, bool>(iterator(this, i), false);
513 i = do_insert(std::make_pair(std::forward<K>(rkey), std::forward<T>(rvalue)), hash);
514 return std::pair<iterator, bool>(iterator(this, i), true);
515 }
516
517 int erase(const K &key)
518 {
519 int hash = do_hash(key);
520 int index = do_lookup(key, hash);
521 return do_erase(index, hash);
522 }
523
524 iterator erase(iterator it)
525 {
526 int hash = do_hash(it->first);
527 do_erase(it.index, hash);
528 return ++it;
529 }
530
531 int count(const K &key) const
532 {
533 int hash = do_hash(key);
534 int i = do_lookup(key, hash);
535 return i < 0 ? 0 : 1;
536 }
537
538 int count(const K &key, const_iterator it) const
539 {
540 int hash = do_hash(key);
541 int i = do_lookup(key, hash);
542 return i < 0 || i > it.index ? 0 : 1;
543 }
544
545 iterator find(const K &key)
546 {
547 int hash = do_hash(key);
548 int i = do_lookup(key, hash);
549 if (i < 0)
550 return end();
551 return iterator(this, i);
552 }
553
554 const_iterator find(const K &key) const
555 {
556 int hash = do_hash(key);
557 int i = do_lookup(key, hash);
558 if (i < 0)
559 return end();
560 return const_iterator(this, i);
561 }
562
563 T& at(const K &key)
564 {
565 int hash = do_hash(key);
566 int i = do_lookup(key, hash);
567 if (i < 0)
568 throw std::out_of_range("dict::at()");
569 return entries[i].udata.second;
570 }
571
572 const T& at(const K &key) const
573 {
574 int hash = do_hash(key);
575 int i = do_lookup(key, hash);
576 if (i < 0)
577 throw std::out_of_range("dict::at()");
578 return entries[i].udata.second;
579 }
580
581 const T& at(const K &key, const T &defval) const
582 {
583 int hash = do_hash(key);
584 int i = do_lookup(key, hash);
585 if (i < 0)
586 return defval;
587 return entries[i].udata.second;
588 }
589
590 T& operator[](const K &key)
591 {
592 int hash = do_hash(key);
593 int i = do_lookup(key, hash);
594 if (i < 0)
595 i = do_insert(std::pair<K, T>(key, T()), hash);
596 return entries[i].udata.second;
597 }
598
599 template<typename Compare = std::less<K>>
600 void sort(Compare comp = Compare())
601 {
602 std::sort(entries.begin(), entries.end(), [comp](const entry_t &a, const entry_t &b){ return comp(b.udata.first, a.udata.first); });
603 do_rehash();
604 }
605
606 void swap(dict &other)
607 {
608 hashtable.swap(other.hashtable);
609 entries.swap(other.entries);
610 }
611
612 bool operator==(const dict &other) const {
613 if (size() != other.size())
614 return false;
615 for (auto &it : entries) {
616 auto oit = other.find(it.udata.first);
617 if (oit == other.end() || !(oit->second == it.udata.second))
618 return false;
619 }
620 return true;
621 }
622
623 bool operator!=(const dict &other) const {
624 return !operator==(other);
625 }
626
627 unsigned int hash() const {
628 unsigned int h = mkhash_init;
629 for (auto &entry : entries) {
630 h ^= hash_ops<K>::hash(entry.udata.first);
631 h ^= hash_ops<T>::hash(entry.udata.second);
632 }
633 return h;
634 }
635
636 void reserve(size_t n) { entries.reserve(n); }
637 size_t size() const { return entries.size(); }
638 bool empty() const { return entries.empty(); }
639 void clear() { hashtable.clear(); entries.clear(); }
640
641 iterator begin() { return iterator(this, int(entries.size())-1); }
642 iterator element(int n) { return iterator(this, int(entries.size())-1-n); }
643 iterator end() { return iterator(nullptr, -1); }
644
645 const_iterator begin() const { return const_iterator(this, int(entries.size())-1); }
646 const_iterator element(int n) const { return const_iterator(this, int(entries.size())-1-n); }
647 const_iterator end() const { return const_iterator(nullptr, -1); }
648 };
649
650 template<typename K, typename OPS>
651 class pool
652 {
653 template<typename, int, typename> friend class idict;
654
655 protected:
656 struct entry_t
657 {
658 K udata;
659 int next;
660
661 entry_t() { }
662 entry_t(const K &udata, int next) : udata(udata), next(next) { }
663 entry_t(K &&udata, int next) : udata(std::move(udata)), next(next) { }
664 };
665
666 std::vector<int> hashtable;
667 std::vector<entry_t> entries;
668 OPS ops;
669
670 #ifdef NDEBUG
671 static inline void do_assert(bool) { }
672 #else
673 static inline void do_assert(bool cond) {
674 if (!cond) throw std::runtime_error("pool<> assert failed.");
675 }
676 #endif
677
678 int do_hash(const K &key) const
679 {
680 unsigned int hash = 0;
681 if (!hashtable.empty())
682 hash = ops.hash(key) % (unsigned int)(hashtable.size());
683 return hash;
684 }
685
686 void do_rehash()
687 {
688 hashtable.clear();
689 hashtable.resize(hashtable_size(entries.capacity() * hashtable_size_factor), -1);
690
691 for (int i = 0; i < int(entries.size()); i++) {
692 do_assert(-1 <= entries[i].next && entries[i].next < int(entries.size()));
693 int hash = do_hash(entries[i].udata);
694 entries[i].next = hashtable[hash];
695 hashtable[hash] = i;
696 }
697 }
698
699 int do_erase(int index, int hash)
700 {
701 do_assert(index < int(entries.size()));
702 if (hashtable.empty() || index < 0)
703 return 0;
704
705 int k = hashtable[hash];
706 if (k == index) {
707 hashtable[hash] = entries[index].next;
708 } else {
709 while (entries[k].next != index) {
710 k = entries[k].next;
711 do_assert(0 <= k && k < int(entries.size()));
712 }
713 entries[k].next = entries[index].next;
714 }
715
716 int back_idx = entries.size()-1;
717
718 if (index != back_idx)
719 {
720 int back_hash = do_hash(entries[back_idx].udata);
721
722 k = hashtable[back_hash];
723 if (k == back_idx) {
724 hashtable[back_hash] = index;
725 } else {
726 while (entries[k].next != back_idx) {
727 k = entries[k].next;
728 do_assert(0 <= k && k < int(entries.size()));
729 }
730 entries[k].next = index;
731 }
732
733 entries[index] = std::move(entries[back_idx]);
734 }
735
736 entries.pop_back();
737
738 if (entries.empty())
739 hashtable.clear();
740
741 return 1;
742 }
743
744 int do_lookup(const K &key, int &hash) const
745 {
746 if (hashtable.empty())
747 return -1;
748
749 if (entries.size() * hashtable_size_trigger > hashtable.size()) {
750 ((pool*)this)->do_rehash();
751 hash = do_hash(key);
752 }
753
754 int index = hashtable[hash];
755
756 while (index >= 0 && !ops.cmp(entries[index].udata, key)) {
757 index = entries[index].next;
758 do_assert(-1 <= index && index < int(entries.size()));
759 }
760
761 return index;
762 }
763
764 int do_insert(const K &value, int &hash)
765 {
766 if (hashtable.empty()) {
767 entries.emplace_back(value, -1);
768 do_rehash();
769 hash = do_hash(value);
770 } else {
771 entries.emplace_back(value, hashtable[hash]);
772 hashtable[hash] = entries.size() - 1;
773 }
774 return entries.size() - 1;
775 }
776
777 int do_insert(K &&rvalue, int &hash)
778 {
779 if (hashtable.empty()) {
780 entries.emplace_back(std::forward<K>(rvalue), -1);
781 do_rehash();
782 hash = do_hash(rvalue);
783 } else {
784 entries.emplace_back(std::forward<K>(rvalue), hashtable[hash]);
785 hashtable[hash] = entries.size() - 1;
786 }
787 return entries.size() - 1;
788 }
789
790 public:
791 class const_iterator : public std::iterator<std::forward_iterator_tag, K>
792 {
793 friend class pool;
794 protected:
795 const pool *ptr;
796 int index;
797 const_iterator(const pool *ptr, int index) : ptr(ptr), index(index) { }
798 public:
799 const_iterator() { }
800 const_iterator operator++() { index--; return *this; }
801 bool operator==(const const_iterator &other) const { return index == other.index; }
802 bool operator!=(const const_iterator &other) const { return index != other.index; }
803 const K &operator*() const { return ptr->entries[index].udata; }
804 const K *operator->() const { return &ptr->entries[index].udata; }
805 };
806
807 class iterator : public std::iterator<std::forward_iterator_tag, K>
808 {
809 friend class pool;
810 protected:
811 pool *ptr;
812 int index;
813 iterator(pool *ptr, int index) : ptr(ptr), index(index) { }
814 public:
815 iterator() { }
816 iterator operator++() { index--; return *this; }
817 bool operator==(const iterator &other) const { return index == other.index; }
818 bool operator!=(const iterator &other) const { return index != other.index; }
819 K &operator*() { return ptr->entries[index].udata; }
820 K *operator->() { return &ptr->entries[index].udata; }
821 const K &operator*() const { return ptr->entries[index].udata; }
822 const K *operator->() const { return &ptr->entries[index].udata; }
823 operator const_iterator() const { return const_iterator(ptr, index); }
824 };
825
826 pool()
827 {
828 }
829
830 pool(const pool &other)
831 {
832 entries = other.entries;
833 do_rehash();
834 }
835
836 pool(pool &&other)
837 {
838 swap(other);
839 }
840
841 pool &operator=(const pool &other) {
842 entries = other.entries;
843 do_rehash();
844 return *this;
845 }
846
847 pool &operator=(pool &&other) {
848 clear();
849 swap(other);
850 return *this;
851 }
852
853 pool(const std::initializer_list<K> &list)
854 {
855 for (auto &it : list)
856 insert(it);
857 }
858
859 template<class InputIterator>
860 pool(InputIterator first, InputIterator last)
861 {
862 insert(first, last);
863 }
864
865 template<class InputIterator>
866 void insert(InputIterator first, InputIterator last)
867 {
868 for (; first != last; ++first)
869 insert(*first);
870 }
871
872 std::pair<iterator, bool> insert(const K &value)
873 {
874 int hash = do_hash(value);
875 int i = do_lookup(value, hash);
876 if (i >= 0)
877 return std::pair<iterator, bool>(iterator(this, i), false);
878 i = do_insert(value, hash);
879 return std::pair<iterator, bool>(iterator(this, i), true);
880 }
881
882 std::pair<iterator, bool> insert(K &&rvalue)
883 {
884 int hash = do_hash(rvalue);
885 int i = do_lookup(rvalue, hash);
886 if (i >= 0)
887 return std::pair<iterator, bool>(iterator(this, i), false);
888 i = do_insert(std::forward<K>(rvalue), hash);
889 return std::pair<iterator, bool>(iterator(this, i), true);
890 }
891
892 template<typename... Args>
893 std::pair<iterator, bool> emplace(Args&&... args)
894 {
895 return insert(K(std::forward<Args>(args)...));
896 }
897
898 int erase(const K &key)
899 {
900 int hash = do_hash(key);
901 int index = do_lookup(key, hash);
902 return do_erase(index, hash);
903 }
904
905 iterator erase(iterator it)
906 {
907 int hash = do_hash(*it);
908 do_erase(it.index, hash);
909 return ++it;
910 }
911
912 int count(const K &key) const
913 {
914 int hash = do_hash(key);
915 int i = do_lookup(key, hash);
916 return i < 0 ? 0 : 1;
917 }
918
919 int count(const K &key, const_iterator it) const
920 {
921 int hash = do_hash(key);
922 int i = do_lookup(key, hash);
923 return i < 0 || i > it.index ? 0 : 1;
924 }
925
926 iterator find(const K &key)
927 {
928 int hash = do_hash(key);
929 int i = do_lookup(key, hash);
930 if (i < 0)
931 return end();
932 return iterator(this, i);
933 }
934
935 const_iterator find(const K &key) const
936 {
937 int hash = do_hash(key);
938 int i = do_lookup(key, hash);
939 if (i < 0)
940 return end();
941 return const_iterator(this, i);
942 }
943
944 bool operator[](const K &key)
945 {
946 int hash = do_hash(key);
947 int i = do_lookup(key, hash);
948 return i >= 0;
949 }
950
951 template<typename Compare = std::less<K>>
952 void sort(Compare comp = Compare())
953 {
954 std::sort(entries.begin(), entries.end(), [comp](const entry_t &a, const entry_t &b){ return comp(b.udata, a.udata); });
955 do_rehash();
956 }
957
958 K pop()
959 {
960 iterator it = begin();
961 K ret = *it;
962 erase(it);
963 return ret;
964 }
965
966 void swap(pool &other)
967 {
968 hashtable.swap(other.hashtable);
969 entries.swap(other.entries);
970 }
971
972 bool operator==(const pool &other) const {
973 if (size() != other.size())
974 return false;
975 for (auto &it : entries)
976 if (!other.count(it.udata))
977 return false;
978 return true;
979 }
980
981 bool operator!=(const pool &other) const {
982 return !operator==(other);
983 }
984
985 bool hash() const {
986 unsigned int hashval = mkhash_init;
987 for (auto &it : entries)
988 hashval ^= ops.hash(it.udata);
989 return hashval;
990 }
991
992 void reserve(size_t n) { entries.reserve(n); }
993 size_t size() const { return entries.size(); }
994 bool empty() const { return entries.empty(); }
995 void clear() { hashtable.clear(); entries.clear(); }
996
997 iterator begin() { return iterator(this, int(entries.size())-1); }
998 iterator element(int n) { return iterator(this, int(entries.size())-1-n); }
999 iterator end() { return iterator(nullptr, -1); }
1000
1001 const_iterator begin() const { return const_iterator(this, int(entries.size())-1); }
1002 const_iterator element(int n) const { return const_iterator(this, int(entries.size())-1-n); }
1003 const_iterator end() const { return const_iterator(nullptr, -1); }
1004 };
1005
1006 template<typename K, int offset, typename OPS>
1007 class idict
1008 {
1009 pool<K, OPS> database;
1010
1011 public:
1012 class const_iterator : public std::iterator<std::forward_iterator_tag, K>
1013 {
1014 friend class idict;
1015 protected:
1016 const idict &container;
1017 int index;
1018 const_iterator(const idict &container, int index) : container(container), index(index) { }
1019 public:
1020 const_iterator() { }
1021 const_iterator operator++() { index++; return *this; }
1022 bool operator==(const const_iterator &other) const { return index == other.index; }
1023 bool operator!=(const const_iterator &other) const { return index != other.index; }
1024 const K &operator*() const { return container[index]; }
1025 const K *operator->() const { return &container[index]; }
1026 };
1027
1028 int operator()(const K &key)
1029 {
1030 int hash = database.do_hash(key);
1031 int i = database.do_lookup(key, hash);
1032 if (i < 0)
1033 i = database.do_insert(key, hash);
1034 return i + offset;
1035 }
1036
1037 int at(const K &key) const
1038 {
1039 int hash = database.do_hash(key);
1040 int i = database.do_lookup(key, hash);
1041 if (i < 0)
1042 throw std::out_of_range("idict::at()");
1043 return i + offset;
1044 }
1045
1046 int at(const K &key, int defval) const
1047 {
1048 int hash = database.do_hash(key);
1049 int i = database.do_lookup(key, hash);
1050 if (i < 0)
1051 return defval;
1052 return i + offset;
1053 }
1054
1055 int count(const K &key) const
1056 {
1057 int hash = database.do_hash(key);
1058 int i = database.do_lookup(key, hash);
1059 return i < 0 ? 0 : 1;
1060 }
1061
1062 void expect(const K &key, int i)
1063 {
1064 int j = (*this)(key);
1065 if (i != j)
1066 throw std::out_of_range("idict::expect()");
1067 }
1068
1069 const K &operator[](int index) const
1070 {
1071 return database.entries.at(index - offset).udata;
1072 }
1073
1074 void swap(idict &other)
1075 {
1076 database.swap(other.database);
1077 }
1078
1079 void reserve(size_t n) { database.reserve(n); }
1080 size_t size() const { return database.size(); }
1081 bool empty() const { return database.empty(); }
1082 void clear() { database.clear(); }
1083
1084 const_iterator begin() const { return const_iterator(*this, offset); }
1085 const_iterator element(int n) const { return const_iterator(*this, n); }
1086 const_iterator end() const { return const_iterator(*this, offset + size()); }
1087 };
1088
1089 template<typename K, typename OPS>
1090 class mfp
1091 {
1092 mutable idict<K, 0, OPS> database;
1093 mutable std::vector<int> parents;
1094
1095 public:
1096 typedef typename idict<K, 0, OPS>::const_iterator const_iterator;
1097
1098 int operator()(const K &key) const
1099 {
1100 int i = database(key);
1101 parents.resize(database.size(), -1);
1102 return i;
1103 }
1104
1105 const K &operator[](int index) const
1106 {
1107 return database[index];
1108 }
1109
1110 int ifind(int i) const
1111 {
1112 int p = i, k = i;
1113
1114 while (parents[p] != -1)
1115 p = parents[p];
1116
1117 while (k != p) {
1118 int next_k = parents[k];
1119 parents[k] = p;
1120 k = next_k;
1121 }
1122
1123 return p;
1124 }
1125
1126 void imerge(int i, int j)
1127 {
1128 i = ifind(i);
1129 j = ifind(j);
1130
1131 if (i != j)
1132 parents[i] = j;
1133 }
1134
1135 void ipromote(int i)
1136 {
1137 int k = i;
1138
1139 while (k != -1) {
1140 int next_k = parents[k];
1141 parents[k] = i;
1142 k = next_k;
1143 }
1144
1145 parents[i] = -1;
1146 }
1147
1148 int lookup(const K &a) const
1149 {
1150 return ifind((*this)(a));
1151 }
1152
1153 const K &find(const K &a) const
1154 {
1155 int i = database.at(a, -1);
1156 if (i < 0)
1157 return a;
1158 return (*this)[ifind(i)];
1159 }
1160
1161 void merge(const K &a, const K &b)
1162 {
1163 imerge((*this)(a), (*this)(b));
1164 }
1165
1166 void promote(const K &a)
1167 {
1168 int i = database.at(a, -1);
1169 if (i >= 0)
1170 ipromote(i);
1171 }
1172
1173 void swap(mfp &other)
1174 {
1175 database.swap(other.database);
1176 parents.swap(other.parents);
1177 }
1178
1179 void reserve(size_t n) { database.reserve(n); }
1180 size_t size() const { return database.size(); }
1181 bool empty() const { return database.empty(); }
1182 void clear() { database.clear(); parents.clear(); }
1183
1184 const_iterator begin() const { return database.begin(); }
1185 const_iterator element(int n) const { return database.element(n); }
1186 const_iterator end() const { return database.end(); }
1187 };
1188
1189 } /* namespace hashlib */
1190
1191 #endif