Actual source code: hashmap.h

  1: #ifndef PETSC_HASHMAP_H
  2: #define PETSC_HASHMAP_H

  4: #include <petsc/private/hashtable.h>

  6: /* SUBMANSEC = PetscH */

  8: /*MC
  9:   PETSC_HASH_MAP - Instantiate a PETSc hash table map type

 11:   Synopsis:
 12: #include <petsc/private/hashmap.h>
 13:   PETSC_HASH_MAP(HMapT, KeyType, ValType, HashFunc, EqualFunc, DefaultValue)

 15:   Input Parameters:
 16: + HMapT - The hash table map type name suffix
 17: . KeyType - The type of keys
 18: . ValType - The type of values
 19: . HashFunc - Routine or function-like macro computing hash values from keys
 20: . EqualFunc - Routine or function-like macro computing whether two values are equal
 21: - DefaultValue - Default value to use for queries in case of missing keys

 23:   Level: developer

 25:   Developer Note:
 26:     Each time this macro is used to create a new hash map type, the make rule for allmanpages in $PETSC_DIR/makefile should
 27:     be updated to cause the automatic generation of appropriate manual pages for that type. The manual pages
 28:     are generated from the templated version of the documentation in include/petsc/private/hashmap.txt.

 30:   References:
 31:     This code uses the standalone and portable C language khash software https://github.com/attractivechaos/klib

 33: .seealso: `PetscHMapI`, `PetscHMapICreate()`, `PetscHMapIJ`, `PetscHMapIJCreate()`, `PETSC_HASH_SET()`
 34: M*/

 36: #define PETSC_HASH_MAP(HashT, KeyType, ValType, HashFunc, EqualFunc, DefaultValue) \
 37: \
 38:   KHASH_INIT(HashT, KeyType, ValType, 1, HashFunc, EqualFunc) \
 39: \
 40:   typedef khash_t(HashT) *Petsc##HashT; \
 41: \
 42:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Create(Petsc##HashT *ht) \
 43:   { \
 45:     *ht = kh_init(HashT); \
 46:     PetscHashAssert(*ht != NULL); \
 47:     return 0; \
 48:   } \
 49: \
 50:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Destroy(Petsc##HashT *ht) \
 51:   { \
 53:     if (!*ht) return 0; \
 54:     kh_destroy(HashT, *ht); \
 55:     *ht = NULL; \
 56:     return 0; \
 57:   } \
 58: \
 59:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Reset(Petsc##HashT ht) \
 60:   { \
 62:     kh_reset(HashT, ht); \
 63:     return 0; \
 64:   } \
 65: \
 66:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Duplicate(Petsc##HashT ht, Petsc##HashT *hd) \
 67:   { \
 68:     int     ret; \
 69:     KeyType key; \
 70:     ValType val; \
 73:     *hd = kh_init(HashT); \
 74:     PetscHashAssert(*hd != NULL); \
 75:     ret = kh_resize(HashT, *hd, kh_size(ht)); \
 76:     PetscHashAssert(ret == 0); \
 77:     kh_foreach(ht, key, val, { \
 78:       khiter_t i; \
 79:       i = kh_put(HashT, *hd, key, &ret); \
 80:       PetscHashAssert(ret >= 0); \
 81:       kh_val(*hd, i) = val; \
 82:     }) return 0; \
 83:   } \
 84: \
 85:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Clear(Petsc##HashT ht) \
 86:   { \
 88:     kh_clear(HashT, ht); \
 89:     return 0; \
 90:   } \
 91: \
 92:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Resize(Petsc##HashT ht, PetscInt nb) \
 93:   { \
 94:     int ret; \
 96:     ret = kh_resize(HashT, ht, (khint_t)nb); \
 97:     PetscHashAssert(ret >= 0); \
 98:     return 0; \
 99:   } \
100: \
101:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetSize(Petsc##HashT ht, PetscInt *n) \
102:   { \
105:     *n = (PetscInt)kh_size(ht); \
106:     return 0; \
107:   } \
108: \
109:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetCapacity(Petsc##HashT ht, PetscInt *n) \
110:   { \
113:     *n = (PetscInt)kh_n_buckets(ht); \
114:     return 0; \
115:   } \
116: \
117:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Has(Petsc##HashT ht, KeyType key, PetscBool *has) \
118:   { \
119:     khiter_t iter; \
123:     iter = kh_get(HashT, ht, key); \
124:     *has = (iter != kh_end(ht)) ? PETSC_TRUE : PETSC_FALSE; \
125:     return 0; \
126:   } \
127: \
128:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Get(Petsc##HashT ht, KeyType key, ValType *val) \
129:   { \
130:     khiter_t iter; \
134:     iter = kh_get(HashT, ht, key); \
135:     *val = (iter != kh_end(ht)) ? kh_val(ht, iter) : (DefaultValue); \
136:     return 0; \
137:   } \
138: \
139:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Set(Petsc##HashT ht, KeyType key, ValType val) \
140:   { \
141:     int      ret; \
142:     khiter_t iter; \
145:     iter = kh_put(HashT, ht, key, &ret); \
146:     PetscHashAssert(ret >= 0); \
147:     kh_val(ht, iter) = val; \
148:     return 0; \
149:   } \
150: \
151:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Del(Petsc##HashT ht, KeyType key) \
152:   { \
153:     khiter_t iter; \
156:     iter = kh_get(HashT, ht, key); \
157:     kh_del(HashT, ht, iter); \
158:     return 0; \
159:   } \
160: \
161:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##QuerySet(Petsc##HashT ht, KeyType key, ValType val, PetscBool *missing) \
162:   { \
163:     int      ret; \
164:     khiter_t iter; \
168:     iter = kh_put(HashT, ht, key, &ret); \
169:     PetscHashAssert(ret >= 0); \
170:     kh_val(ht, iter) = val; \
171:     *missing         = ret ? PETSC_TRUE : PETSC_FALSE; \
172:     return 0; \
173:   } \
174: \
175:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##QueryDel(Petsc##HashT ht, KeyType key, PetscBool *present) \
176:   { \
177:     khiter_t iter; \
181:     iter = kh_get(HashT, ht, key); \
182:     if (iter != kh_end(ht)) { \
183:       kh_del(HashT, ht, iter); \
184:       *present = PETSC_TRUE; \
185:     } else { \
186:       *present = PETSC_FALSE; \
187:     } \
188:     return 0; \
189:   } \
190: \
191:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Find(Petsc##HashT ht, KeyType key, PetscHashIter *iter, PetscBool *found) \
192: \
193:   { \
198:     *iter  = kh_get(HashT, ht, key); \
199:     *found = (*iter != kh_end(ht)) ? PETSC_TRUE : PETSC_FALSE; \
200:     return 0; \
201:   } \
202: \
203:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Put(Petsc##HashT ht, KeyType key, PetscHashIter *iter, PetscBool *missing) \
204:   { \
205:     int ret; \
210:     *iter = kh_put(HashT, ht, key, &ret); \
211:     PetscHashAssert(ret >= 0); \
212:     *missing = ret ? PETSC_TRUE : PETSC_FALSE; \
213:     return 0; \
214:   } \
215: \
216:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##IterGet(Petsc##HashT ht, PetscHashIter iter, ValType *val) \
217:   { \
221:     *val = PetscLikely(iter < kh_end(ht) && kh_exist(ht, iter)) ? kh_val(ht, iter) : (DefaultValue); \
222:     return 0; \
223:   } \
224: \
225:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##IterSet(Petsc##HashT ht, PetscHashIter iter, ValType val) \
226:   { \
229:     if (PetscLikely(iter < kh_end(ht) && kh_exist(ht, iter))) kh_val(ht, iter) = val; \
230:     return 0; \
231:   } \
232: \
233:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##IterDel(Petsc##HashT ht, PetscHashIter iter) \
234:   { \
237:     if (PetscLikely(iter < kh_end(ht))) kh_del(HashT, ht, iter); \
238:     return 0; \
239:   } \
240: \
241:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetKeys(Petsc##HashT ht, PetscInt *off, KeyType array[]) \
242:   { \
243:     KeyType  key; \
244:     PetscInt pos; \
247:     pos = *off; \
248:     kh_foreach_key(ht, key, array[pos++] = key); \
249:     *off = pos; \
250:     return 0; \
251:   } \
252: \
253:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetVals(Petsc##HashT ht, PetscInt *off, ValType array[]) \
254:   { \
255:     ValType  val; \
256:     PetscInt pos; \
259:     pos = *off; \
260:     kh_foreach_value(ht, val, array[pos++] = val); \
261:     *off = pos; \
262:     return 0; \
263:   } \
264: \
265:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetPairs(Petsc##HashT ht, PetscInt *off, KeyType karray[], ValType varray[]) \
266:   { \
267:     ValType  val; \
268:     KeyType  key; \
269:     PetscInt pos; \
272:     pos     = *off; \
273:     kh_foreach(ht, key, val, { \
274:       karray[pos]   = key; \
275:       varray[pos++] = val; \
276:     }) *off = pos; \
277:     return 0; \
278:   }

280: #endif /* PETSC_HASHMAP_H */