potion  0.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
khash.h
Go to the documentation of this file.
1 //
7 // Copyright (c) 2008, by Attractive Chaos <attractivechaos@aol.co.uk>
8 // (Released under the MIT license, see COPYING)
9 //
10 
11 #ifndef __AC_KHASH_H
12 #define __AC_KHASH_H
13 
14 #define AC_VERSION_KHASH_H "0.2.6p"
15 
16 #include <stdint.h>
17 #include <stdlib.h>
18 #include <string.h>
19 
20 typedef uint32_t khint_t;
21 typedef khint_t khiter_t;
22 
23 #define KHASH_FLAG(name, h, i) *(uint32_t *)(h->table + kh_flag_##name(i))
24 #define KHASH_KEY(name, h, i) *kh_key_##name(h, i)
25 #define KHASH_VAL(name, h, i) *kh_val_##name(h, i)
26 
27 #define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
28 #define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1)))
29 #define __kh_isempty(name, h, i) ((KHASH_FLAG(name, h, i)>>((i&0xfU)<<1))&2)
30 #define __kh_isdel(name, h, i) ((KHASH_FLAG(name, h, i)>>((i&0xfU)<<1))&1)
31 #define __kh_iseither(name, h, i) ((KHASH_FLAG(name, h, i)>>((i&0xfU)<<1))&3)
32 #define __kh_set_isdel_false(name, h, i) (KHASH_FLAG(name, h, i)&=~(1ul<<((i&0xfU)<<1)))
33 #define __kh_set_isempty_false(name, h, i) (KHASH_FLAG(name, h, i)&=~(2ul<<((i&0xfU)<<1)))
34 #define __kh_set_isboth_false(name, h, i) (KHASH_FLAG(name, h, i)&=~(3ul<<((i&0xfU)<<1)))
35 #define __kh_set_isdel_true(name, h, i) (KHASH_FLAG(name, h, i)|=1ul<<((i&0xfU)<<1))
36 
37 #define __ac_inc(k) ((k) | 1)
38 #define __ac_fsize(m) ((m) < 16? 1 : (m)>>4)
39 
40 static const double __kh_HASH_UPPER = 0.77;
41 
42 #define PN_TABLE_HEADER PN_SIZE n_buckets, size, n_occupied, upper_bound
43 
44 #define KHASH_INIT(name, kh_t, khkey_t, khval_t, khkey_t2, kh_is_map, __hash_func, __hash_equal, __hash_func2, __hash_equal2) \
45  static inline khint_t kh_pair_##name() { return (kh_is_map ? (sizeof(khkey_t) + sizeof(khval_t)) : sizeof(khkey_t)); } \
46  static inline khint_t kh_size_##name(khint_t n) { return (((n >> 4) + 1) * (sizeof(uint32_t))) + (n * kh_pair_##name()); } \
47  static inline khint_t kh_flag_##name(khint_t i) { return (i >> 4) * (sizeof(uint32_t) + ((sizeof(uint32_t) * 4) * kh_pair_##name())); } \
48  static inline khint_t kh_key_at_##name(khint_t i) { return (((i >> 4) + 1) * sizeof(uint32_t)) + (i * kh_pair_##name()); } \
49  static inline khint_t kh_val_at_##name(khint_t i) { return (((i >> 4) + 1) * sizeof(uint32_t)) + (i * kh_pair_##name()) + sizeof(khkey_t); } \
50  static inline khkey_t *kh_key_##name(kh_t *h, khint_t i) { return (khkey_t *)(h->table + kh_key_at_##name(i)); } \
51  static inline khval_t *kh_val_##name(kh_t *h, khint_t i) { return (khval_t *)(h->table + kh_val_at_##name(i)); } \
52  static inline void kh_clear_##name(Potion *P, kh_t *h) \
53  { \
54  if (h && h->n_buckets > 0) { \
55  /* memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(uint32_t));*/ \
56  int i = ((h->n_buckets) >> 4) + 1; \
57  while (i-- > 0) KHASH_FLAG(name, h, i) = 0xaaaaaaaa; \
58  h->size = h->n_occupied = 0; \
59  } \
60  } \
61  static inline khint_t kh_get_##name(Potion *P, kh_t *h, khkey_t2 key) \
62  { \
63  if (h->n_buckets) { \
64  khint_t inc, k, i, last, mask; \
65  mask = h->n_buckets - 1; \
66  k = __hash_func2(key); i = k & mask; \
67  inc = __ac_inc(k) & mask; last = i; \
68  while (!__kh_isempty(name, h, i) && (__kh_isdel(name, h, i) || !__hash_equal2(KHASH_KEY(name, h, i), key))) { \
69  i = (i + inc) & mask; \
70  if (i == last) return h->n_buckets; \
71  } \
72  return __kh_iseither(name, h, i)? h->n_buckets : i; \
73  } else return 0; \
74  } \
75  static inline kh_t *kh_resize_##name(Potion *P, kh_t *h, khint_t new_n_buckets) \
76  { \
77  vPN(Data) nft = 0; \
78  uint32_t *new_flags = 0; \
79  khint_t j = 1; \
80  { \
81  new_n_buckets = h->n_buckets? h->n_buckets<<1 : 4; \
82  if (h->size >= (khint_t)(new_n_buckets * __kh_HASH_UPPER + 0.5)) j = 0; \
83  else { \
84  nft = PN_DALLOC_N(uint32_t, __ac_fsize(new_n_buckets)); \
85  if (h->n_buckets < new_n_buckets) \
86  PN_REALLOC(h, PN_TUSER, kh_t, kh_size_##name(new_n_buckets)); \
87  new_flags = (uint32_t *)nft->data; \
88  memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(uint32_t)); \
89  } \
90  } \
91  if (j) { \
92  for (j = 0; j != h->n_buckets; ++j) { \
93  if (__kh_iseither(name, h, j) == 0) { \
94  khkey_t key = KHASH_KEY(name, h, j); \
95  khval_t val; \
96  if (kh_is_map) val = KHASH_VAL(name, h, j); \
97  __kh_set_isdel_true(name, h, j); \
98  while (1) { \
99  khint_t inc, k, i, new_mask; \
100  new_mask = new_n_buckets - 1; \
101  k = __hash_func(key); \
102  i = k & new_mask; \
103  inc = __ac_inc(k) & new_mask; \
104  while (!__ac_isempty(new_flags, i)) i = (i + inc) & new_mask; \
105  __ac_set_isempty_false(new_flags, i); \
106  if (i < h->n_buckets && __kh_iseither(name, h, i) == 0) { \
107  { khkey_t tmp = KHASH_KEY(name, h, i); KHASH_KEY(name, h, i) = key; key = tmp; } \
108  if (kh_is_map) { khval_t tmp = KHASH_VAL(name, h, i); KHASH_VAL(name, h, i) = val; val = tmp; } \
109  __kh_set_isdel_true(name, h, i); \
110  } else { \
111  KHASH_KEY(name, h, i) = key; \
112  if (kh_is_map) KHASH_VAL(name, h, i) = val; \
113  break; \
114  } \
115  } \
116  } \
117  } \
118  if (h->n_buckets > new_n_buckets) \
119  PN_REALLOC(h, PN_TUSER, kh_t, kh_size_##name(new_n_buckets)); \
120  j = (new_n_buckets >> 4) + 1; \
121  new_flags = (uint32_t *)nft->data; \
122  while (j-- > 0) KHASH_FLAG(name, h, j << 4) = new_flags[j]; \
123  h->n_buckets = new_n_buckets; \
124  h->n_occupied = h->size; \
125  h->upper_bound = (khint_t)(h->n_buckets * __kh_HASH_UPPER + 0.5); \
126  } \
127  return h; \
128  } \
129  static inline khint_t kh_put_##name(Potion *P, kh_t *h, khkey_t key, int *ret) \
130  { \
131  khint_t x; \
132  if (h->n_occupied >= h->upper_bound) { \
133  if (h->n_buckets > (h->size<<1)) h = kh_resize_##name(P, h, h->n_buckets - 1); \
134  else h = kh_resize_##name(P, h, h->n_buckets + 1); \
135  } \
136  { \
137  khint_t inc, k, i, site, last, mask = h->n_buckets - 1; \
138  x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \
139  if (__kh_isempty(name, h, i)) x = i; \
140  else { \
141  inc = __ac_inc(k) & mask; last = i; \
142  while (!__kh_isempty(name, h, i) && (__kh_isdel(name, h, i) || !__hash_equal(KHASH_KEY(name, h, i), key))) { \
143  if (__kh_isdel(name, h, i)) site = i; \
144  i = (i + inc) & mask; \
145  if (i == last) { x = site; break; } \
146  } \
147  if (x == h->n_buckets) { \
148  if (__kh_isempty(name, h, i) && site != h->n_buckets) x = site; \
149  else x = i; \
150  } \
151  } \
152  } \
153  if (__kh_isempty(name, h, x)) { \
154  KHASH_KEY(name, h, x) = key; \
155  __kh_set_isboth_false(name, h, x); \
156  ++h->size; ++h->n_occupied; \
157  *ret = 1; \
158  } else if (__kh_isdel(name, h, x)) { \
159  KHASH_KEY(name, h, x) = key; \
160  __kh_set_isboth_false(name, h, x); \
161  ++h->size; \
162  *ret = 2; \
163  } else *ret = 0; \
164  return x; \
165  } \
166  static inline void kh_del_##name(Potion *P, kh_t *h, khint_t x) \
167  { \
168  if (x != h->n_buckets && !__kh_iseither(name, h, x)) { \
169  __kh_set_isdel_true(name, h, x); \
170  --h->size; \
171  } \
172  }
173 
174 /* --- BEGIN OF HASH FUNCTIONS --- */
175 
176 #define kh_int_hash_func(key) (uint32_t)(key)
177 #define kh_int_hash_equal(a, b) (a == b)
178 #define kh_int64_hash_func(key) (uint32_t)((key)>>33^(key)^(key)<<11)
179 #define kh_int64_hash_equal(a, b) (a == b)
180 static inline khint_t __kh_X31_hash_string(const char *s)
181 {
182  khint_t h = *s;
183  if (h) for (++s ; *s; ++s) h = (h << 5) - h + *s;
184  return h;
185 }
186 static inline khint_t __luaS_hash_string(const char *s)
187 {
188  size_t len = strlen(s);
189  khint_t h = len;
190  size_t step = (len >> 5) + 1; /* limit amount of string to hash */
191  size_t l1;
192  for (l1 = len; l1 >= step; l1 -= step)
193  h = h ^ ((h << 5) + (h >> 2) + (unsigned char)s[l1 - 1]);
194  return h;
195 }
196 #define kh_pnstr_hash_func(key) __luaS_hash_string(PN_STR_PTR(key))
197 #define kh_pnstr_hash_equal(a, b) (strcmp(PN_STR_PTR(a), PN_STR_PTR(b)) == 0)
198 #define kh_str_hash_func(key) __luaS_hash_string(key)
199 #define kh_str_hash_equal(a, b) (strcmp(PN_STR_PTR(a), b) == 0)
200 #define kh_pn_hash_func(key) (uint32_t)PN_UNIQ(key)
201 #define kh_pn_hash_equal(a, b) (a == b)
202 
203 static inline khint_t __ac_Wang_hash(khint_t key)
204 {
205  key += ~(key << 15);
206  key ^= (key >> 10);
207  key += (key << 3);
208  key ^= (key >> 6);
209  key += ~(key << 11);
210  key ^= (key >> 16);
211  return key;
212 }
213 #define kh_int_hash_func2(k) __ac_Wang_hash((khint_t)key)
214 
215 /* --- END OF HASH FUNCTIONS --- */
216 
217 /* Other convenient macros... */
218 
219 #define kh_clear(name, h) kh_clear_##name(P, h)
220 #define kh_resize(name, h, s) h = kh_resize_##name(P, h, s)
221 #define kh_put(name, h, k, r) kh_put_##name(P, h, k, r)
222 #define kh_get(name, h, k) kh_get_##name(P, h, k)
223 #define kh_del(name, h, k) kh_del_##name(P, h, k)
224 
225 #define kh_exist(name, h, x) (!__kh_iseither(name, (h), (x)))
226 #define kh_key(name, h, x) (KHASH_KEY(name, h, x))
227 #define kh_val(name, h, x) (KHASH_VAL(name, h, x))
228 #define kh_begin(h) (khint_t)(0)
229 #define kh_end(h) ((h)->n_buckets)
230 #define kh_size(h) ((h)->size)
231 #define kh_n_buckets(h) ((h)->n_buckets)
232 #define kh_mem(name, h) (((struct PNTable *)h)->n_buckets == 0 ? 0 : kh_size_##name(((struct PNTable *)h)->n_buckets))
233 
234 #define KHASH_MAP_INIT_STR(name, t) \
235  KHASH_INIT(name, t, _PN, PNUniq, const char *, 0, kh_pnstr_hash_func, \
236  kh_pnstr_hash_equal, kh_str_hash_func, kh_str_hash_equal)
237 
238 #define KHASH_MAP_INIT_PN(name, t) \
239  KHASH_INIT(name, t, _PN, _PN, _PN, 1, kh_pn_hash_func, \
240  kh_pn_hash_equal, kh_pn_hash_func, kh_pn_hash_equal)
241 
242 #endif /* __AC_KHASH_H */
uint32_t khint_t
Definition: khash.h:20
static khint_t __ac_Wang_hash(khint_t key)
Definition: khash.h:203
khint_t khiter_t
Definition: khash.h:21
static khint_t __luaS_hash_string(const char *s)
Definition: khash.h:186
static khint_t __kh_X31_hash_string(const char *s)
Definition: khash.h:180
static const double __kh_HASH_UPPER
Definition: khash.h:40