TdZdd  1.1
A top-down/breadth-first decision diagram manipulation framework
MyHashTable.hpp
1 /*
2  * TdZdd: a Top-down/Breadth-first Decision Diagram Manipulation Framework
3  * by Hiroaki Iwashita <iwashita@erato.ist.hokudai.ac.jp>
4  * Copyright (c) 2014 ERATO MINATO Project
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #pragma once
26 
27 #include <cassert>
28 #include <ostream>
29 #include <stdint.h>
30 
31 namespace tdzdd {
32 
33 class MyHashConstant {
34 protected:
35  static int const MAX_FILL = 75;
36 
37 public:
38  static size_t primeSize(size_t n) {
39  static unsigned long long primes[] = { //
40  (1ULL << 3) + 3, (1ULL << 4) + 3, (1ULL << 5) + 5, //
41  (1ULL << 6) + 3, (1ULL << 7) + 3, (1ULL << 8) + 7, //
42  (1ULL << 9) + 9, (1ULL << 10) + 7, (1ULL << 11) + 5, //
43  (1ULL << 12) + 3, (1ULL << 13) + 17, (1ULL << 14) + 27, //
44  (1ULL << 15) + 3, (1ULL << 16) + 3, (1ULL << 17) + 29, //
45  (1ULL << 18) + 3, (1ULL << 19) + 21, (1ULL << 20) + 7, //
46  (1ULL << 21) + 17, (1ULL << 22) + 15, (1ULL << 23) + 9, //
47  (1ULL << 24) + 43, (1ULL << 25) + 35, (1ULL << 26) + 15, //
48  (1ULL << 27) + 29, (1ULL << 28) + 3, (1ULL << 29) + 11, //
49  (1ULL << 30) + 3, (1ULL << 31) + 11, (1ULL << 32) + 15, //
50  (1ULL << 33) + 17, (1ULL << 34) + 25, (1ULL << 35) + 53, //
51  (1ULL << 36) + 31, (1ULL << 37) + 9, (1ULL << 38) + 7, //
52  (1ULL << 39) + 23, (1ULL << 40) + 15};
53 
54  int lo = 0;
55  int hi = sizeof(primes) / sizeof(primes[0]) - 1;
56 
57  if (n > primes[hi]) return n + 1;
58 
59  int i = (lo + hi) / 2;
60  while (lo < hi) {
61  if (n <= primes[i]) {
62  hi = i;
63  }
64  else {
65  lo = i + 1;
66  }
67  i = (lo + hi) / 2;
68  }
69 
70  assert(i == lo && i == hi);
71  return primes[i];
72  }
73 };
74 
75 template<typename T>
76 struct MyHashDefault {
77  size_t operator()(T const& o) const {
78  return o.hash();
79  }
80 
81  bool operator()(T const& o1, T const& o2) const {
82  return o1 == o2;
83  }
84 };
85 
86 template<typename T>
87 struct MyHashDefault<T*> {
88  size_t operator()(T const* p) const {
89  return p->hash();
90  }
91 
92  bool operator()(T const* p1, T const* p2) const {
93  return *p1 == *p2;
94  }
95 };
96 
97 template<typename T>
98 struct MyHashDefaultForInt {
99  size_t operator()(T k) const {
100  return k * 314159257ULL;
101  }
102 
103  bool operator()(T k1, T k2) const {
104  return k1 == k2;
105  }
106 };
107 
108 template<>
109 struct MyHashDefault<int8_t> : MyHashDefaultForInt<int8_t> {
110 };
111 
112 template<>
113 struct MyHashDefault<int16_t> : MyHashDefaultForInt<int16_t> {
114 };
115 
116 template<>
117 struct MyHashDefault<int32_t> : MyHashDefaultForInt<int32_t> {
118 };
119 
120 template<>
121 struct MyHashDefault<int64_t> : MyHashDefaultForInt<int64_t> {
122 };
123 
124 template<>
125 struct MyHashDefault<uint8_t> : MyHashDefaultForInt<uint8_t> {
126 };
127 
128 template<>
129 struct MyHashDefault<uint16_t> : MyHashDefaultForInt<uint16_t> {
130 };
131 
132 template<>
133 struct MyHashDefault<uint32_t> : MyHashDefaultForInt<uint32_t> {
134 };
135 
136 template<>
137 struct MyHashDefault<uint64_t> : MyHashDefaultForInt<uint64_t> {
138 };
139 
145 template<typename T, typename Hash = MyHashDefault<T>,
146  typename Equal = MyHashDefault<T> >
147 class MyHashTable: MyHashConstant {
148 protected:
149  typedef T Entry;
150 
151  Hash const hashFunc;
152  Equal const eqFunc;
153 
154  size_t tableCapacity_;
155  size_t tableSize_;
156  size_t maxSize_;
157  size_t size_;
158  Entry* table;
159  size_t collisions_;
160 
161 public:
165  MyHashTable(Hash const& hash = Hash(), Equal const& equal = Equal())
166  : hashFunc(hash), eqFunc(equal), tableCapacity_(0), tableSize_(0),
167  maxSize_(0), size_(0), table(0), collisions_(0) {
168  }
169 
176  MyHashTable(size_t n, Hash const& hash = Hash(), Equal const& equal =
177  Equal())
178  : hashFunc(hash), eqFunc(equal), tableCapacity_(0), tableSize_(0),
179  maxSize_(0), size_(0), table(0), collisions_(0) {
180  initialize(n);
181  }
182 
188  MyHashTable(MyHashTable const& o, size_t n = 1)
189  : hashFunc(o.hashFunc), eqFunc(o.eqFunc), tableCapacity_(0),
190  tableSize_(0), maxSize_(0), size_(0), table(0), collisions_(0) {
191  initialize(std::max(o.tableSize_, n));
192  for (const_iterator t = o.begin(); t != o.end(); ++t) {
193  add(*t);
194  }
195  }
196 
197  MyHashTable& operator=(MyHashTable const& o) {
198  initialize(o.tableSize_);
199  for (const_iterator t = o.begin(); t != o.end(); ++t) {
200  add(*t);
201  }
202  return *this;
203  }
204 
205 // /**
206 // * Move constructor.
207 // * @param o object to be moved.
208 // * @param n lower bound of initial table size.
209 // */
210 // MyHashTable(MyHashTable&& o, size_t n):
211 // hashFunc(o.hashFunc), eqFunc(o.eqFunc), tableCapacity_(0),
212 // tableSize_(0), maxSize_(0), size_(0), table(0), collisions_(0) {
213 // initialize(std::max(o.tableSize_, n));
214 // for (Entry const& e : o) {
215 // add(std::move(e));
216 // }
217 // o.table = 0;
218 // o.clear();
219 // }
220 //
221 // /**
222 // * Move constructor.
223 // * @param o object to be moved.
224 // */
225 // MyHashTable(MyHashTable&& o):
226 // hashFunc(o.hashFunc), eqFunc(o.eqFunc),
227 // tableCapacity_(o.tableCapacity_),
228 // tableSize_(o.tableSize_), maxSize_(o.maxSize_),
229 // size_(o.size_), table(o.table), collisions_(o.collisions_) {
230 // o.table = 0;
231 // o.clear();
232 // }
233 //
234 // MyHashTable& operator=(MyHashTable&& o) {
235 // delete [] table;
236 // tableCapacity_ = o.tableCapacity_;
237 // tableSize_ = o.tableSize_;
238 // maxSize_ = o.maxSize_;
239 // size_ = o.size_;
240 // table = o.table;
241 // collisions_ = o.collisions_;
242 // o.table = 0;
243 // o.clear();
244 // return *this;
245 // }
246 
248  delete[] table;
249  tableCapacity_ = o.tableCapacity_;
250  tableSize_ = o.tableSize_;
251  maxSize_ = o.maxSize_;
252  size_ = o.size_;
253  table = o.table;
254  collisions_ = o.collisions_;
255  o.table = 0;
256  o.clear();
257  }
258 
259  virtual ~MyHashTable() {
260  delete[] table;
261  }
262 
263  size_t tableCapacity() const {
264  return tableCapacity_ * sizeof(Entry);
265  }
266 
267  size_t tableSize() const {
268  return tableSize_;
269  }
270 
271  size_t size() const {
272  return size_;
273  }
274 
275  bool empty() const {
276  return size_ == 0;
277  }
278 
279  size_t collisions() const {
280  return collisions_;
281  }
282 
287  void clear() {
288  delete[] table;
289  tableCapacity_ = 0;
290  tableSize_ = 0;
291  maxSize_ = 0;
292  size_ = 0;
293  table = 0;
294  collisions_ = 0;
295  }
296 
301  void initialize(size_t n) {
302  tableSize_ = primeSize(n * 100 / MAX_FILL + 1);
303  maxSize_ = tableSize_ * MAX_FILL / 100;
304  size_ = 0;
305  collisions_ = 0;
306 
307  if (tableSize_ <= tableCapacity_) {
308  for (size_t i = 0; i < tableSize_; ++i) {
309  table[i] = Entry();
310  }
311  }
312  else {
313  tableCapacity_ = tableSize_;
314  delete[] table;
315  table = new Entry[tableCapacity_]();
316  }
317  }
318 
323  void rehash(size_t n = 1) {
324  MyHashTable tmp(std::max(tableSize_, n), hashFunc, eqFunc);
325  for (iterator t = begin(); t != end(); ++t) {
326  tmp.add(*t);
327  }
328  moveAssign(tmp);
329  }
330 
336  Entry& add(Entry const& elem) {
337  assert(!(elem == Entry()));
338  if (tableSize_ == 0) rehash();
339  size_t i;
340 
341  while (1) {
342  i = hashFunc(elem) % tableSize_;
343 
344  while (!(table[i] == Entry())) {
345  if (eqFunc(table[i], elem)) return table[i];
346  ++collisions_;
347  ++i;
348  if (i >= tableSize_) i = 0;
349  }
350 
351  if (size_ < maxSize_) break;
352 
353  /* Rehash only when new element is inserted. */
354  rehash(size_ * 2);
355  }
356 
357  ++size_;
358  table[i] = elem;
359  return table[i];
360  }
361 
367  Entry* get(Entry const& elem) const {
368  assert(!(elem == Entry()));
369 
370  if (tableSize_ > 0) {
371  size_t i = hashFunc(elem) % tableSize_;
372  while (!(table[i] == Entry())) {
373  if (eqFunc(table[i], elem)) return &table[i];
374  ++i;
375  if (i >= tableSize_) i = 0;
376  }
377  }
378 
379  return static_cast<Entry*>(0);
380  }
381 
382  class iterator {
383  Entry* ptr;
384  Entry const* end;
385 
386  public:
387  explicit iterator(Entry* from, Entry const* to)
388  : ptr(from), end(to) {
389  while (ptr < end && *ptr == Entry()) {
390  ++ptr;
391  }
392  }
393 
394  Entry& operator*() {
395  return *ptr;
396  }
397 
398  Entry* operator->() {
399  return ptr;
400  }
401 
402  iterator& operator++() {
403  while (++ptr < end) {
404  if (!(*ptr == Entry())) break;
405  }
406  return *this;
407  }
408 
409  bool operator==(iterator const& o) const {
410  return ptr == o.ptr;
411  }
412 
413  bool operator!=(iterator const& o) const {
414  return ptr != o.ptr;
415  }
416  };
417 
418  class const_iterator {
419  Entry const* ptr;
420  Entry const* end;
421 
422  public:
423  explicit const_iterator(Entry const* from, Entry const* to)
424  : ptr(from), end(to) {
425  while (ptr < end && *ptr == Entry()) {
426  ++ptr;
427  }
428  }
429 
430  Entry const& operator*() const {
431  return *ptr;
432  }
433 
434  Entry const* operator->() const {
435  return ptr;
436  }
437 
438  const_iterator& operator++() {
439  while (++ptr < end) {
440  if (!(*ptr == Entry())) break;
441  }
442  return *this;
443  }
444 
445  bool operator==(const_iterator const& o) const {
446  return ptr == o.ptr;
447  }
448 
449  bool operator!=(const_iterator const& o) const {
450  return ptr != o.ptr;
451  }
452  };
453 
454  iterator begin() {
455  return iterator(table, table + tableSize_);
456  }
457 
458  const_iterator begin() const {
459  return const_iterator(table, table + tableSize_);
460  }
461 
462  iterator end() {
463  return iterator(table + tableSize_, table + tableSize_);
464  }
465 
466  const_iterator end() const {
467  return const_iterator(table + tableSize_, table + tableSize_);
468  }
469 };
470 
476 template<typename K, typename V>
478  typedef K Key;
479  typedef V Value;
480 
481  K key;
482  V value;
483 
485  : key(), value() {
486  }
487 
488  MyHashMapEntry(K const& key)
489  : key(key), value() {
490  }
491 
492  MyHashMapEntry(K const& key, V const& value)
493  : key(key), value(value) {
494  }
495 
501  bool operator==(MyHashMapEntry const& o) const {
502  return key == o.key;
503  }
504 
510  bool operator<(MyHashMapEntry const& o) const {
511  return key < o.key;
512  }
513 
520  friend std::ostream& operator<<(std::ostream& os, MyHashMapEntry const& o) {
521  return os << "(" << o.key << " => " << o.value << ")";
522  }
523 }
524 ;
525 
526 template<typename K, typename V, typename Hash, typename Equal>
527 class MyHashMapHashWrapper {
528  Hash const hashFunc;
529  Equal const eqFunc;
530 
531 public:
532  MyHashMapHashWrapper(Hash const& hash, Equal const& equal)
533  : hashFunc(hash), eqFunc(equal) {
534  }
535 
536  size_t operator()(MyHashMapEntry<K,V> const& o) const {
537  return hashFunc(o.key);
538  }
539 
540  bool operator()(MyHashMapEntry<K,V> const& o1,
541  MyHashMapEntry<K,V> const& o2) const {
542  return eqFunc(o1.key, o2.key);
543  }
544 };
545 
552 template<typename K, typename V, typename Hash = MyHashDefault<K>,
553  typename Equal = MyHashDefault<K> >
554 struct MyHashMap: public MyHashTable<MyHashMapEntry<K,V>,
555  MyHashMapHashWrapper<K,V,Hash,Equal>,
556  MyHashMapHashWrapper<K,V,Hash,Equal> > {
557  typedef MyHashMapEntry<K,V> Entry;
559  MyHashMapHashWrapper<K,V,Hash,Equal> > Table;
560 
564  MyHashMap(Hash const& hash = Hash(), Equal const& equal = Equal())
565  : Table(MyHashMapHashWrapper<K,V,Hash,Equal>(hash, equal),
566  MyHashMapHashWrapper<K,V,Hash,Equal>(hash, equal)) {
567  }
568 
575  MyHashMap(size_t n, Hash const& hash = Hash(), Equal const& equal = Equal())
576  : Table(n, MyHashMapHashWrapper<K,V,Hash,Equal>(hash, equal),
577  MyHashMapHashWrapper<K,V,Hash,Equal>(hash, equal)) {
578  }
579 
585  MyHashMap(MyHashMap const& o, size_t n = 1)
586  : Table(o, n) {
587  }
588 
589 // /**
590 // * Move constructor.
591 // * @param o the object to be moved.
592 // * @param n lower bound of initial table size.
593 // */
594 // MyHashMap(MyHashMap&& o, size_t n = 1): Table(std::move(o), n) {
595 // }
596 
602  V& operator[](K const& key) {
603  return Table::add(Entry(key)).value;
604  }
605 
611  V* getValue(K const& key) const {
612  Entry* p = Table::get(Entry(key));
613  return (p != 0) ? &p->value : 0;
614  }
615 };
616 
617 } // namespace tdzdd
bool operator<(MyHashMapEntry const &o) const
Check the order of keys with another object.
Closed hash map implementation.
Closed hash table implementation.
Entry * table
Pointer to the storage.
bool operator==(MyHashMapEntry const &o) const
Check key&#39;s equivalence between another object.
MyHashMap(MyHashMap const &o, size_t n=1)
Copy constructor.
MyHashTable(size_t n, Hash const &hash=Hash(), Equal const &equal=Equal())
Constructor.
Entry & add(Entry const &elem)
Insert an element if no other equivalent element is registered.
void clear()
Initialize the table to be empty.
Hash const hashFunc
Functor for getting hash codes.
MyHashTable(MyHashTable const &o, size_t n=1)
Copy constructor.
MyHashMap(size_t n, Hash const &hash=Hash(), Equal const &equal=Equal())
Constructor.
size_t tableSize_
Size of the hash table.
Equal const eqFunc
Functor for checking equivalence.
MyHashTable(Hash const &hash=Hash(), Equal const &equal=Equal())
Default constructor.
void rehash(size_t n=1)
Resize the storage appropriately.
V & operator[](K const &key)
Move constructor.
V * getValue(K const &key) const
Get the value that is already registered.
void initialize(size_t n)
Initialize the table to be empty.
void moveAssign(MyHashTable &o)
Move constructor.
MyHashMap(Hash const &hash=Hash(), Equal const &equal=Equal())
Default constructor.
Entry for a hash map.
size_t maxSize_
The maximum number of elements.
size_t tableCapacity_
Size of the hash table storage.
size_t size_
The number of elements.
friend std::ostream & operator<<(std::ostream &os, MyHashMapEntry const &o)
Print the object.