Actual source code: hashset.h
1: #ifndef PETSC_HASHSET_H
2: #define PETSC_HASHSET_H
4: #include <petsc/private/hashtable.h>
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: Developer Note:
24: Each time this macro is used to create a new hash set type, the make rule for allmanpages in $PETSC_DIR/makefile should
25: be updated to cause the automatic generation of appropriate manual pages for that type. The manual pages
26: are generated from the templated version of the documentation in include/petsc/private/hashset.txt.
28: References:
29: This code uses the standalone and portable C language khash software https://github.com/attractivechaos/klib
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: { \
43: *ht = kh_init(HashT); \
44: return 0; \
45: } \
46: \
47: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Destroy(Petsc##HashT *ht) \
48: { \
50: if (!*ht) return 0; \
51: kh_destroy(HashT, *ht); \
52: *ht = NULL; \
53: return 0; \
54: } \
55: \
56: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Reset(Petsc##HashT ht) \
57: { \
59: kh_reset(HashT, ht); \
60: return 0; \
61: } \
62: \
63: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Duplicate(Petsc##HashT ht, Petsc##HashT *hd) \
64: { \
65: int ret; \
66: KeyType key; \
69: *hd = kh_init(HashT); \
70: ret = kh_resize(HashT, *hd, kh_size(ht)); \
71: PetscHashAssert(ret == 0); \
72: kh_foreach_key(ht, key, { \
73: kh_put(HashT, *hd, key, &ret); \
74: PetscHashAssert(ret >= 0); \
75: }) return 0; \
76: } \
77: \
78: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Update(Petsc##HashT ht, Petsc##HashT hta) \
79: { \
80: int ret; \
81: KeyType key; \
84: kh_foreach_key(hta, key, { \
85: kh_put(HashT, ht, key, &ret); \
86: PetscHashAssert(ret >= 0); \
87: }) return 0; \
88: } \
89: \
90: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Clear(Petsc##HashT ht) \
91: { \
93: kh_clear(HashT, ht); \
94: return 0; \
95: } \
96: \
97: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Resize(Petsc##HashT ht, PetscInt nb) \
98: { \
99: int ret; \
101: ret = kh_resize(HashT, ht, (khint_t)nb); \
102: PetscHashAssert(ret == 0); \
103: return 0; \
104: } \
105: \
106: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetSize(Petsc##HashT ht, PetscInt *n) \
107: { \
110: *n = (PetscInt)kh_size(ht); \
111: return 0; \
112: } \
113: \
114: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetCapacity(Petsc##HashT ht, PetscInt *n) \
115: { \
118: *n = (PetscInt)kh_n_buckets(ht); \
119: return 0; \
120: } \
121: \
122: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Has(Petsc##HashT ht, KeyType key, PetscBool *has) \
123: { \
124: khiter_t iter; \
128: iter = kh_get(HashT, ht, key); \
129: *has = (iter != kh_end(ht)) ? PETSC_TRUE : PETSC_FALSE; \
130: return 0; \
131: } \
132: \
133: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Add(Petsc##HashT ht, KeyType key) \
134: { \
135: int ret; \
136: khiter_t iter; \
139: iter = kh_put(HashT, ht, key, &ret); \
140: (void)iter; \
141: PetscHashAssert(ret >= 0); \
142: return 0; \
143: } \
144: \
145: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##Del(Petsc##HashT ht, KeyType key) \
146: { \
147: khiter_t iter; \
150: iter = kh_get(HashT, ht, key); \
151: kh_del(HashT, ht, iter); \
152: return 0; \
153: } \
154: \
155: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##QueryAdd(Petsc##HashT ht, KeyType key, PetscBool *missing) \
156: { \
157: int ret; \
158: khiter_t iter; \
162: iter = kh_put(HashT, ht, key, &ret); \
163: (void)iter; \
164: PetscHashAssert(ret >= 0); \
165: *missing = ret ? PETSC_TRUE : PETSC_FALSE; \
166: return 0; \
167: } \
168: \
169: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##QueryDel(Petsc##HashT ht, KeyType key, PetscBool *present) \
170: { \
171: khiter_t iter; \
175: iter = kh_get(HashT, ht, key); \
176: if (iter != kh_end(ht)) { \
177: kh_del(HashT, ht, iter); \
178: *present = PETSC_TRUE; \
179: } else { \
180: *present = PETSC_FALSE; \
181: } \
182: return 0; \
183: } \
184: \
185: static inline PETSC_UNUSED PetscErrorCode Petsc##HashT##GetElems(Petsc##HashT ht, PetscInt *off, KeyType array[]) \
186: { \
187: KeyType key; \
188: PetscInt pos; \
191: pos = *off; \
192: kh_foreach_key(ht, key, array[pos++] = key); \
193: *off = pos; \
194: return 0; \
195: }
197: #endif /* PETSC_HASHSET_H */