Actual source code: hashset.h

  1: #pragma once

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

  5: /* SUBMANSEC = PetscH */

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

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

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

 20:   Level: developer

 22:   Note:
 23:   This code uses the standalone and portable C language khash software <https://github.com/attractivechaos/klib>

 25:   Developer Note:
 26:   Each time this macro is used to create a new hash set 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/hashset.txt.

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

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