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