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: }