Blame src/khash.h

Packit ae9e2a
/* The MIT License
Packit ae9e2a
Packit ae9e2a
   Copyright (c) 2008, 2009, 2011 by Attractive Chaos <attractor@live.co.uk>
Packit ae9e2a
Packit ae9e2a
   Permission is hereby granted, free of charge, to any person obtaining
Packit ae9e2a
   a copy of this software and associated documentation files (the
Packit ae9e2a
   "Software"), to deal in the Software without restriction, including
Packit ae9e2a
   without limitation the rights to use, copy, modify, merge, publish,
Packit ae9e2a
   distribute, sublicense, and/or sell copies of the Software, and to
Packit ae9e2a
   permit persons to whom the Software is furnished to do so, subject to
Packit ae9e2a
   the following conditions:
Packit ae9e2a
Packit ae9e2a
   The above copyright notice and this permission notice shall be
Packit ae9e2a
   included in all copies or substantial portions of the Software.
Packit ae9e2a
Packit ae9e2a
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit ae9e2a
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit ae9e2a
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit ae9e2a
   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit ae9e2a
   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit ae9e2a
   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit ae9e2a
   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit ae9e2a
   SOFTWARE.
Packit ae9e2a
*/
Packit ae9e2a
Packit ae9e2a
/*
Packit ae9e2a
  An example:
Packit ae9e2a
Packit ae9e2a
#include "khash.h"
Packit ae9e2a
KHASH_MAP_INIT_INT(32, char)
Packit ae9e2a
int main() {
Packit ae9e2a
	int ret, is_missing;
Packit ae9e2a
	khiter_t k;
Packit ae9e2a
	khash_t(32) *h = kh_init(32);
Packit ae9e2a
	k = kh_put(32, h, 5, &ret;;
Packit ae9e2a
	kh_value(h, k) = 10;
Packit ae9e2a
	k = kh_get(32, h, 10);
Packit ae9e2a
	is_missing = (k == kh_end(h));
Packit ae9e2a
	k = kh_get(32, h, 5);
Packit ae9e2a
	kh_del(32, h, k);
Packit ae9e2a
	for (k = kh_begin(h); k != kh_end(h); ++k)
Packit ae9e2a
		if (kh_exist(h, k)) kh_value(h, k) = 1;
Packit ae9e2a
	kh_destroy(32, h);
Packit ae9e2a
	return 0;
Packit ae9e2a
}
Packit ae9e2a
*/
Packit ae9e2a
Packit ae9e2a
/*
Packit ae9e2a
  2013-05-02 (0.2.8):
Packit ae9e2a
Packit ae9e2a
	* Use quadratic probing. When the capacity is power of 2, stepping function
Packit ae9e2a
	  i*(i+1)/2 guarantees to traverse each bucket. It is better than double
Packit ae9e2a
	  hashing on cache performance and is more robust than linear probing.
Packit ae9e2a
Packit ae9e2a
	  In theory, double hashing should be more robust than quadratic probing.
Packit ae9e2a
	  However, my implementation is probably not for large hash tables, because
Packit ae9e2a
	  the second hash function is closely tied to the first hash function,
Packit ae9e2a
	  which reduce the effectiveness of double hashing.
Packit ae9e2a
Packit ae9e2a
	Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php
Packit ae9e2a
Packit ae9e2a
  2011-12-29 (0.2.7):
Packit ae9e2a
Packit ae9e2a
    * Minor code clean up; no actual effect.
Packit ae9e2a
Packit ae9e2a
  2011-09-16 (0.2.6):
Packit ae9e2a
Packit ae9e2a
	* The capacity is a power of 2. This seems to dramatically improve the
Packit ae9e2a
	  speed for simple keys. Thank Zilong Tan for the suggestion. Reference:
Packit ae9e2a
Packit ae9e2a
	   - http://code.google.com/p/ulib/
Packit ae9e2a
	   - http://nothings.org/computer/judy/
Packit ae9e2a
Packit ae9e2a
	* Allow to optionally use linear probing which usually has better
Packit ae9e2a
	  performance for random input. Double hashing is still the default as it
Packit ae9e2a
	  is more robust to certain non-random input.
Packit ae9e2a
Packit ae9e2a
	* Added Wang's integer hash function (not used by default). This hash
Packit ae9e2a
	  function is more robust to certain non-random input.
Packit ae9e2a
Packit ae9e2a
  2011-02-14 (0.2.5):
Packit ae9e2a
Packit ae9e2a
    * Allow to declare global functions.
Packit ae9e2a
Packit ae9e2a
  2009-09-26 (0.2.4):
Packit ae9e2a
Packit ae9e2a
    * Improve portability
Packit ae9e2a
Packit ae9e2a
  2008-09-19 (0.2.3):
Packit ae9e2a
Packit ae9e2a
	* Corrected the example
Packit ae9e2a
	* Improved interfaces
Packit ae9e2a
Packit ae9e2a
  2008-09-11 (0.2.2):
Packit ae9e2a
Packit ae9e2a
	* Improved speed a little in kh_put()
Packit ae9e2a
Packit ae9e2a
  2008-09-10 (0.2.1):
Packit ae9e2a
Packit ae9e2a
	* Added kh_clear()
Packit ae9e2a
	* Fixed a compiling error
Packit ae9e2a
Packit ae9e2a
  2008-09-02 (0.2.0):
Packit ae9e2a
Packit ae9e2a
	* Changed to token concatenation which increases flexibility.
Packit ae9e2a
Packit ae9e2a
  2008-08-31 (0.1.2):
Packit ae9e2a
Packit ae9e2a
	* Fixed a bug in kh_get(), which has not been tested previously.
Packit ae9e2a
Packit ae9e2a
  2008-08-31 (0.1.1):
Packit ae9e2a
Packit ae9e2a
	* Added destructor
Packit ae9e2a
*/
Packit ae9e2a
Packit ae9e2a
Packit ae9e2a
#ifndef __AC_KHASH_H
Packit ae9e2a
#define __AC_KHASH_H
Packit ae9e2a
Packit ae9e2a
/*!
Packit ae9e2a
  @header
Packit ae9e2a
Packit ae9e2a
  Generic hash table library.
Packit ae9e2a
 */
Packit ae9e2a
Packit ae9e2a
#define AC_VERSION_KHASH_H "0.2.8"
Packit ae9e2a
Packit ae9e2a
#include <stdlib.h>
Packit ae9e2a
#include <string.h>
Packit ae9e2a
#include <limits.h>
Packit ae9e2a
Packit ae9e2a
/* compiler specific configuration */
Packit ae9e2a
Packit ae9e2a
#if UINT_MAX == 0xffffffffu
Packit ae9e2a
typedef unsigned int khint32_t;
Packit ae9e2a
#elif ULONG_MAX == 0xffffffffu
Packit ae9e2a
typedef unsigned long khint32_t;
Packit ae9e2a
#endif
Packit ae9e2a
Packit ae9e2a
#if ULONG_MAX == ULLONG_MAX
Packit ae9e2a
typedef unsigned long khint64_t;
Packit ae9e2a
#else
Packit ae9e2a
typedef unsigned long long khint64_t;
Packit ae9e2a
#endif
Packit ae9e2a
Packit ae9e2a
#ifndef kh_inline
Packit ae9e2a
#ifdef _MSC_VER
Packit ae9e2a
#define kh_inline __inline
Packit ae9e2a
#else
Packit ae9e2a
#define kh_inline inline
Packit ae9e2a
#endif
Packit ae9e2a
#endif /* kh_inline */
Packit ae9e2a
Packit ae9e2a
typedef khint32_t khint_t;
Packit ae9e2a
typedef khint_t khiter_t;
Packit ae9e2a
Packit ae9e2a
#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
Packit ae9e2a
#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1)
Packit ae9e2a
#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3)
Packit ae9e2a
#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1)))
Packit ae9e2a
#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1)))
Packit ae9e2a
#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1)))
Packit ae9e2a
#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1))
Packit ae9e2a
Packit ae9e2a
#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4)
Packit ae9e2a
Packit ae9e2a
#ifndef kroundup32
Packit ae9e2a
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
Packit ae9e2a
#endif
Packit ae9e2a
Packit ae9e2a
#ifndef kcalloc
Packit ae9e2a
#define kcalloc(N,Z) calloc(N,Z)
Packit ae9e2a
#endif
Packit ae9e2a
#ifndef kmalloc
Packit ae9e2a
#define kmalloc(Z) malloc(Z)
Packit ae9e2a
#endif
Packit ae9e2a
#ifndef krealloc
Packit ae9e2a
#define krealloc(P,Z) realloc(P,Z)
Packit ae9e2a
#endif
Packit ae9e2a
#ifndef kreallocarray
Packit ae9e2a
#define kreallocarray(P,N,Z) ((SIZE_MAX - N < Z) ? NULL : krealloc(P, (N*Z)))
Packit ae9e2a
#endif
Packit ae9e2a
#ifndef kfree
Packit ae9e2a
#define kfree(P) free(P)
Packit ae9e2a
#endif
Packit ae9e2a
Packit ae9e2a
static const double __ac_HASH_UPPER = 0.77;
Packit ae9e2a
Packit ae9e2a
#define __KHASH_TYPE(name, khkey_t, khval_t) \
Packit ae9e2a
	typedef struct kh_##name##_s { \
Packit ae9e2a
		khint_t n_buckets, size, n_occupied, upper_bound; \
Packit ae9e2a
		khint32_t *flags; \
Packit ae9e2a
		khkey_t *keys; \
Packit ae9e2a
		khval_t *vals; \
Packit ae9e2a
	} kh_##name##_t;
Packit ae9e2a
Packit ae9e2a
#define __KHASH_PROTOTYPES(name, khkey_t, khval_t)	 					\
Packit ae9e2a
	extern kh_##name##_t *kh_init_##name(void);							\
Packit ae9e2a
	extern void kh_destroy_##name(kh_##name##_t *h);					\
Packit ae9e2a
	extern void kh_clear_##name(kh_##name##_t *h);						\
Packit ae9e2a
	extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); 	\
Packit ae9e2a
	extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \
Packit ae9e2a
	extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \
Packit ae9e2a
	extern void kh_del_##name(kh_##name##_t *h, khint_t x);
Packit ae9e2a
Packit ae9e2a
#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
Packit ae9e2a
	SCOPE kh_##name##_t *kh_init_##name(void) {							\
Packit ae9e2a
		return (kh_##name##_t*)kcalloc(1, sizeof(kh_##name##_t));		\
Packit ae9e2a
	}																	\
Packit ae9e2a
	SCOPE void kh_destroy_##name(kh_##name##_t *h)						\
Packit ae9e2a
	{																	\
Packit ae9e2a
		if (h) {														\
Packit ae9e2a
			kfree((void *)h->keys); kfree(h->flags);					\
Packit ae9e2a
			kfree((void *)h->vals);										\
Packit ae9e2a
			kfree(h);													\
Packit ae9e2a
		}																\
Packit ae9e2a
	}																	\
Packit ae9e2a
	SCOPE void kh_clear_##name(kh_##name##_t *h)						\
Packit ae9e2a
	{																	\
Packit ae9e2a
		if (h && h->flags) {											\
Packit ae9e2a
			memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \
Packit ae9e2a
			h->size = h->n_occupied = 0;								\
Packit ae9e2a
		}																\
Packit ae9e2a
	}																	\
Packit ae9e2a
	SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) 	\
Packit ae9e2a
	{																	\
Packit ae9e2a
		if (h->n_buckets) {												\
Packit ae9e2a
			khint_t k, i, last, mask, step = 0; \
Packit ae9e2a
			mask = h->n_buckets - 1;									\
Packit ae9e2a
			k = __hash_func(key); i = k & mask;							\
Packit ae9e2a
			last = i; \
Packit ae9e2a
			while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
Packit ae9e2a
				i = (i + (++step)) & mask; \
Packit ae9e2a
				if (i == last) return h->n_buckets;						\
Packit ae9e2a
			}															\
Packit ae9e2a
			return __ac_iseither(h->flags, i)? h->n_buckets : i;		\
Packit ae9e2a
		} else return 0;												\
Packit ae9e2a
	}																	\
Packit ae9e2a
	SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
Packit ae9e2a
	{ /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \
Packit ae9e2a
		khint32_t *new_flags = 0;										\
Packit ae9e2a
		khint_t j = 1;													\
Packit ae9e2a
		{																\
Packit ae9e2a
			kroundup32(new_n_buckets); 									\
Packit ae9e2a
			if (new_n_buckets < 4) new_n_buckets = 4;					\
Packit ae9e2a
			if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0;	/* requested size is too small */ \
Packit ae9e2a
			else { /* hash table size to be changed (shrink or expand); rehash */ \
Packit ae9e2a
				new_flags = (khint32_t*)kreallocarray(NULL, __ac_fsize(new_n_buckets), sizeof(khint32_t)); \
Packit ae9e2a
				if (!new_flags) return -1;								\
Packit ae9e2a
				memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
Packit ae9e2a
				if (h->n_buckets < new_n_buckets) {	/* expand */		\
Packit ae9e2a
					khkey_t *new_keys = (khkey_t*)kreallocarray((void *)h->keys, new_n_buckets, sizeof(khkey_t)); \
Packit ae9e2a
					if (!new_keys) { kfree(new_flags); return -1; }		\
Packit ae9e2a
					h->keys = new_keys;									\
Packit ae9e2a
					if (kh_is_map) {									\
Packit ae9e2a
						khval_t *new_vals = (khval_t*)kreallocarray((void *)h->vals, new_n_buckets, sizeof(khval_t)); \
Packit ae9e2a
						if (!new_vals) { kfree(new_flags); return -1; }	\
Packit ae9e2a
						h->vals = new_vals;								\
Packit ae9e2a
					}													\
Packit ae9e2a
				} /* otherwise shrink */								\
Packit ae9e2a
			}															\
Packit ae9e2a
		}																\
Packit ae9e2a
		if (j) { /* rehashing is needed */								\
Packit ae9e2a
			for (j = 0; j != h->n_buckets; ++j) {						\
Packit ae9e2a
				if (__ac_iseither(h->flags, j) == 0) {					\
Packit ae9e2a
					khkey_t key = h->keys[j];							\
Packit ae9e2a
					khval_t val;										\
Packit ae9e2a
					khint_t new_mask;									\
Packit ae9e2a
					new_mask = new_n_buckets - 1; 						\
Packit ae9e2a
					if (kh_is_map) val = h->vals[j];					\
Packit ae9e2a
					__ac_set_isdel_true(h->flags, j);					\
Packit ae9e2a
					while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \
Packit ae9e2a
						khint_t k, i, step = 0; \
Packit ae9e2a
						k = __hash_func(key);							\
Packit ae9e2a
						i = k & new_mask;								\
Packit ae9e2a
						while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \
Packit ae9e2a
						__ac_set_isempty_false(new_flags, i);			\
Packit ae9e2a
						if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \
Packit ae9e2a
							{ khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \
Packit ae9e2a
							if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \
Packit ae9e2a
							__ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \
Packit ae9e2a
						} else { /* write the element and jump out of the loop */ \
Packit ae9e2a
							h->keys[i] = key;							\
Packit ae9e2a
							if (kh_is_map) h->vals[i] = val;			\
Packit ae9e2a
							break;										\
Packit ae9e2a
						}												\
Packit ae9e2a
					}													\
Packit ae9e2a
				}														\
Packit ae9e2a
			}															\
Packit ae9e2a
			if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \
Packit ae9e2a
				h->keys = (khkey_t*)kreallocarray((void *)h->keys, new_n_buckets, sizeof(khkey_t)); \
Packit ae9e2a
				if (kh_is_map) h->vals = (khval_t*)kreallocarray((void *)h->vals, new_n_buckets, sizeof(khval_t)); \
Packit ae9e2a
			}															\
Packit ae9e2a
			kfree(h->flags); /* free the working space */				\
Packit ae9e2a
			h->flags = new_flags;										\
Packit ae9e2a
			h->n_buckets = new_n_buckets;								\
Packit ae9e2a
			h->n_occupied = h->size;									\
Packit ae9e2a
			h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \
Packit ae9e2a
		}																\
Packit ae9e2a
		return 0;														\
Packit ae9e2a
	}																	\
Packit ae9e2a
	SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \
Packit ae9e2a
	{																	\
Packit ae9e2a
		khint_t x;														\
Packit ae9e2a
		if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \
Packit ae9e2a
			if (h->n_buckets > (h->size<<1)) {							\
Packit ae9e2a
				if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \
Packit ae9e2a
					*ret = -1; return h->n_buckets;						\
Packit ae9e2a
				}														\
Packit ae9e2a
			} else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \
Packit ae9e2a
				*ret = -1; return h->n_buckets;							\
Packit ae9e2a
			}															\
Packit ae9e2a
		} /* TODO: to implement automatically shrinking; resize() already support shrinking */ \
Packit ae9e2a
		{																\
Packit ae9e2a
			khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \
Packit ae9e2a
			x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \
Packit ae9e2a
			if (__ac_isempty(h->flags, i)) x = i; /* for speed up */	\
Packit ae9e2a
			else {														\
Packit ae9e2a
				last = i; \
Packit ae9e2a
				while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \
Packit ae9e2a
					if (__ac_isdel(h->flags, i)) site = i;				\
Packit ae9e2a
					i = (i + (++step)) & mask; \
Packit ae9e2a
					if (i == last) { x = site; break; }					\
Packit ae9e2a
				}														\
Packit ae9e2a
				if (x == h->n_buckets) {								\
Packit ae9e2a
					if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \
Packit ae9e2a
					else x = i;											\
Packit ae9e2a
				}														\
Packit ae9e2a
			}															\
Packit ae9e2a
		}																\
Packit ae9e2a
		if (__ac_isempty(h->flags, x)) { /* not present at all */		\
Packit ae9e2a
			h->keys[x] = key;											\
Packit ae9e2a
			__ac_set_isboth_false(h->flags, x);							\
Packit ae9e2a
			++h->size; ++h->n_occupied;									\
Packit ae9e2a
			*ret = 1;													\
Packit ae9e2a
		} else if (__ac_isdel(h->flags, x)) { /* deleted */				\
Packit ae9e2a
			h->keys[x] = key;											\
Packit ae9e2a
			__ac_set_isboth_false(h->flags, x);							\
Packit ae9e2a
			++h->size;													\
Packit ae9e2a
			*ret = 2;													\
Packit ae9e2a
		} else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \
Packit ae9e2a
		return x;														\
Packit ae9e2a
	}																	\
Packit ae9e2a
	SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x)				\
Packit ae9e2a
	{																	\
Packit ae9e2a
		if (x != h->n_buckets && !__ac_iseither(h->flags, x)) {			\
Packit ae9e2a
			__ac_set_isdel_true(h->flags, x);							\
Packit ae9e2a
			--h->size;													\
Packit ae9e2a
		}																\
Packit ae9e2a
	}
Packit ae9e2a
Packit ae9e2a
#define KHASH_DECLARE(name, khkey_t, khval_t)		 					\
Packit ae9e2a
	__KHASH_TYPE(name, khkey_t, khval_t) 								\
Packit ae9e2a
	__KHASH_PROTOTYPES(name, khkey_t, khval_t)
Packit ae9e2a
Packit ae9e2a
#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
Packit ae9e2a
	__KHASH_TYPE(name, khkey_t, khval_t) 								\
Packit ae9e2a
	__KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
Packit ae9e2a
Packit ae9e2a
#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \
Packit ae9e2a
	KHASH_INIT2(name, static kh_inline, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal)
Packit ae9e2a
Packit ae9e2a
/* --- BEGIN OF HASH FUNCTIONS --- */
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Integer hash function
Packit ae9e2a
  @param  key   The integer [khint32_t]
Packit ae9e2a
  @return       The hash value [khint_t]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_int_hash_func(key) (khint32_t)(key)
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Integer comparison function
Packit ae9e2a
 */
Packit ae9e2a
#define kh_int_hash_equal(a, b) ((a) == (b))
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     64-bit integer hash function
Packit ae9e2a
  @param  key   The integer [khint64_t]
Packit ae9e2a
  @return       The hash value [khint_t]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11)
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     64-bit integer comparison function
Packit ae9e2a
 */
Packit ae9e2a
#define kh_int64_hash_equal(a, b) ((a) == (b))
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     const char* hash function
Packit ae9e2a
  @param  s     Pointer to a null terminated string
Packit ae9e2a
  @return       The hash value
Packit ae9e2a
 */
Packit ae9e2a
static kh_inline khint_t __ac_X31_hash_string(const char *s)
Packit ae9e2a
{
Packit ae9e2a
	khint_t h = (khint_t)*s;
Packit ae9e2a
	if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s;
Packit ae9e2a
	return h;
Packit ae9e2a
}
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Another interface to const char* hash function
Packit ae9e2a
  @param  key   Pointer to a null terminated string [const char*]
Packit ae9e2a
  @return       The hash value [khint_t]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_str_hash_func(key) __ac_X31_hash_string(key)
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Const char* comparison function
Packit ae9e2a
 */
Packit ae9e2a
#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0)
Packit ae9e2a
Packit ae9e2a
static kh_inline khint_t __ac_Wang_hash(khint_t key)
Packit ae9e2a
{
Packit ae9e2a
    key += ~(key << 15);
Packit ae9e2a
    key ^=  (key >> 10);
Packit ae9e2a
    key +=  (key << 3);
Packit ae9e2a
    key ^=  (key >> 6);
Packit ae9e2a
    key += ~(key << 11);
Packit ae9e2a
    key ^=  (key >> 16);
Packit ae9e2a
    return key;
Packit ae9e2a
}
Packit ae9e2a
#define kh_int_hash_func2(k) __ac_Wang_hash((khint_t)key)
Packit ae9e2a
Packit ae9e2a
/* --- END OF HASH FUNCTIONS --- */
Packit ae9e2a
Packit ae9e2a
/* Other convenient macros... */
Packit ae9e2a
Packit ae9e2a
/*!
Packit ae9e2a
  @abstract Type of the hash table.
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
 */
Packit ae9e2a
#define khash_t(name) kh_##name##_t
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Initiate a hash table.
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
  @return       Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_init(name) kh_init_##name()
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Destroy a hash table.
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_destroy(name, h) kh_destroy_##name(h)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Reset a hash table without deallocating memory.
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_clear(name, h) kh_clear_##name(h)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Resize a hash table.
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @param  s     New size [khint_t]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_resize(name, h, s) kh_resize_##name(h, s)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Insert a key to the hash table.
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @param  k     Key [type of keys]
Packit ae9e2a
  @param  r     Extra return code: -1 if the operation failed;
Packit ae9e2a
                0 if the key is present in the hash table;
Packit ae9e2a
                1 if the bucket is empty (never used); 2 if the element in
Packit ae9e2a
				the bucket has been deleted [int*]
Packit ae9e2a
  @return       Iterator to the inserted element [khint_t]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_put(name, h, k, r) kh_put_##name(h, k, r)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Retrieve a key from the hash table.
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @param  k     Key [type of keys]
Packit ae9e2a
  @return       Iterator to the found element, or kh_end(h) if the element is absent [khint_t]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_get(name, h, k) kh_get_##name(h, k)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Remove a key from the hash table.
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @param  k     Iterator to the element to be deleted [khint_t]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_del(name, h, k) kh_del_##name(h, k)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Test whether a bucket contains data.
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @param  x     Iterator to the bucket [khint_t]
Packit ae9e2a
  @return       1 if containing data; 0 otherwise [int]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x)))
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Get key given an iterator
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @param  x     Iterator to the bucket [khint_t]
Packit ae9e2a
  @return       Key [type of keys]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_key(h, x) ((h)->keys[x])
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Get value given an iterator
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @param  x     Iterator to the bucket [khint_t]
Packit ae9e2a
  @return       Value [type of values]
Packit ae9e2a
  @discussion   For hash sets, calling this results in segfault.
Packit ae9e2a
 */
Packit ae9e2a
#define kh_val(h, x) ((h)->vals[x])
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Alias of kh_val()
Packit ae9e2a
 */
Packit ae9e2a
#define kh_value(h, x) ((h)->vals[x])
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Get the start iterator
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @return       The start iterator [khint_t]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_begin(h) (khint_t)(0)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Get the end iterator
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @return       The end iterator [khint_t]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_end(h) ((h)->n_buckets)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Get the number of elements in the hash table
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @return       Number of elements in the hash table [khint_t]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_size(h) ((h)->size)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Get the number of buckets in the hash table
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @return       Number of buckets in the hash table [khint_t]
Packit ae9e2a
 */
Packit ae9e2a
#define kh_n_buckets(h) ((h)->n_buckets)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Iterate over the entries in the hash table
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @param  kvar  Variable to which key will be assigned
Packit ae9e2a
  @param  vvar  Variable to which value will be assigned
Packit ae9e2a
  @param  code  Block of code to execute
Packit ae9e2a
 */
Packit ae9e2a
#define kh_foreach(h, kvar, vvar, code) { khint_t __i;		\
Packit ae9e2a
	for (__i = kh_begin(h); __i != kh_end(h); ++__i) {		\
Packit ae9e2a
		if (!kh_exist(h,__i)) continue;						\
Packit ae9e2a
		(kvar) = kh_key(h,__i);								\
Packit ae9e2a
		(vvar) = kh_val(h,__i);								\
Packit ae9e2a
		code;												\
Packit ae9e2a
	} }
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Iterate over the values in the hash table
Packit ae9e2a
  @param  h     Pointer to the hash table [khash_t(name)*]
Packit ae9e2a
  @param  vvar  Variable to which value will be assigned
Packit ae9e2a
  @param  code  Block of code to execute
Packit ae9e2a
 */
Packit ae9e2a
#define kh_foreach_value(h, vvar, code) { khint_t __i;		\
Packit ae9e2a
	for (__i = kh_begin(h); __i != kh_end(h); ++__i) {		\
Packit ae9e2a
		if (!kh_exist(h,__i)) continue;						\
Packit ae9e2a
		(vvar) = kh_val(h,__i);								\
Packit ae9e2a
		code;												\
Packit ae9e2a
	} }
Packit ae9e2a
Packit ae9e2a
/* More conenient interfaces */
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Instantiate a hash set containing integer keys
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
 */
Packit ae9e2a
#define KHASH_SET_INIT_INT(name)										\
Packit ae9e2a
	KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Instantiate a hash map containing integer keys
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
  @param  khval_t  Type of values [type]
Packit ae9e2a
 */
Packit ae9e2a
#define KHASH_MAP_INIT_INT(name, khval_t)								\
Packit ae9e2a
	KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Instantiate a hash map containing 64-bit integer keys
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
 */
Packit ae9e2a
#define KHASH_SET_INIT_INT64(name)										\
Packit ae9e2a
	KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Instantiate a hash map containing 64-bit integer keys
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
  @param  khval_t  Type of values [type]
Packit ae9e2a
 */
Packit ae9e2a
#define KHASH_MAP_INIT_INT64(name, khval_t)								\
Packit ae9e2a
	KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal)
Packit ae9e2a
Packit ae9e2a
typedef const char *kh_cstr_t;
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Instantiate a hash map containing const char* keys
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
 */
Packit ae9e2a
#define KHASH_SET_INIT_STR(name)										\
Packit ae9e2a
	KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal)
Packit ae9e2a
Packit ae9e2a
/*! @function
Packit ae9e2a
  @abstract     Instantiate a hash map containing const char* keys
Packit ae9e2a
  @param  name  Name of the hash table [symbol]
Packit ae9e2a
  @param  khval_t  Type of values [type]
Packit ae9e2a
 */
Packit ae9e2a
#define KHASH_MAP_INIT_STR(name, khval_t)								\
Packit ae9e2a
	KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal)
Packit ae9e2a
Packit ae9e2a
#endif /* __AC_KHASH_H */