1 /* General bitsets.
2 Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
3 Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include "bitset.h"
26 #include "abitset.h"
27 #include "lbitset.h"
28 #include "ebitset.h"
29 #include "vbitset.h"
30 #include "bitset_stats.h"
31 #include "obstack.h"
32
33 const char * const bitset_type_names[] = BITSET_TYPE_NAMES;
34
35
36 /* Return number of bytes required to create a N_BIT bitset
37 of TYPE. The bitset may grow to require more bytes than this. */
38 size_t
bitset_bytes(enum bitset_type type,bitset_bindex n_bits)39 bitset_bytes (enum bitset_type type, bitset_bindex n_bits)
40 {
41 size_t bytes;
42
43 if (bitset_stats_enabled)
44 return bitset_stats_bytes ();
45
46 switch (type)
47 {
48 default:
49 abort ();
50
51 case BITSET_ARRAY:
52 bytes = abitset_bytes (n_bits);
53 break;
54
55 case BITSET_LIST:
56 bytes = lbitset_bytes (n_bits);
57 break;
58
59 case BITSET_TABLE:
60 bytes = ebitset_bytes (n_bits);
61 break;
62
63 case BITSET_VARRAY:
64 bytes = vbitset_bytes (n_bits);
65 break;
66 }
67
68 return bytes;
69 }
70
71
72 /* Initialise bitset BSET of TYPE for N_BITS. */
73 bitset
bitset_init(bitset bset,bitset_bindex n_bits,enum bitset_type type)74 bitset_init (bitset bset, bitset_bindex n_bits, enum bitset_type type)
75 {
76 if (bitset_stats_enabled)
77 return bitset_stats_init (bset, n_bits, type);
78
79 switch (type)
80 {
81 default:
82 abort ();
83
84 case BITSET_ARRAY:
85 return abitset_init (bset, n_bits);
86
87 case BITSET_LIST:
88 return lbitset_init (bset, n_bits);
89
90 case BITSET_TABLE:
91 return ebitset_init (bset, n_bits);
92
93 case BITSET_VARRAY:
94 return vbitset_init (bset, n_bits);
95 }
96 }
97
98
99 /* Select a bitset type for a set of N_BITS and with attribute hints
100 specified by ATTR. For variable size bitsets, N_BITS is only a
101 hint and may be zero. */
102 enum bitset_type
bitset_type_choose(bitset_bindex n_bits ATTRIBUTE_UNUSED,unsigned int attr)103 bitset_type_choose (bitset_bindex n_bits ATTRIBUTE_UNUSED, unsigned int attr)
104 {
105 /* Check attributes. */
106 if (attr & BITSET_FIXED && attr & BITSET_VARIABLE)
107 abort ();
108 if (attr & BITSET_SPARSE && attr & BITSET_DENSE)
109 abort ();
110
111 /* Choose the type of bitset. Note that sometimes we will be asked
112 for a zero length fixed size bitset. */
113
114
115 /* If no attributes selected, choose a good compromise. */
116 if (!attr)
117 return BITSET_VARRAY;
118
119 if (attr & BITSET_SPARSE)
120 return BITSET_LIST;
121
122 if (attr & BITSET_FIXED)
123 return BITSET_ARRAY;
124
125 if (attr & BITSET_GREEDY)
126 return BITSET_TABLE;
127
128 return BITSET_VARRAY;
129 }
130
131
132 /* Create a bitset of N_BITS of type TYPE. */
133 bitset
bitset_alloc(bitset_bindex n_bits,enum bitset_type type)134 bitset_alloc (bitset_bindex n_bits, enum bitset_type type)
135 {
136 size_t bytes;
137 bitset bset;
138
139 bytes = bitset_bytes (type, n_bits);
140
141 bset = xcalloc (1, bytes);
142
143 /* The cache is disabled until some elements are allocated. If we
144 have variable length arrays, then we may need to allocate a dummy
145 element. */
146
147 return bitset_init (bset, n_bits, type);
148 }
149
150
151 /* Create a bitset of N_BITS of type TYPE. */
152 bitset
bitset_obstack_alloc(struct obstack * bobstack,bitset_bindex n_bits,enum bitset_type type)153 bitset_obstack_alloc (struct obstack *bobstack,
154 bitset_bindex n_bits, enum bitset_type type)
155 {
156 size_t bytes;
157 bitset bset;
158
159 bytes = bitset_bytes (type, n_bits);
160
161 bset = obstack_alloc (bobstack, bytes);
162 memset (bset, 0, bytes);
163
164 return bitset_init (bset, n_bits, type);
165 }
166
167
168 /* Create a bitset of N_BITS and with attribute hints specified by
169 ATTR. */
170 bitset
bitset_create(bitset_bindex n_bits,unsigned int attr)171 bitset_create (bitset_bindex n_bits, unsigned int attr)
172 {
173 enum bitset_type type;
174
175 type = bitset_type_choose (n_bits, attr);
176
177 return bitset_alloc (n_bits, type);
178 }
179
180
181 /* Free bitset BSET. */
182 void
bitset_free(bitset bset)183 bitset_free (bitset bset)
184 {
185 BITSET_FREE_ (bset);
186 free (bset);
187 }
188
189
190 /* Free bitset BSET allocated on obstack. */
191 void
bitset_obstack_free(bitset bset)192 bitset_obstack_free (bitset bset)
193 {
194 BITSET_FREE_ (bset);
195 }
196
197
198 /* Return bitset type. */
199 enum bitset_type
bitset_type_get(bitset bset)200 bitset_type_get (bitset bset)
201 {
202 enum bitset_type type;
203
204 type = BITSET_TYPE_ (bset);
205 if (type != BITSET_STATS)
206 return type;
207
208 return bitset_stats_type_get (bset);
209 }
210
211
212 /* Return name of bitset type. */
213 const char *
bitset_type_name_get(bitset bset)214 bitset_type_name_get (bitset bset)
215 {
216 enum bitset_type type;
217
218 type = bitset_type_get (bset);
219
220 return bitset_type_names[type];
221 }
222
223
224 /* Find next bit set in SRC starting from and including BITNO.
225 Return BITSET_BINDEX_MAX if SRC empty. */
226 bitset_bindex
bitset_next(bitset src,bitset_bindex bitno)227 bitset_next (bitset src, bitset_bindex bitno)
228 {
229 bitset_bindex val;
230 bitset_bindex next = bitno;
231
232 if (!bitset_list (src, &val, 1, &next))
233 return BITSET_BINDEX_MAX;
234 return val;
235 }
236
237
238 /* Return true if both bitsets are of the same type and size. */
239 extern bool
bitset_compatible_p(bitset bset1,bitset bset2)240 bitset_compatible_p (bitset bset1, bitset bset2)
241 {
242 return BITSET_COMPATIBLE_ (bset1, bset2);
243 }
244
245
246 /* Find previous bit set in SRC starting from and including BITNO.
247 Return BITSET_BINDEX_MAX if SRC empty. */
248 bitset_bindex
bitset_prev(bitset src,bitset_bindex bitno)249 bitset_prev (bitset src, bitset_bindex bitno)
250 {
251 bitset_bindex val;
252 bitset_bindex next = bitno;
253
254 if (!bitset_list_reverse (src, &val, 1, &next))
255 return BITSET_BINDEX_MAX;
256 return val;
257 }
258
259
260 /* Find first set bit. */
261 bitset_bindex
bitset_first(bitset src)262 bitset_first (bitset src)
263 {
264 return bitset_next (src, 0);
265 }
266
267
268 /* Find last set bit. */
269 bitset_bindex
bitset_last(bitset src)270 bitset_last (bitset src)
271 {
272 return bitset_prev (src, 0);
273 }
274
275
276 /* Is BITNO in SRC the only set bit? */
277 bool
bitset_only_set_p(bitset src,bitset_bindex bitno)278 bitset_only_set_p (bitset src, bitset_bindex bitno)
279 {
280 bitset_bindex val[2];
281 bitset_bindex next = 0;
282
283 if (bitset_list (src, val, 2, &next) != 1)
284 return false;
285 return val[0] == bitno;
286 }
287
288
289 /* Print contents of bitset BSET to FILE. */
290 static void
bitset_print(FILE * file,bitset bset,bool verbose)291 bitset_print (FILE *file, bitset bset, bool verbose)
292 {
293 unsigned int pos;
294 bitset_bindex i;
295 bitset_iterator iter;
296
297 if (verbose)
298 fprintf (file, "n_bits = %lu, set = {",
299 (unsigned long int) bitset_size (bset));
300
301 pos = 30;
302 BITSET_FOR_EACH (iter, bset, i, 0)
303 {
304 if (pos > 70)
305 {
306 fprintf (file, "\n");
307 pos = 0;
308 }
309
310 fprintf (file, "%lu ", (unsigned long int) i);
311 pos += 1 + (i >= 10) + (i >= 100);
312 };
313
314 if (verbose)
315 fprintf (file, "}\n");
316 }
317
318
319 /* Dump bitset BSET to FILE. */
320 void
bitset_dump(FILE * file,bitset bset)321 bitset_dump (FILE *file, bitset bset)
322 {
323 bitset_print (file, bset, false);
324 }
325
326
327 /* Release memory associated with bitsets. */
328 void
bitset_release_memory(void)329 bitset_release_memory (void)
330 {
331 lbitset_release_memory ();
332 ebitset_release_memory ();
333 }
334
335
336 /* Toggle bit BITNO in bitset BSET and the new value of the bit. */
337 bool
bitset_toggle_(bitset bset,bitset_bindex bitno)338 bitset_toggle_ (bitset bset, bitset_bindex bitno)
339 {
340 /* This routine is for completeness. It could be optimized if
341 required. */
342 if (bitset_test (bset, bitno))
343 {
344 bitset_reset (bset, bitno);
345 return false;
346 }
347 else
348 {
349 bitset_set (bset, bitno);
350 return true;
351 }
352 }
353
354
355 /* Return number of bits in bitset SRC. */
356 bitset_bindex
bitset_size_(bitset src)357 bitset_size_ (bitset src)
358 {
359 return BITSET_NBITS_ (src);
360 }
361
362
363 /* Return number of bits set in bitset SRC. */
364 bitset_bindex
bitset_count_(bitset src)365 bitset_count_ (bitset src)
366 {
367 bitset_bindex list[BITSET_LIST_SIZE];
368 bitset_bindex next;
369 bitset_bindex num;
370 bitset_bindex count;
371
372 /* This could be greatly sped up by adding a count method for each
373 bitset implementation that uses a direct technique (based on
374 masks) for counting the number of bits set in a word. */
375
376 next = 0;
377 for (count = 0; (num = bitset_list (src, list, BITSET_LIST_SIZE, &next));
378 count += num)
379 continue;
380
381 return count;
382 }
383
384
385 /* DST = SRC. Return true if DST != SRC.
386 This is a fallback for the case where SRC and DST are different
387 bitset types. */
388 bool
bitset_copy_(bitset dst,bitset src)389 bitset_copy_ (bitset dst, bitset src)
390 {
391 bitset_bindex i;
392 bitset_iterator iter;
393
394 /* Convert bitset types. We assume that the DST bitset
395 is large enough to hold the SRC bitset. */
396 bitset_zero (dst);
397 BITSET_FOR_EACH (iter, src, i, 0)
398 {
399 bitset_set (dst, i);
400 };
401
402 return true;
403 }
404
405
406 /* This is a fallback for implementations that do not support
407 four operand operations. */
408 static inline bool
bitset_op4_cmp(bitset dst,bitset src1,bitset src2,bitset src3,enum bitset_ops op)409 bitset_op4_cmp (bitset dst, bitset src1, bitset src2, bitset src3,
410 enum bitset_ops op)
411 {
412 bool changed = false;
413 bool stats_enabled_save;
414 bitset tmp;
415
416 /* Create temporary bitset. */
417 stats_enabled_save = bitset_stats_enabled;
418 bitset_stats_enabled = false;
419 tmp = bitset_alloc (0, bitset_type_get (dst));
420 bitset_stats_enabled = stats_enabled_save;
421
422 switch (op)
423 {
424 default:
425 abort ();
426
427 case BITSET_OP_OR_AND:
428 bitset_or (tmp, src1, src2);
429 changed = bitset_and_cmp (dst, src3, tmp);
430 break;
431
432 case BITSET_OP_AND_OR:
433 bitset_and (tmp, src1, src2);
434 changed = bitset_or_cmp (dst, src3, tmp);
435 break;
436
437 case BITSET_OP_ANDN_OR:
438 bitset_andn (tmp, src1, src2);
439 changed = bitset_or_cmp (dst, src3, tmp);
440 break;
441 }
442
443 bitset_free (tmp);
444 return changed;
445 }
446
447
448 /* DST = (SRC1 & SRC2) | SRC3. */
449 void
bitset_and_or_(bitset dst,bitset src1,bitset src2,bitset src3)450 bitset_and_or_ (bitset dst, bitset src1, bitset src2, bitset src3)
451 {
452 bitset_and_or_cmp_ (dst, src1, src2, src3);
453 }
454
455
456 /* DST = (SRC1 & SRC2) | SRC3. Return non-zero if
457 DST != (SRC1 & SRC2) | SRC3. */
458 bool
bitset_and_or_cmp_(bitset dst,bitset src1,bitset src2,bitset src3)459 bitset_and_or_cmp_ (bitset dst, bitset src1, bitset src2, bitset src3)
460 {
461 return bitset_op4_cmp (dst, src1, src2, src3, BITSET_OP_AND_OR);
462 }
463
464
465 /* DST = (SRC1 & ~SRC2) | SRC3. */
466 void
bitset_andn_or_(bitset dst,bitset src1,bitset src2,bitset src3)467 bitset_andn_or_ (bitset dst, bitset src1, bitset src2, bitset src3)
468 {
469 bitset_andn_or_cmp_ (dst, src1, src2, src3);
470 }
471
472
473 /* DST = (SRC1 & ~SRC2) | SRC3. Return non-zero if
474 DST != (SRC1 & ~SRC2) | SRC3. */
475 bool
bitset_andn_or_cmp_(bitset dst,bitset src1,bitset src2,bitset src3)476 bitset_andn_or_cmp_ (bitset dst, bitset src1, bitset src2, bitset src3)
477 {
478 return bitset_op4_cmp (dst, src1, src2, src3, BITSET_OP_ANDN_OR);
479 }
480
481
482 /* DST = (SRC1 | SRC2) & SRC3. */
483 void
bitset_or_and_(bitset dst,bitset src1,bitset src2,bitset src3)484 bitset_or_and_ (bitset dst, bitset src1, bitset src2, bitset src3)
485 {
486 bitset_or_and_cmp_ (dst, src1, src2, src3);
487 }
488
489
490 /* DST = (SRC1 | SRC2) & SRC3. Return non-zero if
491 DST != (SRC1 | SRC2) & SRC3. */
492 bool
bitset_or_and_cmp_(bitset dst,bitset src1,bitset src2,bitset src3)493 bitset_or_and_cmp_ (bitset dst, bitset src1, bitset src2, bitset src3)
494 {
495 return bitset_op4_cmp (dst, src1, src2, src3, BITSET_OP_OR_AND);
496 }
497
498
499 /* Function to be called from debugger to print bitset. */
500 void
debug_bitset(bitset bset)501 debug_bitset (bitset bset)
502 {
503 if (bset)
504 bitset_print (stderr, bset, true);
505 }
506