Actual source code: hashset.h

  1: #pragma once

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

  5: /* MANSEC = Sys */
  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:   Note:
 24:   This code uses the standalone and portable C language khash software <https://github.com/attractivechaos/klib>

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

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