xref: /petsc/include/petsc/private/hashset.h (revision 6d8694c4fbab79f9439f1ad13c0386ba7ee1ca4b)
1 #pragma once
2 
3 #include <petsc/private/hashtable.h>
4 
5 /* MANSEC = Sys */
6 /* SUBMANSEC = PetscH */
7 
8 /*MC
9   PETSC_HASH_SET - Instantiate a new PETSc hash set type
10 
11   Synopsis:
12   #include <petsc/private/hashset.h>
13   PETSC_HASH_SET(HSetT, KeyType, HashFunc, EqualFunc)
14 
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
20 
21   Level: developer
22 
23   Note:
24   This code uses the standalone and portable C language khash software <https://github.com/attractivechaos/klib>
25 
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.
30 
31 .seealso: `PetscHSetI`, `PetscHSetICreate()`, `PetscHSetIJ`, `PetscHSetIJCreate()`, `PETSC_HASH_MAP()`
32 M*/
33 
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   }
206