Skip to content

Instantly share code, notes, and snippets.

@miura1729
Last active September 23, 2023 11:47
Show Gist options
  • Save miura1729/d24bfb66020ce6b58237851cb07b0ec1 to your computer and use it in GitHub Desktop.
Save miura1729/d24bfb66020ce6b58237851cb07b0ec1 to your computer and use it in GitHub Desktop.
1st version 24 entry on 32 buckets
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef int key_t;
typedef int value_t;
typedef struct mhash {
uint64_t exists;
uint64_t origin;
key_t *keys;
value_t *values;
uint8_t *same_hash;
int n_buckets;
} mhash;
uint64_t ror(uint64_t base, int sn, int basesize)
{
uint64_t snbit = (1ll << (sn + 1)) - 1;
return (((base & snbit) << (basesize - sn)) | (base >> sn))
& ((1ll << basesize)) - 1;
}
mhash *mh_init(int size) {
mhash *h = malloc(sizeof(mhash));
h->n_buckets = size;
h->exists = 0;
h->origin = 0;
h->keys = calloc(size, sizeof(key_t));
h->values = calloc(size, sizeof(key_t));
h->same_hash = calloc(size, sizeof(uint8_t));
return h;
}
#define hash_func(hash) (unsigned int)((key)^((key)<<2)^((key)>>2))
int mh_put(mhash *h, key_t key) {
int hv = hash_func(key) % h->n_buckets;
uint64_t hv_bitmap = (1ll << hv);
if ((h->exists & hv_bitmap) == 0) {
/* no confilct hash value and entry is fresh */
h->exists |= hv_bitmap;
h->keys[hv] = key;
h->same_hash[hv] = 1;
h->exists |= hv_bitmap;
return hv;
}
if (h->same_hash[hv] & 1) {
/* useing entry for same hash value */
uint64_t alexits = ror(h->exists, hv, h->n_buckets);
int empoff = __builtin_ffsll(alexits + 1) - 1;
if (empoff < 8) {
int newent = (empoff + hv) % h->n_buckets;
h->same_hash[hv] |= (1 << empoff);
h->exists |= (1ll << newent);
h->same_hash[newent] = (empoff << 1);
h->keys[newent] = key;
return newent;
}
/* Oh! fill my entry. Must still from other entry */
abort();
}
/* using entry for other hash value. */
{
int eoff = h->same_hash[hv] >> 1;
int hv2 = (hv - eoff) % h->n_buckets;
uint64_t alexits = ror(h->exists, hv2, h->n_buckets);
int empoff = __builtin_ffsll(alexits + 1) - 1;
if (empoff < 8) {
int newent = (empoff + hv2) % h->n_buckets;
h->same_hash[hv2] ^= (1 << eoff); /* Clear old entry */
h->same_hash[hv2] |= (1 << empoff); /* Set new entry */
h->keys[newent] = h->keys[hv];
h->values[newent] = h->values[hv];
h->same_hash[newent] = empoff << 1;
h->exists |= (1 << newent);
h->same_hash[hv] = 1;
h->keys[hv] = key;
return hv;
}
abort();
}
return h->n_buckets;
}
int mh_get(mhash *h, key_t key) {
int hv = hash_func(key) % h->n_buckets;
uint8_t hbit = h->same_hash[hv];
if (hbit & 1) {
for (int i = 0; i >= 0 && i < 8;i = __builtin_ffs(hbit) - 1) {
int ent = (i + hv) % h->n_buckets;
if (h->keys[ent] == key) {
return ent;
}
hbit ^= (1 << i);
}
}
return -1;
}
main(){
mhash *h = mh_init(32);
for (int i = 0; i < 23; i++) {
int ent = mh_put(h, i);
printf("%d \n", ent);
h->values[ent] = i + 1;
}
printf("fin\n");
for (int i = 0; i < 23; i++) {
int ent = mh_get(h, i);
printf("%d %d \n", h->values[ent], ent);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment