6 #ifndef TURI_UTIL_HOPSCOTCH_TABLE_HPP 7 #define TURI_UTIL_HOPSCOTCH_TABLE_HPP 14 #include <core/logging/assertions.hpp> 16 #define _HOPSCOTCH_TABLE_DEFAULT_HASH std::hash<T> 36 typename Hash = _HOPSCOTCH_TABLE_DEFAULT_HASH,
37 typename KeyEqual = std::equal_to<T> >
42 typedef size_t size_type;
62 element():hasdata(
false), field(0) { }
65 std::vector<element> data;
68 equality_function equalfun;
73 static uint64_t next_powerof2(uint64_t val) {
75 val = val | (val >> 1);
76 val = val | (val >> 2);
77 val = val | (val >> 4);
78 val = val | (val >> 8);
79 val = val | (val >> 16);
80 val = val | (val >> 32);
87 size_t compute_hash(
const value_type& d)
const {
88 size_t state = hashfun(d);
89 #ifdef HAS_BUILTIN_CRC32 90 return __builtin_ia32_crc32di(0, state);
96 state += (state << 12);
97 state ^= (state >> 22);
98 state += (state << 4);
99 state ^= (state >> 9);
100 state += (state << 10);
101 state ^= (state >> 2);
102 state += (state << 7);
103 state ^= (state >> 12);
120 Hash hashfun = Hash(),
121 KeyEqual equalfun = KeyEqual()):
122 data(next_powerof2(len) + 32),
126 mask(data.
size() - 32 - 1) {
145 typedef std::forward_iterator_tag iterator_category;
147 typedef size_t difference_type;
154 typename std::vector<element>::const_iterator iter;
160 while(iter != ptr->data.end() && !iter->hasdata) {
173 reference operator*() {
177 pointer operator->() {
178 return &(iter->elem);
182 return ptr == it.ptr && iter == it.iter;
186 return !((*this) == iter);
192 typename std::vector<element>::const_iterator iter):
193 ptr(table), iter(iter) { }
204 typedef std::forward_iterator_tag iterator_category;
206 typedef size_t difference_type;
213 typename std::vector<element>::iterator iter;
225 while(iter != ptr->data.end() && !iter->hasdata) {
238 reference operator*() {
242 pointer operator->() {
243 return &(iter->elem);
246 bool operator==(
const iterator it)
const {
247 return ptr == it.ptr && iter == it.iter;
250 bool operator!=(
const iterator iter)
const {
251 return !((*this) == iter);
257 typename std::vector<element>::iterator iter):
258 ptr(table), iter(iter) { }
268 typedef std::forward_iterator_tag iterator_category;
298 iterator try_find_and_overwrite(
const value_type& newdata,
302 iterator iter = find_impl(newdata, target);
303 if (iter !=
end() && overwrite) {
304 iter.iter->elem = newdata;
314 iterator insert_impl(
const value_type& newdata,
bool overwrite =
true) {
316 size_t target = compute_hash(newdata) & mask;
318 iterator ret = try_find_and_overwrite(newdata,
321 if (ret !=
end())
return ret;
325 size_t shift_target = target;
327 size_t limit = std::min(data.size(), target + 31 * 20);
328 for (;shift_target < limit; shift_target++) {
329 if (data[shift_target].hasdata ==
false) {
331 if (data[shift_target].hasdata ==
false) {
347 while(shift_target - target >= 31) {
356 for (
size_t i = 30; i >= 1; --i) {
358 if (data[shift_target - i].field) {
359 r = __builtin_ctz(data[shift_target - i].field);
362 size_t new_shift_target = shift_target - i + r;
364 data[shift_target].elem = data[new_shift_target].elem;
365 data[shift_target].hasdata =
true;
366 data[new_shift_target].hasdata =
false;
367 data[new_shift_target].elem = T();
370 data[shift_target - i].field =
371 (data[shift_target - i].field & ~((uint32_t)1 << r))
372 | ((uint32_t)1 << i);
373 shift_target = new_shift_target;
386 data[shift_target].elem = newdata;
387 data[target].field |= (1 << (shift_target - target));
388 data[shift_target].hasdata =
true;
390 return iterator(
this, data.begin() + shift_target);
400 const_iterator find_impl(
const value_type& key,
size_t target)
const {
401 uint32_t field = data[target].field;
403 int r = __builtin_ctz(field);
404 if (data[target + r].hasdata &&
405 key_eq()(data[target + r].elem, key)) {
410 field &= ~(((uint32_t)1 << r));
417 iterator find_impl(
const value_type& key,
size_t target) {
419 return iterator(
this, data.begin() + (iter.iter - data.begin()));
430 return insert_impl(newdata);
441 return insert_impl(newdata,
false);
452 size_t target = compute_hash(key) & mask;
453 return find_impl(key, target);
463 return iterator(
this, data.begin() + (iter.iter - data.begin()));
468 for (
size_t i = 0;i < data.size(); ++i) {
469 data[i].hasdata =
false;
480 if (iter.iter == data.end())
return false;
482 size_t target = compute_hash(iter.iter->elem) & mask;
483 size_t offset = iter.iter - (data.begin() + target);
486 iter.iter->hasdata =
false;
488 data[target].field &= ~((uint32_t)1 << offset);
500 typename std::vector<element>::iterator iter = data.begin();
501 while (iter != data.end() && !iter->hasdata) {
510 typename std::vector<element>::iterator iter = data.begin();
511 while (iter != data.end() && !iter->hasdata) {
528 size_t count(
const value_type& v)
const {
547 float load_factor()
const {
555 hashfun = other.hashfun;
556 equalfun = other.equalfun;
569 return insert_impl(t).iter != data.end();
579 return insert_impl(t,
false).iter != data.end();
589 std::pair<bool, T>
get(
const T& t)
const {
594 element e = *(iter.iter);
595 if (e.hasdata &&
key_eq()(e.elem, t)) {
596 return std::make_pair(
true, e.elem);
600 return std::make_pair(
false, T());
size_t capacity() const
Returns the capacity of the table.
KeyEqual equality_function
The type of the equality tester.
Hash hasher
The type of the hasher object.
hasher hash_function() const
Returns the hash function used by the hash table.
value_type * pointer
A pointer to the data type stored in the table.
iterator end()
Returns an iterator to the end of the table.
iterator insert_do_not_overwrite(const value_type &newdata)
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 contains(const value_type &v) const
Returns true if the table contains a given element. false otherwise.
bool erase(const value_type &key)
Erases a entry matching a given value.
bool erase(iterator iter)
bool put_do_not_overwrite(const T &t)
equality_function key_eq() const
Returns the equality function used by the hash table.
iterator find(const value_type &key)
const value_type * const_pointer
A constant pointer to the data type stored in the table.
const_iterator begin() const
Returns an iterator to the start of the table.
hopscotch_table(size_t len, Hash hashfun=Hash(), KeyEqual equalfun=KeyEqual())
iterator insert(const value_type &newdata)
size_t size() const
Returns the number of elements in the table.
T value_type
The data type stored in the table.
value_type & reference
A reference to the data type stored in the table.
#define DASSERT_TRUE(cond)
const value_type & const_reference
A constant reference to the data type stored in the table.
const_iterator end() const
Returns an iterator to the end of the table.