Skip to content

Commit

Permalink
HashTable: Fix bug HashTable htable set to empty_slot
Browse files Browse the repository at this point in the history
htable needs to set to empty_slot or in `Insert()` it will set probing
to continue which results in additional probe at slot=0
  • Loading branch information
sethtroisi committed Nov 16, 2022
1 parent a7d08e1 commit e533780
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 40 deletions.
42 changes: 4 additions & 38 deletions core/HashTable.cpp
Expand Up @@ -25,39 +25,6 @@ HashTable::HashTable(uint32_t elements)
elements = HASH_MINIMUM_ELTS;

for (hsize = 1<<HASH_MINIMUM_SHIFT; hsize < elements/HASH_MAX_DENSITY; )
hsize <<= 1;

hsize_minus1 = hsize - 1;

htable = (uint16_t *) xmalloc(hsize*sizeof(uint16_t));
olist = (uint16_t *) xmalloc(elements*sizeof(uint16_t));

// The j values are all in the range 0 <= j < M, so we can use M as an
// empty slot marker as long as we fill BJ[M] with a value that will never
// match a real b^j value. Since b^j is always in the range 0 <= b^j < p
// for some prime p, any value larger than all 32/64 bit primes will do.
empty_slot = elements;
BJ64 = (uint64_t *) xmalloc((elements+1)*sizeof(uint64_t));
BJ64[empty_slot] = UINT64_MAX;
}

HashTable::HashTable(uint32_t elements, uint32_t bestQ, uint32_t powerResidueLcm)
{
uint32_t bjLen;

assert(elements <= HASH_MAX_ELTS);

if (elements < HASH_MINIMUM_ELTS)
elements = HASH_MINIMUM_ELTS;

for (hsize = 1<<HASH_MINIMUM_SHIFT; hsize*HASH_MAX_DENSITY < elements; )
hsize *= 2;

// Double size of hashtable if it will fit into L1 cache
if (hsize*sizeof(uint16_t) < L1_CACHE_SIZE*1024 && hsize <= elements/HASH_MIN_DENSITY/2)
hsize *= 2;

if (hsize*sizeof(uint16_t)*2 < L1_CACHE_SIZE*1024 && hsize <= elements/HASH_MIN_DENSITY/2)
hsize *= 2;

// Don't exceed maximum hash
Expand All @@ -69,15 +36,14 @@ HashTable::HashTable(uint32_t elements, uint32_t bestQ, uint32_t powerResidueLcm
htable = (uint16_t *) xmalloc(hsize*sizeof(uint16_t));
olist = (uint16_t *) xmalloc(elements*sizeof(uint16_t));

bjLen = bestQ+powerResidueLcm+9;

// The j values are all in the range 0 <= j < M, so we can use M as an
// empty slot marker as long as we fill BJ[M] with a value that will never
// match a real b^j value. Since b^j is always in the range 0 <= b^j < p
// for some prime p, any value larger than all 32/64 bit primes will do.
empty_slot = elements+1;
BJ64 = (uint64_t *) xmalloc(bjLen*sizeof(uint64_t));
BJ64[empty_slot] = UINT64_MAX;
empty_slot = elements;
BJ64 = (uint64_t *) xmalloc((elements+1)*sizeof(uint64_t));
// Point all slots at empty_slot
Clear();
}

HashTable::~HashTable(void)
Expand Down
9 changes: 7 additions & 2 deletions core/HashTable.h
Expand Up @@ -19,15 +19,18 @@ class HashTable
{
public:
HashTable(uint32_t elements);
HashTable(uint32_t babySteps, uint32_t bestQ, uint32_t powerResidueLcm);

~HashTable(void);

void Cleanup(void);

inline void Clear(void)
{
memset(htable, 0, hsize*sizeof(uint16_t));
for(uint32_t i=0; i < hsize; i++) {
htable[i] = empty_slot;
}
// will never match a Lookup value
BJ64[empty_slot] = UINT64_MAX;
}

inline uint64_t get(uint32_t x) {return BJ64[x]; };
Expand Down Expand Up @@ -55,6 +58,8 @@ class HashTable
slot = bj & hsize_minus1;
elt = htable[slot];

// Could check elt == empty_slot to avoid checking BJ64

if (BJ64[elt & HASH_MASK2] == bj)
return elt & HASH_MASK2;

Expand Down

0 comments on commit e533780

Please sign in to comment.