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