3 Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk>
5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sublicense, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
13 The above copyright notice and this permission notice shall be
14 included in all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 KHASH_MAP_INIT_INT(32, char)
34 khash_t(32) *h = kh_init(32);
35 k = kh_put(32, h, 5, &ret);
36 if (!ret) kh_del(32, h, k);
38 k = kh_get(32, h, 10);
39 is_missing = (k == kh_end(h));
42 for (k = kh_begin(h); k != kh_end(h); ++k)
43 if (kh_exist(h, k)) kh_value(h, k) = 1;
52 * Allow to declare global functions.
60 * Corrected the example
65 * Improved speed a little in kh_put()
70 * Fixed a compiling error
74 * Changed to token concatenation which increases flexibility.
78 * Fixed a bug in kh_get(), which has not been tested previously.
92 Generic hash table library.
97 #define AC_VERSION_KHASH_H "0.2.5"
103 /* compipler specific configuration */
105 #if UINT_MAX == 0xffffffffu
106 typedef unsigned int khint32_t;
107 #elif ULONG_MAX == 0xffffffffu
108 typedef unsigned long khint32_t;
111 #if ULONG_MAX == ULLONG_MAX
112 typedef unsigned long khint64_t;
114 typedef unsigned long long khint64_t;
118 #define inline __inline
121 typedef khint32_t khint_t;
122 typedef khint_t khiter_t;
124 #define __ac_HASH_PRIME_SIZE 32
125 static const khint32_t __ac_prime_list[__ac_HASH_PRIME_SIZE] =
127 0ul, 3ul, 11ul, 23ul, 53ul,
128 97ul, 193ul, 389ul, 769ul, 1543ul,
129 3079ul, 6151ul, 12289ul, 24593ul, 49157ul,
130 98317ul, 196613ul, 393241ul, 786433ul, 1572869ul,
131 3145739ul, 6291469ul, 12582917ul, 25165843ul, 50331653ul,
132 100663319ul, 201326611ul, 402653189ul, 805306457ul, 1610612741ul,
133 3221225473ul, 4294967291ul
136 #define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
137 #define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1)
138 #define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3)
139 #define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1)))
140 #define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1)))
141 #define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1)))
142 #define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1))
144 static const double __ac_HASH_UPPER = 0.77;
146 #define KHASH_DECLARE(name, khkey_t, khval_t) \
148 khint_t n_buckets, size, n_occupied, upper_bound; \
153 extern kh_##name##_t *kh_init_##name(); \
154 extern void kh_destroy_##name(kh_##name##_t *h); \
155 extern void kh_clear_##name(kh_##name##_t *h); \
156 extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \
157 extern void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
158 extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
159 extern void kh_del_##name(kh_##name##_t *h, khint_t x);
161 #define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
163 khint_t n_buckets, size, n_occupied, upper_bound; \
168 SCOPE kh_##name##_t *kh_init_##name() { \
169 return (kh_##name##_t*)calloc(1, sizeof(kh_##name##_t)); \
171 SCOPE void kh_destroy_##name(kh_##name##_t *h) \
174 free(h->keys); free(h->flags); \
179 SCOPE void kh_clear_##name(kh_##name##_t *h) \
181 if (h && h->flags) { \
182 memset(h->flags, 0xaa, ((h->n_buckets>>4) + 1) * sizeof(khint32_t)); \
183 h->size = h->n_occupied = 0; \
186 SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \
188 if (h->n_buckets) { \
189 khint_t inc, k, i, last; \
190 k = __hash_func(key); i = k % h->n_buckets; \
191 inc = 1 + k % (h->n_buckets - 1); last = i; \
192 while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
193 if (i + inc >= h->n_buckets) i = i + inc - h->n_buckets; \
195 if (i == last) return h->n_buckets; \
197 return __ac_iseither(h->flags, i)? h->n_buckets : i; \
200 SCOPE void kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
202 khint32_t *new_flags = 0; \
205 khint_t t = __ac_HASH_PRIME_SIZE - 1; \
206 while (__ac_prime_list[t] > new_n_buckets) --t; \
207 new_n_buckets = __ac_prime_list[t+1]; \
208 if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; \
210 new_flags = (khint32_t*)malloc(((new_n_buckets>>4) + 1) * sizeof(khint32_t)); \
211 memset(new_flags, 0xaa, ((new_n_buckets>>4) + 1) * sizeof(khint32_t)); \
212 if (h->n_buckets < new_n_buckets) { \
213 h->keys = (khkey_t*)realloc(h->keys, new_n_buckets * sizeof(khkey_t)); \
215 h->vals = (khval_t*)realloc(h->vals, new_n_buckets * sizeof(khval_t)); \
220 for (j = 0; j != h->n_buckets; ++j) { \
221 if (__ac_iseither(h->flags, j) == 0) { \
222 khkey_t key = h->keys[j]; \
224 if (kh_is_map) val = h->vals[j]; \
225 __ac_set_isdel_true(h->flags, j); \
228 k = __hash_func(key); \
229 i = k % new_n_buckets; \
230 inc = 1 + k % (new_n_buckets - 1); \
231 while (!__ac_isempty(new_flags, i)) { \
232 if (i + inc >= new_n_buckets) i = i + inc - new_n_buckets; \
235 __ac_set_isempty_false(new_flags, i); \
236 if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { \
237 { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \
238 if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \
239 __ac_set_isdel_true(h->flags, i); \
242 if (kh_is_map) h->vals[i] = val; \
248 if (h->n_buckets > new_n_buckets) { \
249 h->keys = (khkey_t*)realloc(h->keys, new_n_buckets * sizeof(khkey_t)); \
251 h->vals = (khval_t*)realloc(h->vals, new_n_buckets * sizeof(khval_t)); \
254 h->flags = new_flags; \
255 h->n_buckets = new_n_buckets; \
256 h->n_occupied = h->size; \
257 h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \
260 SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \
263 if (h->n_occupied >= h->upper_bound) { \
264 if (h->n_buckets > (h->size<<1)) kh_resize_##name(h, h->n_buckets - 1); \
265 else kh_resize_##name(h, h->n_buckets + 1); \
268 khint_t inc, k, i, site, last; \
269 x = site = h->n_buckets; k = __hash_func(key); i = k % h->n_buckets; \
270 if (__ac_isempty(h->flags, i)) x = i; \
272 inc = 1 + k % (h->n_buckets - 1); last = i; \
273 while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
274 if (__ac_isdel(h->flags, i)) site = i; \
275 if (i + inc >= h->n_buckets) i = i + inc - h->n_buckets; \
277 if (i == last) { x = site; break; } \
279 if (x == h->n_buckets) { \
280 if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \
285 if (__ac_isempty(h->flags, x)) { \
287 __ac_set_isboth_false(h->flags, x); \
288 ++h->size; ++h->n_occupied; \
290 } else if (__ac_isdel(h->flags, x)) { \
292 __ac_set_isboth_false(h->flags, x); \
298 SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \
300 if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \
301 __ac_set_isdel_true(h->flags, x); \
306 #define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
307 KHASH_INIT2(name, static inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
309 /* --- BEGIN OF HASH FUNCTIONS --- */
312 @abstract Integer hash function
313 @param key The integer [khint32_t]
314 @return The hash value [khint_t]
316 #define kh_int_hash_func(key) (khint32_t)(key)
318 @abstract Integer comparison function
320 #define kh_int_hash_equal(a, b) ((a) == (b))
322 @abstract 64-bit integer hash function
323 @param key The integer [khint64_t]
324 @return The hash value [khint_t]
326 #define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11)
328 @abstract 64-bit integer comparison function
330 #define kh_int64_hash_equal(a, b) ((a) == (b))
332 @abstract const char* hash function
333 @param s Pointer to a null terminated string
334 @return The hash value
336 static inline khint_t __ac_X31_hash_string(const char *s)
339 if (h) for (++s ; *s; ++s) h = (h << 5) - h + *s;
343 @abstract Another interface to const char* hash function
344 @param key Pointer to a null terminated string [const char*]
345 @return The hash value [khint_t]
347 #define kh_str_hash_func(key) __ac_X31_hash_string(key)
349 @abstract Const char* comparison function
351 #define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
353 /* --- END OF HASH FUNCTIONS --- */
355 /* Other necessary macros... */
358 @abstract Type of the hash table.
359 @param name Name of the hash table [symbol]
361 #define khash_t(name) kh_##name##_t
364 @abstract Initiate a hash table.
365 @param name Name of the hash table [symbol]
366 @return Pointer to the hash table [khash_t(name)*]
368 #define kh_init(name) kh_init_##name()
371 @abstract Destroy a hash table.
372 @param name Name of the hash table [symbol]
373 @param h Pointer to the hash table [khash_t(name)*]
375 #define kh_destroy(name, h) kh_destroy_##name(h)
378 @abstract Reset a hash table without deallocating memory.
379 @param name Name of the hash table [symbol]
380 @param h Pointer to the hash table [khash_t(name)*]
382 #define kh_clear(name, h) kh_clear_##name(h)
385 @abstract Resize a hash table.
386 @param name Name of the hash table [symbol]
387 @param h Pointer to the hash table [khash_t(name)*]
388 @param s New size [khint_t]
390 #define kh_resize(name, h, s) kh_resize_##name(h, s)
393 @abstract Insert a key to the hash table.
394 @param name Name of the hash table [symbol]
395 @param h Pointer to the hash table [khash_t(name)*]
396 @param k Key [type of keys]
397 @param r Extra return code: 0 if the key is present in the hash table;
398 1 if the bucket is empty (never used); 2 if the element in
399 the bucket has been deleted [int*]
400 @return Iterator to the inserted element [khint_t]
402 #define kh_put(name, h, k, r) kh_put_##name(h, k, r)
405 @abstract Retrieve a key from the hash table.
406 @param name Name of the hash table [symbol]
407 @param h Pointer to the hash table [khash_t(name)*]
408 @param k Key [type of keys]
409 @return Iterator to the found element, or kh_end(h) is the element is absent [khint_t]
411 #define kh_get(name, h, k) kh_get_##name(h, k)
414 @abstract Remove a key from the hash table.
415 @param name Name of the hash table [symbol]
416 @param h Pointer to the hash table [khash_t(name)*]
417 @param k Iterator to the element to be deleted [khint_t]
419 #define kh_del(name, h, k) kh_del_##name(h, k)
423 @abstract Test whether a bucket contains data.
424 @param h Pointer to the hash table [khash_t(name)*]
425 @param x Iterator to the bucket [khint_t]
426 @return 1 if containing data; 0 otherwise [int]
428 #define kh_exist(h, x) (!__ac_iseither((h)->flags, (x)))
431 @abstract Get key given an iterator
432 @param h Pointer to the hash table [khash_t(name)*]
433 @param x Iterator to the bucket [khint_t]
434 @return Key [type of keys]
436 #define kh_key(h, x) ((h)->keys[x])
439 @abstract Get value given an iterator
440 @param h Pointer to the hash table [khash_t(name)*]
441 @param x Iterator to the bucket [khint_t]
442 @return Value [type of values]
443 @discussion For hash sets, calling this results in segfault.
445 #define kh_val(h, x) ((h)->vals[x])
448 @abstract Alias of kh_val()
450 #define kh_value(h, x) ((h)->vals[x])
453 @abstract Get the start iterator
454 @param h Pointer to the hash table [khash_t(name)*]
455 @return The start iterator [khint_t]
457 #define kh_begin(h) (khint_t)(0)
460 @abstract Get the end iterator
461 @param h Pointer to the hash table [khash_t(name)*]
462 @return The end iterator [khint_t]
464 #define kh_end(h) ((h)->n_buckets)
467 @abstract Get the number of elements in the hash table
468 @param h Pointer to the hash table [khash_t(name)*]
469 @return Number of elements in the hash table [khint_t]
471 #define kh_size(h) ((h)->size)
474 @abstract Get the number of buckets in the hash table
475 @param h Pointer to the hash table [khash_t(name)*]
476 @return Number of buckets in the hash table [khint_t]
478 #define kh_n_buckets(h) ((h)->n_buckets)
480 /* More conenient interfaces */
483 @abstract Instantiate a hash set containing integer keys
484 @param name Name of the hash table [symbol]
486 #define KHASH_SET_INIT_INT(name) \
487 KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
490 @abstract Instantiate a hash map containing integer keys
491 @param name Name of the hash table [symbol]
492 @param khval_t Type of values [type]
494 #define KHASH_MAP_INIT_INT(name, khval_t) \
495 KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
498 @abstract Instantiate a hash map containing 64-bit integer keys
499 @param name Name of the hash table [symbol]
501 #define KHASH_SET_INIT_INT64(name) \
502 KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal)
505 @abstract Instantiate a hash map containing 64-bit integer keys
506 @param name Name of the hash table [symbol]
507 @param khval_t Type of values [type]
509 #define KHASH_MAP_INIT_INT64(name, khval_t) \
510 KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal)
512 typedef const char *kh_cstr_t;
514 @abstract Instantiate a hash map containing const char* keys
515 @param name Name of the hash table [symbol]
517 #define KHASH_SET_INIT_STR(name) \
518 KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
521 @abstract Instantiate a hash map containing const char* keys
522 @param name Name of the hash table [symbol]
523 @param khval_t Type of values [type]
525 #define KHASH_MAP_INIT_STR(name, khval_t) \
526 KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
528 #endif /* __AC_KHASH_H */