38 #define HM_INITIAL_CAPACITY 8 39 #define DIB(curr_i, hash, capacity_mo) ((curr_i) >= ((hash) & (capacity_mo)) ? (curr_i) - ((hash) & (capacity_mo)) : (capacity_mo) + 1 + (curr_i) - ((hash) & (capacity_mo))) 40 #define SWAP_VALUES(a, b) do{__typeof(a) _tmp = (a); (a) = (b); (b) = _tmp;}while(0) 45 static hash_t _get_hash(key_type_t key){
46 uint64_t z = key + 0x9e3779b97f4a7c15;
47 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
48 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
49 return (hash_t)((z ^ (z >> 31)) >> 32);
57 _i_hmap->capacity_mo = HM_INITIAL_CAPACITY - 1;
58 _i_hmap->nodes = rsalloc(
sizeof(
struct _hash_map_node_t) * HM_INITIAL_CAPACITY);
59 memset(_i_hmap->nodes, UCHAR_MAX,
sizeof(
struct _hash_map_node_t) * HM_INITIAL_CAPACITY);
63 rsfree(_i_hmap->nodes);
66 static void _hash_map_insert_hashed(
struct _inner_hash_map_t *_i_hmap,
struct _hash_map_node_t node){
67 struct _hash_map_node_t *nodes = _i_hmap->nodes;
68 struct _hash_map_node_t cur_node = node;
69 map_size_t capacity_mo = _i_hmap->capacity_mo;
72 map_size_t i = node.hash & capacity_mo;
79 if(nodes[i].elem_i == HMAP_INVALID_I){
83 }
else if(dib > DIB(i, nodes[i].hash, capacity_mo)){
85 dib = DIB(i, nodes[i].hash, capacity_mo);
86 SWAP_VALUES(cur_node, nodes[i]);
95 static void _hash_map_realloc_rehash(
struct _inner_hash_map_t *_i_hmap, map_size_t count){
97 struct _hash_map_node_t *rmv = _i_hmap->nodes;
99 _i_hmap->nodes = rsalloc(
sizeof(
struct _hash_map_node_t) * (_i_hmap->capacity_mo + 1));
100 memset(_i_hmap->nodes, UCHAR_MAX,
sizeof(
struct _hash_map_node_t) * (_i_hmap->capacity_mo + 1));
102 map_size_t i = count, j = 0;
104 while(rmv[j].elem_i == HMAP_INVALID_I)
107 _hash_map_insert_hashed(_i_hmap, rmv[j]);
114 static void _hash_map_expand(
struct _inner_hash_map_t *_i_hmap, map_size_t count){
116 if((
double)_i_hmap->capacity_mo * MAX_LOAD_FACTOR >= count)
119 _i_hmap->capacity_mo = 2 * _i_hmap->capacity_mo + 1;
121 _hash_map_realloc_rehash(_i_hmap, count);
124 static void _hash_map_shrink(
struct _inner_hash_map_t *_i_hmap, map_size_t count){
126 if((
double)_i_hmap->capacity_mo * MIN_LOAD_FACTOR <= count ||
127 _i_hmap->capacity_mo <= HM_INITIAL_CAPACITY)
130 _i_hmap->capacity_mo /= 2;
132 _hash_map_realloc_rehash(_i_hmap, count);
135 void _hash_map_add(
struct _inner_hash_map_t *_i_hmap, key_type_t key, map_size_t count){
137 _hash_map_expand(_i_hmap, count);
139 struct _hash_map_node_t node = {key, _get_hash(key), count};
141 _hash_map_insert_hashed(_i_hmap, node);
144 static map_size_t _hash_map_index_lookup(
struct _inner_hash_map_t *_i_hmap, key_type_t key){
145 struct _hash_map_node_t *nodes = _i_hmap->nodes;
146 map_size_t capacity_mo = _i_hmap->capacity_mo;
148 hash_t cur_hash = _get_hash(key);
149 map_size_t i = cur_hash & capacity_mo;
153 if(nodes[i].elem_i == HMAP_INVALID_I){
155 return HMAP_INVALID_I;
157 }
else if(nodes[i].hash == cur_hash && nodes[i].key == key)
163 }
while(dib <= DIB(i, nodes[i].hash, capacity_mo));
169 unsigned _hash_map_lookup(
struct _inner_hash_map_t *_i_hmap,
unsigned long long key){
171 map_size_t i = _hash_map_index_lookup(_i_hmap, key);
173 return i == UINT_MAX ? UINT_MAX : _i_hmap->nodes[i].elem_i;
176 void _hash_map_update_i(
struct _inner_hash_map_t *_i_hmap,
unsigned long long key, map_size_t new_i){
178 map_size_t i = _hash_map_index_lookup(_i_hmap, key);
181 _i_hmap->nodes[i].elem_i = new_i;
184 void _hash_map_remove(
struct _inner_hash_map_t *_i_hmap,
unsigned long long key, map_size_t cur_count){
186 map_size_t i = _hash_map_index_lookup(_i_hmap, key);
188 if(i == UINT_MAX)
return;
190 struct _hash_map_node_t *nodes = _i_hmap->nodes;
191 map_size_t capacity_mo = _i_hmap->capacity_mo;
198 }
while(nodes[j].elem_i != UINT_MAX && DIB(j, nodes[j].hash, capacity_mo) != 0);
207 memmove(&nodes[i], &nodes[i + 1], (j - i) *
sizeof(
struct _hash_map_node_t));
210 memmove(&nodes[i], &nodes[i + 1], (capacity_mo - i) *
sizeof(
struct _hash_map_node_t));
212 memcpy(&nodes[capacity_mo], &nodes[0],
sizeof(
struct _hash_map_node_t));
214 memmove(&nodes[0], &nodes[1], j *
sizeof(
struct _hash_map_node_t));
218 nodes[j].elem_i = UINT_MAX;
221 _hash_map_shrink(_i_hmap, cur_count - 1);
225 return sizeof(_i_hmap->capacity_mo) + (_i_hmap->capacity_mo + 1) *
sizeof(*(_i_hmap->nodes));
228 inline unsigned char * _hash_map_dump(
struct _inner_hash_map_t *_i_hmap,
unsigned char *_destination){
229 *((map_size_t *)_destination) = _i_hmap->capacity_mo;
230 _destination +=
sizeof(map_size_t);
231 size_t table_cpy_size = (_i_hmap->capacity_mo + 1) *
sizeof(*(_i_hmap->nodes));
232 memcpy(_destination, _i_hmap->nodes, table_cpy_size);
233 _destination += table_cpy_size;
237 inline unsigned char * _hash_map_load(
struct _inner_hash_map_t *_i_hmap,
unsigned char *_source){
238 _i_hmap->capacity_mo = *((map_size_t *)_source);
239 _source +=
sizeof(map_size_t);
240 size_t table_cpy_size = (_i_hmap->capacity_mo + 1) *
sizeof(*(_i_hmap->nodes));
241 _i_hmap->nodes = rsalloc(table_cpy_size);
242 memcpy(_i_hmap->nodes, _source, table_cpy_size);
243 _source += table_cpy_size;
Dynamic Memory Logger and Restorer (DyMeLoR)
This header implements a simple hash map data structure.