Last active
September 23, 2023 11:47
-
-
Save miura1729/d24bfb66020ce6b58237851cb07b0ec1 to your computer and use it in GitHub Desktop.
1st version 24 entry on 32 buckets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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