1 /* General bitsets.
2 
3    Copyright (C) 2002-2006, 2009-2012 Free Software Foundation, Inc.
4 
5    Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
6 
7    This program is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #include <config.h>
21 
22 #include "bitset.h"
23 
24 #include <stdlib.h>
25 #include <string.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