31template <
typename GID,
typename LID,
int maxBucketOverflow = 4, GID EMPTYBUCKET = vmesh::INVALID_GLOBALID >
class OpenBucketHashtable {
40 uint32_t retval = (uint64_t)(in * 2654435769ul) >> (32 -
sizePower);
45 static uint32_t
fnv_1a(
const void* chunk,
size_t bytes) {
47 uint32_t h = 2166136261ul;
48 const unsigned char* ptr =
static_cast<const unsigned char*
>(chunk);
50 h = (h ^ *ptr++) * 16777619ul;
56 uint32_t
hash(GID in)
const {
57 static constexpr bool n = (std::is_arithmetic<GID>::value &&
sizeof(GID) <=
sizeof(uint32_t));
62 return fnv_1a(&in,
sizeof(GID));
72 if (newSizePower > 31) {
73 throw std::out_of_range(
"OpenBucketHashtable ran into rehashing catastrophe and exceeded 32bit buckets.");
75 std::vector<std::pair<GID, LID>> newBuckets(1u << newSizePower, std::pair<GID, LID>(EMPTYBUCKET, LID()));
82 if (e.first == EMPTYBUCKET) {
86 uint32_t newHash =
hash(e.first);
88 for (
int i = 0;
i < maxBucketOverflow;
i++) {
89 std::pair<GID, LID>& candidate = newBuckets[(newHash +
i) & bitMask];
90 if (candidate.first == EMPTYBUCKET) {
101 return rehash(newSizePower + 1);
110 LID&
at(
const GID& key) {
112 uint32_t hashIndex =
hash(key);
115 for (
int i = 0;
i < maxBucketOverflow;
i++) {
116 std::pair<GID, LID>& candidate =
buckets[(hashIndex +
i) & bitMask];
117 if (candidate.first == key) {
119 return candidate.second;
121 if (candidate.first == EMPTYBUCKET) {
123 candidate.first = key;
125 return candidate.second;
134 const LID&
at(
const GID& key)
const {
136 uint32_t hashIndex =
hash(key);
139 for (
int i = 0;
i < maxBucketOverflow;
i++) {
140 const std::pair<GID, LID>& candidate =
buckets[(hashIndex +
i) & bitMask];
141 if (candidate.first == key) {
143 return candidate.second;
145 if (candidate.first == EMPTYBUCKET) {
147 throw std::out_of_range(
"Element not found in OpenBucketHashtable.at");
152 throw std::out_of_range(
"Element not found in OpenBucketHashtable.at");
163 size_t count(
const GID& key)
const {
172 buckets = std::vector<std::pair<GID, LID>>(1 <<
sizePower, {EMPTYBUCKET, LID()});
214 return !(*
this == other);
258 return !(*
this == other);
267 if (
buckets[
i].first != EMPTYBUCKET) {
275 if (
buckets[
i].first != EMPTYBUCKET) {
288 uint32_t hashIndex =
hash(key);
291 for (
int i = 0;
i < maxBucketOverflow;
i++) {
292 const std::pair<GID, LID>& candidate =
buckets[(hashIndex +
i) & bitMask];
293 if (candidate.first == key) {
295 return iterator(
this, (hashIndex +
i) & bitMask);
298 if (candidate.first == EMPTYBUCKET) {
310 uint32_t hashIndex =
hash(key);
313 for (
int i = 0;
i < maxBucketOverflow;
i++) {
314 const std::pair<GID, LID>& candidate =
buckets[(hashIndex +
i) & bitMask];
315 if (candidate.first == key) {
320 if (candidate.first == EMPTYBUCKET) {
331 std::pair<iterator, bool>
insert(std::pair<GID, LID> newEntry) {
332 bool found =
find(newEntry.first) !=
end();
334 at(newEntry.first) = newEntry.second;
336 return std::pair<iterator, bool>(
find(newEntry.first), !found);
352 size_t targetPos =
index;
354 for (
unsigned int i = 1;
i <
fill;
i++) {
356 if (nextBucket == EMPTYBUCKET) {
361 uint32_t hashIndex =
hash(nextBucket);
362 if ((hashIndex&bitMask) != ((
index +
i)&bitMask)) {
364 uint32_t distance = ((targetPos - hashIndex + (1<<
sizePower) )&bitMask);
365 if (distance < maxBucketOverflow) {
369 buckets[targetPos] = std::pair<GID, LID>(nextBucket,moveValue);
370 targetPos = ((
index+
i)&bitMask);
371 buckets[targetPos].first = EMPTYBUCKET;
382 if(element ==
end()) {
396 size_t tempFill =
fill;
398 other.
fill = tempFill;
std::random_access_iterator_tag iterator_category
std::pair< GID, LID > value_type
const std::pair< GID, LID > & operator*() const
std::pair< GID, LID > * pointer
bool operator==(const_iterator other) const
const_iterator & operator++()
bool operator!=(const_iterator other) const
std::ptrdiff_t difference_type
std::pair< GID, LID > & reference
const std::pair< GID, LID > * operator->() const
const_iterator operator++(int)
const_iterator(const OpenBucketHashtable< GID, LID > *hashtable, size_t index)
const OpenBucketHashtable< GID, LID > * hashtable
OpenBucketHashtable< GID, LID > * hashtable
std::pair< GID, LID > value_type
std::pair< GID, LID > * pointer
std::random_access_iterator_tag iterator_category
bool operator==(iterator other) const
std::ptrdiff_t difference_type
std::pair< GID, LID > * operator->() const
bool operator!=(iterator other) const
std::pair< GID, LID > & reference
iterator(OpenBucketHashtable< GID, LID > *hashtable, size_t index)
std::pair< GID, LID > & operator*() const
const_iterator end() const
size_t bucket_count() const
const_iterator begin() const
void swap(OpenBucketHashtable< GID, LID > &other)
void rehash(int newSizePower)
static uint32_t fnv_1a(const void *chunk, size_t bytes)
std::pair< iterator, bool > insert(std::pair< GID, LID > newEntry)
const LID & at(const GID &key) const
size_t erase(const GID &key)
iterator erase(iterator keyPos)
uint32_t fibonacci_hash(GID in) const
const const_iterator find(GID key) const
uint32_t hash(GID in) const
std::vector< std::pair< GID, LID > > buckets
LID & operator[](const GID &key)
size_t count(const GID &key) const