Actual source code: hashset.h

  1: #ifndef PETSC_HASHSET_H
  2: #define PETSC_HASHSET_H

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

  6: /* SUBMANSEC = PetscH */

  8: /*MC
  9:   PETSC_HASH_SET - Instantiate a new PETSc hash set type

 11:   Synopsis:
 12: #include <petsc/private/hashset.h>
 13:   PETSC_HASH_SET(HSetT, KeyType, HashFunc, EqualFunc)

 15:   Input Parameters:
 16: + HSetT - The hash set type name suffix, i.e. the name of the object created is PetscHSet<HSetT>
 17: . KeyType - The type of entries, may be a basic type such as int or a struct
 18: . HashFunc - Routine or function-like macro that computes hash values from entries
 19: - EqualFunc - Routine or function-like macro that computes whether two values are equal

 21:   Level: developer

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

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

 31: .seealso: `PetscHSetI`, `PetscHSetICreate()`, `PetscHSetIJ`, `PetscHSetIJCreate()`, `PETSC_HASH_MAP()`
 32: M*/

 34: #define PETSC_HASH_SET(HashT, KeyType, HashFunc, EqualFunc) \
 35: \
 36:   KHASH_INIT(HashT, KeyType, char, 0, HashFunc, EqualFunc) \
 37: \
 38:   typedef khash_t(HashT) *Petsc##HashT; \
 39: \
 40:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Create(Petsc##HashT *ht) \
 41:   { \
 43:     *ht = kh_init(HashT); \
 44:     return 0; \
 45:   } \
 46: \
 47:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Destroy(Petsc##HashT *ht) \
 48:   { \
 50:     if (!*ht) return 0; \
 51:     kh_destroy(HashT, *ht); \
 52:     *ht = NULL; \
 53:     return 0; \
 54:   } \
 55: \
 56:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Reset(Petsc##HashT ht) \
 57:   { \
 59:     kh_reset(HashT, ht); \
 60:     return 0; \
 61:   } \
 62: \
 63:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Duplicate(Petsc##HashT ht, Petsc##HashT *hd) \
 64:   { \
 65:     int     ret; \
 66:     KeyType key; \
 69:     *hd = kh_init(HashT); \
 70:     ret = kh_resize(HashT, *hd, kh_size(ht)); \
 71:     PetscHashAssert(ret == 0); \
 72:     kh_foreach_key(ht, key, { \
 73:       kh_put(HashT, *hd, key, &ret); \
 74:       PetscHashAssert(ret >= 0); \
 75:     }) return 0; \
 76:   } \
 77: \
 78:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Update(Petsc##HashT ht, Petsc##HashT hta) \
 79:   { \
 80:     int     ret; \
 81:     KeyType key; \
 84:     kh_foreach_key(hta, key, { \
 85:       kh_put(HashT, ht, key, &ret); \
 86:       PetscHashAssert(ret >= 0); \
 87:     }) return 0; \
 88:   } \
 89: \
 90:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Clear(Petsc##HashT ht) \
 91:   { \
 93:     kh_clear(HashT, ht); \
 94:     return 0; \
 95:   } \
 96: \
 97:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Resize(Petsc##HashT ht, PetscInt nb) \
 98:   { \
 99:     int ret; \
101:     ret = kh_resize(HashT, ht, (khint_t)nb); \
102:     PetscHashAssert(ret == 0); \
103:     return 0; \
104:   } \
105: \
106:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetSize(Petsc##HashT ht, PetscInt *n) \
107:   { \
110:     *n = (PetscInt)kh_size(ht); \
111:     return 0; \
112:   } \
113: \
114:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetCapacity(Petsc##HashT ht, PetscInt *n) \
115:   { \
118:     *n = (PetscInt)kh_n_buckets(ht); \
119:     return 0; \
120:   } \
121: \
122:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Has(Petsc##HashT ht, KeyType key, PetscBool *has) \
123:   { \
124:     khiter_t iter; \
128:     iter = kh_get(HashT, ht, key); \
129:     *has = (iter != kh_end(ht)) ? PETSC_TRUE : PETSC_FALSE; \
130:     return 0; \
131:   } \
132: \
133:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Add(Petsc##HashT ht, KeyType key) \
134:   { \
135:     int      ret; \
136:     khiter_t iter; \
139:     iter = kh_put(HashT, ht, key, &ret); \
140:     (void)iter; \
141:     PetscHashAssert(ret >= 0); \
142:     return 0; \
143:   } \
144: \
145:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Del(Petsc##HashT ht, KeyType key) \
146:   { \
147:     khiter_t iter; \
150:     iter = kh_get(HashT, ht, key); \
151:     kh_del(HashT, ht, iter); \
152:     return 0; \
153:   } \
154: \
155:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##QueryAdd(Petsc##HashT ht, KeyType key, PetscBool *missing) \
156:   { \
157:     int      ret; \
158:     khiter_t iter; \
162:     iter = kh_put(HashT, ht, key, &ret); \
163:     (void)iter; \
164:     PetscHashAssert(ret >= 0); \
165:     *missing = ret ? PETSC_TRUE : PETSC_FALSE; \
166:     return 0; \
167:   } \
168: \
169:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##QueryDel(Petsc##HashT ht, KeyType key, PetscBool *present) \
170:   { \
171:     khiter_t iter; \
175:     iter = kh_get(HashT, ht, key); \
176:     if (iter != kh_end(ht)) { \
177:       kh_del(HashT, ht, iter); \
178:       *present = PETSC_TRUE; \
179:     } else { \
180:       *present = PETSC_FALSE; \
181:     } \
182:     return 0; \
183:   } \
184: \
185:   static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetElems(Petsc##HashT ht, PetscInt *off, KeyType array[]) \
186:   { \
187:     KeyType  key; \
188:     PetscInt pos; \
191:     pos = *off; \
192:     kh_foreach_key(ht, key, array[pos++] = key); \
193:     *off = pos; \
194:     return 0; \
195:   }

197: #endif /* PETSC_HASHSET_H */