6 #ifndef TURI_UTIL_HOPSCOTCH_HASH_HPP 7 #define TURI_UTIL_HOPSCOTCH_HASH_HPP 9 #include <core/generics/hopscotch_table.hpp> 11 #include <core/storage/serialization/serialization_includes.hpp> 14 #define _HOPSCOTCH_MAP_DEFAULT_HASH std::hash<Key> 35 template <
typename Key,
37 typename Hash = _HOPSCOTCH_MAP_DEFAULT_HASH,
38 typename KeyEqual = std::equal_to<Key> >
44 typedef std::pair<Key, Value> value_type;
45 typedef Value mapped_type;
46 typedef size_t size_type;
48 typedef KeyEqual equality_function;
49 typedef value_type* pointer;
50 typedef value_type& reference;
51 typedef const value_type* const_pointer;
52 typedef const value_type& const_reference;
55 typedef std::pair<Key, Value> storage_type;
59 hash_redirect(Hash h): hashfun(h) { }
60 size_t operator()(
const storage_type& v)
const {
61 return hashfun(v.first);
64 struct key_equal_redirect{
66 key_equal_redirect(KeyEqual k): keyeq(k) { }
67 bool operator()(
const storage_type& v,
const storage_type& v2)
const {
68 return keyeq(v.first, v2.first);
76 typedef boost::unordered_map<key_type, mapped_type, Hash> spill_type;
78 struct const_iterator{
79 typedef std::forward_iterator_tag iterator_category;
80 typedef const typename hopscotch_map::value_type value_type;
81 typedef size_t difference_type;
82 typedef value_type* pointer;
83 typedef value_type& reference;
89 typename hopscotch_map::spill_type::const_iterator iter2;
92 const_iterator():ptr(NULL) {}
95 const_iterator operator++() {
98 if (iter == ptr->container->
end()) {
107 const_iterator operator++(
int) {
108 iterator cur = *
this;
114 reference operator*() {
115 if (!in_spill)
return (*iter);
116 else return *
reinterpret_cast<pointer
>(&(*iter2));
119 pointer operator->() {
120 if (!in_spill)
return &(*iter);
121 else return reinterpret_cast<pointer
>(&(*iter2));
125 bool operator==(
const const_iterator it)
const {
126 return ptr == it.ptr &&
127 ((!in_spill && iter == it.iter) ||
128 (in_spill && iter2 == it.iter2));
131 bool operator!=(
const const_iterator iter)
const {
132 return !((*this) == iter);
137 typename spill_type::const_iterator iter2):
138 ptr(map), iter(iter), iter2(iter2), in_spill(iter == ptr->container->
end()) { }
142 typedef std::forward_iterator_tag iterator_category;
143 typedef typename hopscotch_map::value_type value_type;
144 typedef size_t difference_type;
145 typedef value_type* pointer;
146 typedef value_type& reference;
152 typename hopscotch_map::spill_type::iterator iter2;
155 iterator():ptr(NULL) {}
158 operator const_iterator()
const {
159 const_iterator it(ptr, iter, iter2);
163 iterator operator++() {
168 if (iter == ptr->container->
end()) {
177 iterator operator++(
int) {
178 iterator cur = *
this;
184 reference operator*() {
185 if (!in_spill)
return (*iter);
186 else return *
reinterpret_cast<pointer
>(&(*iter2));
189 pointer operator->() {
190 if (!in_spill)
return &(*iter);
191 else return reinterpret_cast<pointer
>(&(*iter2));
194 bool operator==(
const iterator it)
const {
195 return ptr == it.ptr &&
196 ((!in_spill && iter == it.iter) ||
197 (in_spill && iter2 == it.iter2));
200 bool operator!=(
const iterator iter)
const {
201 return !((*this) == iter);
206 typename spill_type::iterator iter2):
207 ptr(map), iter(iter), iter2(iter2), in_spill(iter == ptr->container->
end()) { }
216 container_type* container;
222 hash_redirect hashfun;
226 key_equal_redirect equalfun;
228 container_type* create_new_container(
size_t size) {
229 return new container_type(size, hashfun, equalfun);
239 void rehash_to_new_container(
size_t newsize = (
size_t)(-1)) {
246 if (newsize == (
size_t)(-1)) newsize = size() * 2;
247 container_type* newcontainer = create_new_container(newsize);
248 const_iterator citer = begin();
250 while (citer != end()) {
251 if(newcontainer->
insert(*citer) == newcontainer->
end()) {
252 newspill.insert(*citer);
256 std::swap(container, newcontainer);
257 std::swap(spill, newspill);
263 iterator do_insert(
const value_type &v) {
266 if (iter != container->
end()) {
267 return iterator(
this, iter, spill.begin());
270 if (load_factor() > 0.8) {
271 rehash_to_new_container();
272 iter = container->
insert(v);
273 if(iter != container->
end()) {
274 return iterator(
this, iter, spill.begin());
277 return iterator(
this, container->
end(), spill.insert(v).first);
282 return iterator(
this, container->
end(), spill.insert(v).first);
290 KeyEqual equalfun = KeyEqual()):
292 hashfun(hashfun), equalfun(equalfun) {
293 container = create_new_container(32);
297 hashfun(h.hashfun), equalfun(h.equalfun) {
298 container = create_new_container(h.capacity());
299 (*container) = *(h.container);
304 void rehash(
size_t s) {
305 if (s > capacity()) {
306 rehash_to_new_container(s);
314 hasher hash_function()
const {
315 return hashfun.hashfun;
318 KeyEqual key_eq()
const {
319 return equalfun.equalfun;
323 (*container) = *(other.container);
324 hashfun = other.hashfun;
325 equalfun = other.equalfun;
329 size_type size()
const {
330 return container->
size() + spill.size();
334 return iterator(
this, container->
begin(), spill.begin());
338 return iterator(
this, container->
end(), spill.end());
342 const_iterator begin()
const {
343 return const_iterator(
this, container->
begin(), spill.begin());
346 const_iterator end()
const {
347 return const_iterator(
this, container->
end(), spill.end());
351 std::pair<iterator, bool> insert(
const value_type& v) {
352 iterator i = find(v.first);
353 if (i != end())
return std::make_pair(i,
false);
354 else return std::make_pair(do_insert(v),
true);
358 iterator insert(const_iterator hint,
const value_type& v) {
359 return insert(v).first;
362 iterator find(key_type
const& k) {
363 value_type v(k, mapped_type());
365 if (iter != container->
end()) {
366 return iterator(
this, iter, spill.begin());
368 return iterator(
this, iter, spill.find(k));
372 const_iterator find(key_type
const& k)
const {
373 value_type v(k, mapped_type());
375 if (iter != container->
end()) {
376 return const_iterator(
this, iter, spill.begin());
378 return const_iterator(
this, iter, spill.find(k));
382 size_t count(key_type
const& k)
const {
383 value_type v(k, mapped_type());
384 return container->
count(v) || spill.count(k);
388 bool erase(iterator iter) {
389 return container->
erase(iter.iter) || spill.erase(iter.iter2);
392 bool erase(key_type
const& k) {
393 value_type v(k, mapped_type());
394 return container->
erase(v) || spill.erase(k);
398 std::swap(container, other.container);
399 std::swap(spill, other.spill);
400 std::swap(hashfun, other.hashfun);
401 std::swap(equalfun, other.equalfun);
404 mapped_type& operator[](
const key_type& i) {
405 iterator iter = find(i);
406 value_type tmp(i, mapped_type());
407 if (iter == end()) iter = do_insert(tmp);
413 container = create_new_container(128);
417 size_t capacity()
const {
418 return container->
capacity() + spill.size();
422 float load_factor()
const {
423 return float(size()) / capacity();
427 oarc << size() << capacity();
428 const_iterator iter = begin();
429 while (iter != end()) {
439 if (capacity() != c) {
441 container = create_new_container(c);
446 for (
size_t i = 0;i < s; ++i) {
453 void put(
const value_type &v) {
455 (*this)[v.first] = v.second;
458 void put(
const Key& k,
const Value& v) {
462 std::pair<bool, Value>
get(
const Key& k)
const {
463 const_iterator iter = find(k);
464 return std::make_pair(iter == end(), iter->second);
size_t capacity() const
Returns the capacity of the table.
The serialization input archive object which, provided with a reference to an istream, will read from the istream, providing deserialization capabilities.
iterator end()
Returns an iterator to the end of the table.
size_t count(const value_type &v) const
Returns 1 if the table contains a given element. 0 otherwise.
const_iterator find(const value_type &key) const
iterator begin()
Returns an iterator to the start of the table.
bool erase(iterator iter)
iterator insert(const value_type &newdata)
size_t size() const
Returns the number of elements in the table.
The serialization output archive object which, provided with a reference to an ostream, will write to the ostream, providing serialization capabilities.