File Coverage

ds_iset.c
Criterion Covered Total %
statement 54 170 31.7
branch 31 148 20.9
condition n/a
subroutine n/a
pod n/a
total 85 318 26.7


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include
4              
5             #include "ptypes.h"
6             #include "ds_iset.h"
7             #include "util.h"
8             #include "sort.h"
9              
10             #define FILL_RATIO 0.55
11              
12             #if BITS_PER_WORD == 32
13             /* 16 0x45d9f3b 16 0x45d9f3b 16 */
14             /* 16 0x21f0aaad 15 0x735a2d97 15 */
15             static UV _hash(UV x) {
16             x = ((x >> 16) ^ x) * 0x45d9f3b;
17             x = ((x >> 16) ^ x) * 0x45d9f3b;
18             x = (x >> 16) ^ x;
19             return x;
20             }
21             #else
22             /* 30 0xbf58476d1ce4e5b9 27 0x94d049bb133111eb 31 SplitMix64/Meuller */
23             /* 32 0xd6e8feb86659fd93 32 0xd6e8feb86659fd93 32 degski */
24             /* 33 0xff51afd7ed558ccd 33 0xc4ceb9fe1a85ec53 33 Murmur64 */
25             /* 32 0xe9846af9b1a615d 32 0xe9846af9b1a615d 28 xmxmx */
26             /* 32 0xbea225f9eb34556d 29 0xbea225f9eb34556d 32 0xbea225f9eb34556d 29 mx3 */
27              
28 5370           static UV _hash(UV x) {
29 5370           x = (x ^ (x >> 32)) * UVCONST(0xe9846af9b1a615d);
30 5370           x = (x ^ (x >> 32)) * UVCONST(0xe9846af9b1a615d);
31 5370           x = x ^ (x >> 28);
32 5370           return x;
33             }
34             #endif
35              
36             #define HVAL(x,mask) (_hash(x) & mask)
37              
38             /******************************************************************************/
39              
40 79           iset_t iset_create(size_t init_size) {
41             iset_t set;
42 79           int bits = 4;
43 79           const int maxsizebits = 8 * sizeof(size_t);
44              
45 79           set.size = 0; set.contains_zero = 0; set.type = 0;
46              
47 267 50         while (bits < maxsizebits-1 && ((1UL << bits) * FILL_RATIO + 1) < init_size)
    100          
48 188           bits++;
49 79           set.maxsize = 1UL << bits;
50 79           set.mask = set.maxsize - 1;
51 79 50         Newz(0, set.arr, set.maxsize, UV);
52 79           return set;
53             }
54              
55 79           void iset_destroy(iset_t *set) {
56 79           set->maxsize = 0; set->size = 0; set->contains_zero = 0; set->type = 0;
57 79           Safefree(set->arr);
58 79           set->arr = 0;
59 79           }
60              
61 5370           static size_t _iset_pos(const UV* arr, UV mask, UV val) {
62 5370           size_t h = HVAL(val,mask);
63 6640 100         while (arr[h] != 0 && arr[h] != val)
    100          
64 1270           h = (h+1) & mask;
65 5370           return h;
66             }
67              
68 47           bool iset_contains(const iset_t set, UV val) {
69 47 100         if (val == 0) return set.contains_zero;
70 46           return set.arr[_iset_pos(set.arr, set.mask, val)] == val;
71             }
72              
73 0           static void _iset_resize(iset_t *set) {
74             UV v, *narr;
75             size_t i, oldsize, newsize, newmask;
76              
77 0           oldsize = set->maxsize;
78 0           newsize = oldsize << 1;
79 0 0         if (newsize < oldsize) croak("iset: max set size overflow");
80 0           newmask = newsize - 1;
81              
82 0 0         Newz(0, narr, newsize, UV);
83 0 0         for (i = 0; i < oldsize; i++)
84 0 0         if (v = set->arr[i], v != 0)
85 0           narr[ _iset_pos(narr,newmask,v) ] = v;
86 0           Safefree(set->arr);
87 0           set->arr = narr;
88 0           set->maxsize = newsize;
89 0           set->mask = newmask;
90 0           }
91              
92 5351           bool iset_add(iset_t *set, UV val, int sign) {
93 5351 50         if (sign == 0)
94 0           set->type = ISET_TYPE_INVALID;
95 5351 100         else if (val > (UV)IV_MAX)
96 108 100         set->type |= ((sign > 0) ? ISET_TYPE_UV : ISET_TYPE_IV);
97 5351 100         if (val == 0) {
98 27 100         if (set->contains_zero)
99 11           return 0;
100 16           set->contains_zero = 1;
101 16           set->size++;
102             } else {
103 5324           size_t h = _iset_pos(set->arr, set->mask, val);
104 5324 100         if (set->arr[h] == val)
105 2351           return 0;
106 2973           set->arr[h] = val;
107 2973 50         if (++set->size > FILL_RATIO * (double)set->maxsize)
108 0           _iset_resize(set);
109             }
110 2989           return 1;
111             }
112              
113 0           iset_t iset_create_from_array(UV* d, size_t dlen, int dsign) {
114 0           iset_t s = iset_create(dlen);
115              
116 0 0         if (dsign != 0) {
117 0 0         unsigned char typemask = ((dsign > 0) ? ISET_TYPE_UV : ISET_TYPE_IV);
118             size_t i;
119 0 0         for (i = 0; i < dlen; i++) {
120 0           UV val = d[i];
121 0 0         if (val == 0) {
122 0 0         if (!s.contains_zero) { s.contains_zero = 1; s.size++; }
123             } else {
124 0           size_t h = _iset_pos(s.arr, s.mask, val);
125 0 0         if (s.arr[h] != val) {
126 0           s.arr[h] = val;
127 0 0         if (++s.size > FILL_RATIO * (double)s.maxsize)
128 0           _iset_resize(&s);
129             }
130 0 0         if (val > (UV)IV_MAX)
131 0           s.type |= typemask;
132             }
133             }
134             }
135 0           return s;
136             }
137              
138 38           void iset_allvals(const iset_t set, UV* array) {
139 38           size_t j, i = 0;
140 38 100         if (set.contains_zero)
141 2           array[i++] = 0;
142 7782 100         for (j = 0; j < set.maxsize; j++)
143 7744 100         if (set.arr[j] != 0)
144 603           array[i++] = set.arr[j];
145 38 50         if (i != set.size) croak("iset_allvals bad size");
146 38 100         if (set.type == ISET_TYPE_IV) sort_iv_array((IV*)array, i);
147 29           else sort_uv_array(array, i);
148 38           }
149              
150             #if 0
151             void iset_minmax(const iset_t set, UV *min, UV *max) {
152             size_t i;
153              
154             *min = *max = 0;
155             if (set.type == ISET_TYPE_INVALID || set.size == 0)
156             return;
157              
158             if (set.type != ISET_TYPE_IV) {
159             if (!set.contains_zero) { *min = UV_MAX; }
160             for (i = 0; i < set.maxsize; i++) {
161             UV v = set.arr[i];
162             if (v != 0) {
163             if (v < *min) *min = v;
164             if (v > *max) *max = v;
165             }
166             }
167             } else {
168             IV smin = set.contains_zero ? 0 : IV_MAX;
169             IV smax = set.contains_zero ? 0 : IV_MIN;
170             for (i = 0; i < set.maxsize; i++) {
171             IV sv = (IV) set.arr[i];
172             if (sv != 0) {
173             if (sv < smin) smin = sv;
174             if (sv > smax) smax = sv;
175             }
176             }
177             *min = (UV)smin;
178             *max = (UV)smax;
179             }
180             }
181             #endif
182              
183              
184             /******************************************************************************/
185              
186 0           void iset_union_with(iset_t *set, const iset_t L) {
187             size_t i, lsize;
188             UV v, *larr;
189 0           int lsign = iset_sign(L);
190              
191 0           lsize = L.maxsize;
192 0           larr = L.arr;
193 0 0         for (i = 0; i < lsize; i++)
194 0 0         if (v = larr[i], v != 0)
195 0           iset_add(set, v, lsign);
196 0 0         if (L.contains_zero && !set->contains_zero) iset_add(set,0,1);
    0          
197 0           }
198              
199 0           void iset_intersect_with(iset_t *set, const iset_t L) {
200 0           iset_t s = iset_intersection_of(*set, L);
201 0           iset_destroy(set);
202 0           *set = s;
203 0           }
204              
205 0           void iset_difference_with(iset_t *set, const iset_t L) {
206 0           iset_t s = iset_difference_of(*set, L);
207 0           iset_destroy(set);
208 0           *set = s;
209 0           }
210              
211 0           void iset_symdiff_with(iset_t *set, const iset_t L) {
212 0           iset_t s = iset_symdiff_of(*set, L);
213 0           iset_destroy(set);
214 0           *set = s;
215 0           }
216              
217             /******************************************************************************/
218              
219 0           iset_t iset_union_of(const iset_t A, const iset_t B) {
220             size_t i;
221             UV v;
222 0           int asign = iset_sign(A), bsign = iset_sign(B);
223 0           iset_t s = iset_create(A.size + B.size);
224              
225 0 0         for (i = 0; i < A.maxsize; i++)
226 0 0         if (v = A.arr[i], v != 0)
227 0           iset_add(&s, v, asign);
228 0 0         for (i = 0; i < B.maxsize; i++)
229 0 0         if (v = B.arr[i], v != 0)
230 0           iset_add(&s, v, bsign);
231 0 0         if (A.contains_zero || B.contains_zero) iset_add(&s,0,1);
    0          
232 0           return s;
233             }
234              
235 0           iset_t iset_intersection_of(const iset_t A, const iset_t B) {
236 0           int asign = iset_sign(A), bsign = iset_sign(B);
237 0           int samesign = (asign == bsign);
238             size_t i;
239             UV v;
240             iset_t s;
241              
242 0 0         if (A.size > B.size) /* Swap for performance. */
243 0           return iset_intersection_of(B,A);
244              
245 0           s = iset_create((A.size < B.size) ? A.size : B.size);
246              
247 0 0         for (i = 0; i < A.maxsize; i++)
248 0 0         if (v = A.arr[i], v != 0)
249 0 0         if ( !((v > (UV)IV_MAX) && !samesign) && iset_contains(B, v))
    0          
    0          
250 0           iset_add(&s, v, asign);
251 0 0         if (A.contains_zero && B.contains_zero) iset_add(&s,0,1);
    0          
252 0           return s;
253             }
254 0           iset_t iset_difference_of(const iset_t A, const iset_t B) {
255 0           int asign = iset_sign(A), bsign = iset_sign(B);
256 0           int samesign = (asign == bsign);
257             size_t i;
258             UV v;
259 0           iset_t s = iset_create((A.size > B.size) ? A.size : B.size);
260              
261 0 0         for (i = 0; i < A.maxsize; i++)
262 0 0         if (v = A.arr[i], v != 0)
263 0 0         if ( ((v > (UV)IV_MAX) && !samesign) || !iset_contains(B, v) )
    0          
    0          
264 0           iset_add(&s, v, asign);
265 0 0         if (A.contains_zero && !B.contains_zero) iset_add(&s,0,1);
    0          
266 0           return s;
267             }
268 0           iset_t iset_symdiff_of(const iset_t A, const iset_t B) {
269 0           int asign = iset_sign(A), bsign = iset_sign(B);
270 0           int samesign = (asign == bsign);
271             size_t i;
272             UV v;
273 0           iset_t s = iset_create((A.size > B.size) ? A.size : B.size);
274              
275 0 0         for (i = 0; i < A.maxsize; i++)
276 0 0         if (v = A.arr[i], v != 0)
277 0 0         if ( ((v > (UV)IV_MAX) && !samesign) || !iset_contains(B, v) )
    0          
    0          
278 0           iset_add(&s, v, asign);
279 0 0         for (i = 0; i < B.maxsize; i++)
280 0 0         if (v = B.arr[i], v != 0)
281 0 0         if ( ((v > (UV)IV_MAX) && !samesign) || !iset_contains(A, v) )
    0          
    0          
282 0           iset_add(&s, v, bsign);
283 0 0         if ((A.contains_zero + B.contains_zero) == 1) iset_add(&s,0,1);
284 0           return s;
285             }
286 0           bool iset_is_subset_of(const iset_t A, const iset_t B) {
287 0           int samesign = (iset_sign(A) == iset_sign(B));
288             size_t i;
289             UV v;
290              
291 0 0         if (A.size > B.size)
292 0           return 0;
293 0 0         if (A.contains_zero && !B.contains_zero)
    0          
294 0           return 0;
295 0 0         for (i = 0; i < A.maxsize; i++)
296 0 0         if (v = A.arr[i], v != 0)
297 0 0         if ( ((v > (UV)IV_MAX) && !samesign) || !iset_contains(B, v) )
    0          
    0          
298 0           return 0;
299 0           return 1;
300             }
301              
302             /******************************************************************************/
303              
304 0           void iset_test(void) {
305             #if 0
306             iset_t s;
307             UV *S;
308             size_t i;
309             const size_t ts = 30000000;
310              
311             printf("create .. "); fflush(stdout);
312             s = iset_create(0);
313             printf("done\n"); fflush(stdout);
314             for (i = ts/2; i < ts; i++) {
315             iset_add(&s, i, 1);
316             }
317             printf("done adding. size is %lu\n", (unsigned long)iset_size(s)); fflush(stdout);
318             if (iset_contains(s,0) != 0) croak("fail 0");
319             for (i = 0; i < ts; i++) {
320             iset_add(&s, i, 1);
321             }
322             printf("done adding. size is %lu\n", (unsigned long)iset_size(s)); fflush(stdout);
323              
324             if (iset_contains(s,1) != 1) croak("fail 1");
325             if (iset_contains(s,ts-1) != 1) croak("fail 999");
326             if (iset_contains(s,ts) != 0) croak("fail 1000");
327             if (iset_contains(s,0) != 1) croak("fail 0");
328             if (iset_sign(s) != 1) croak("fail sign");
329             if (iset_is_invalid(s) != 0) croak("fail invalid");
330             if (iset_size(s) != ts) croak("fail size");
331              
332             New(0,S,iset_size(s),UV);
333             iset_allvals(s,S);
334             for (i = 0; i < ts; i++)
335             if (S[i] != i)
336             croak("fail element %lu expected %lu got %lu\n", (unsigned long)i, (unsigned long)i, S[i]);
337             iset_destroy(&s);
338             #endif
339 0           }