findprog-in: Relicense under LGPLv2+.
[gnulib.git] / lib / bitset / table.c
blob16781958a7c1fb637aa08cc365995ee9e690e63c
1 /* Functions to support expandable bitsets.
3 Copyright (C) 2002-2006, 2009-2015, 2018-2020 Free Software Foundation, Inc.
5 Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
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.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>. */
20 #include <config.h>
22 #include "bitset/table.h"
24 #include <stdlib.h>
25 #include <string.h>
27 #include "obstack.h"
28 #include "xalloc.h"
30 /* This file implements expandable bitsets. These bitsets can be of
31 arbitrary length and are more efficient than arrays of bits for
32 large sparse sets.
34 Empty elements are represented by a NULL pointer in the table of
35 element pointers. An alternative is to point to a special zero
36 element. Similarly, we could represent an all 1's element with
37 another special ones element pointer.
39 Bitsets are commonly empty so we need to ensure that this special
40 case is fast. A zero bitset is indicated when cdata is 0. This is
41 conservative since cdata may be non zero and the bitset may still
42 be zero.
44 The bitset cache can be disabled either by setting cindex to
45 BITSET_WINDEX_MAX or by setting csize to 0. Here
46 we use the former approach since cindex needs to be updated whenever
47 cdata is changed.
51 /* Number of words to use for each element. */
52 #define TBITSET_ELT_WORDS 2
54 /* Number of bits stored in each element. */
55 #define TBITSET_ELT_BITS \
56 ((unsigned) (TBITSET_ELT_WORDS * BITSET_WORD_BITS))
58 /* Tbitset element. We use an array of bits. */
59 typedef struct tbitset_elt_struct
61 union
63 bitset_word words[TBITSET_ELT_WORDS]; /* Bits that are set. */
64 struct tbitset_elt_struct *next;
68 tbitset_elt;
71 typedef tbitset_elt *tbitset_elts;
74 /* Number of elements to initially allocate. */
76 #ifndef TBITSET_INITIAL_SIZE
77 # define TBITSET_INITIAL_SIZE 2
78 #endif
81 enum tbitset_find_mode
82 { TBITSET_FIND, TBITSET_CREATE, TBITSET_SUBST };
84 static tbitset_elt tbitset_zero_elts[1]; /* Elements of all zero bits. */
86 /* Obstack to allocate bitset elements from. */
87 static struct obstack tbitset_obstack;
88 static bool tbitset_obstack_init = false;
89 static tbitset_elt *tbitset_free_list; /* Free list of bitset elements. */
91 #define TBITSET_N_ELTS(N) (((N) + TBITSET_ELT_BITS - 1) / TBITSET_ELT_BITS)
92 #define TBITSET_ELTS(BSET) ((BSET)->e.elts)
93 #define TBITSET_SIZE(BSET) TBITSET_N_ELTS (BITSET_NBITS_ (BSET))
94 #define TBITSET_ASIZE(BSET) ((BSET)->e.size)
96 #define TBITSET_NEXT(ELT) ((ELT)->u.next)
97 #define TBITSET_WORDS(ELT) ((ELT)->u.words)
99 /* Disable bitset cache and mark BSET as being zero. */
100 #define TBITSET_ZERO_SET(BSET) ((BSET)->b.cindex = BITSET_WINDEX_MAX, \
101 (BSET)->b.cdata = 0)
103 #define TBITSET_CACHE_DISABLE(BSET) ((BSET)->b.cindex = BITSET_WINDEX_MAX)
105 /* Disable bitset cache and mark BSET as being possibly non-zero. */
106 #define TBITSET_NONZERO_SET(BSET) \
107 (TBITSET_CACHE_DISABLE (BSET), (BSET)->b.cdata = (bitset_word *)~0)
109 /* A conservative estimate of whether the bitset is zero.
110 This is non-zero only if we know for sure that the bitset is zero. */
111 #define TBITSET_ZERO_P(BSET) ((BSET)->b.cdata == 0)
113 /* Enable cache to point to element with table index EINDEX.
114 The element must exist. */
115 #define TBITSET_CACHE_SET(BSET, EINDEX) \
116 ((BSET)->b.cindex = (EINDEX) * TBITSET_ELT_WORDS, \
117 (BSET)->b.cdata = TBITSET_WORDS (TBITSET_ELTS (BSET) [EINDEX]))
119 #undef min
120 #undef max
121 #define min(a, b) ((a) > (b) ? (b) : (a))
122 #define max(a, b) ((a) > (b) ? (a) : (b))
124 static bitset_bindex
125 tbitset_resize (bitset src, bitset_bindex n_bits)
127 if (n_bits == BITSET_NBITS_ (src))
128 return n_bits;
130 bitset_windex oldsize = TBITSET_SIZE (src);
131 bitset_windex newsize = TBITSET_N_ELTS (n_bits);
133 if (oldsize < newsize)
135 /* The bitset needs to grow. If we already have enough memory
136 allocated, then just zero what we need. */
137 if (newsize > TBITSET_ASIZE (src))
139 /* We need to allocate more memory. When oldsize is
140 non-zero this means that we are changing the size, so
141 grow the bitset 25% larger than requested to reduce
142 number of reallocations. */
144 bitset_windex size = oldsize == 0 ? newsize : newsize + newsize / 4;
145 TBITSET_ELTS (src)
146 = xrealloc (TBITSET_ELTS (src), size * sizeof (tbitset_elt *));
147 TBITSET_ASIZE (src) = size;
150 memset (TBITSET_ELTS (src) + oldsize, 0,
151 (newsize - oldsize) * sizeof (tbitset_elt *));
153 else
155 /* The bitset needs to shrink. There's no point deallocating
156 the memory unless it is shrinking by a reasonable amount. */
157 if ((oldsize - newsize) >= oldsize / 2)
159 void *p
160 = realloc (TBITSET_ELTS (src), newsize * sizeof (tbitset_elt *));
161 if (p)
163 TBITSET_ELTS (src) = p;
164 TBITSET_ASIZE (src) = newsize;
168 /* Need to prune any excess bits. FIXME. */
171 BITSET_NBITS_ (src) = n_bits;
172 return n_bits;
176 /* Allocate a tbitset element. The bits are not cleared. */
177 static inline tbitset_elt *
178 tbitset_elt_alloc (void)
180 tbitset_elt *elt;
182 if (tbitset_free_list != 0)
184 elt = tbitset_free_list;
185 tbitset_free_list = TBITSET_NEXT (elt);
187 else
189 if (!tbitset_obstack_init)
191 tbitset_obstack_init = true;
193 /* Let particular systems override the size of a chunk. */
195 #ifndef OBSTACK_CHUNK_SIZE
196 # define OBSTACK_CHUNK_SIZE 0
197 #endif
199 /* Let them override the alloc and free routines too. */
201 #ifndef OBSTACK_CHUNK_ALLOC
202 # define OBSTACK_CHUNK_ALLOC xmalloc
203 #endif
205 #ifndef OBSTACK_CHUNK_FREE
206 # define OBSTACK_CHUNK_FREE free
207 #endif
209 #if !(defined __GNUC__ || defined __clang__)
210 # define __alignof__(type) 0
211 #endif
213 obstack_specify_allocation (&tbitset_obstack, OBSTACK_CHUNK_SIZE,
214 __alignof__ (tbitset_elt),
215 OBSTACK_CHUNK_ALLOC,
216 OBSTACK_CHUNK_FREE);
219 /* Perhaps we should add a number of new elements to the free
220 list. */
221 elt = (tbitset_elt *) obstack_alloc (&tbitset_obstack,
222 sizeof (tbitset_elt));
225 return elt;
229 /* Allocate a tbitset element. The bits are cleared. */
230 static inline tbitset_elt *
231 tbitset_elt_calloc (void)
233 tbitset_elt *elt = tbitset_elt_alloc ();
234 memset (TBITSET_WORDS (elt), 0, sizeof (TBITSET_WORDS (elt)));
235 return elt;
239 static inline void
240 tbitset_elt_free (tbitset_elt *elt)
242 TBITSET_NEXT (elt) = tbitset_free_list;
243 tbitset_free_list = elt;
247 /* Remove element with index EINDEX from bitset BSET. */
248 static inline void
249 tbitset_elt_remove (bitset bset, bitset_windex eindex)
251 tbitset_elts *elts = TBITSET_ELTS (bset);
252 tbitset_elt *elt = elts[eindex];
254 elts[eindex] = 0;
255 tbitset_elt_free (elt);
259 /* Add ELT into elts at index EINDEX of bitset BSET. */
260 static inline void
261 tbitset_elt_add (bitset bset, tbitset_elt *elt, bitset_windex eindex)
263 tbitset_elts *elts = TBITSET_ELTS (bset);
264 /* Assume that the elts entry not allocated. */
265 elts[eindex] = elt;
269 /* Are all bits in an element zero? */
270 static inline bool
271 tbitset_elt_zero_p (tbitset_elt *elt)
273 for (int i = 0; i < TBITSET_ELT_WORDS; i++)
274 if (TBITSET_WORDS (elt)[i])
275 return false;
276 return true;
280 static tbitset_elt *
281 tbitset_elt_find (bitset bset, bitset_bindex bindex,
282 enum tbitset_find_mode mode)
284 bitset_windex eindex = bindex / TBITSET_ELT_BITS;
286 tbitset_elts *elts = TBITSET_ELTS (bset);
287 bitset_windex size = TBITSET_SIZE (bset);
289 if (eindex < size)
291 tbitset_elt *elt = elts[eindex];
292 if (elt)
294 if (TBITSET_WORDS (elt) != bset->b.cdata)
295 TBITSET_CACHE_SET (bset, eindex);
296 return elt;
300 /* The element could not be found. */
302 switch (mode)
304 default:
305 abort ();
307 case TBITSET_FIND:
308 return NULL;
310 case TBITSET_CREATE:
311 if (eindex >= size)
312 tbitset_resize (bset, bindex);
314 /* Create a new element. */
316 tbitset_elt *elt = tbitset_elt_calloc ();
317 tbitset_elt_add (bset, elt, eindex);
318 TBITSET_CACHE_SET (bset, eindex);
319 return elt;
322 case TBITSET_SUBST:
323 return &tbitset_zero_elts[0];
328 /* Weed out the zero elements from the elts. */
329 static inline bitset_windex
330 tbitset_weed (bitset bset)
332 if (TBITSET_ZERO_P (bset))
333 return 0;
335 tbitset_elts *elts = TBITSET_ELTS (bset);
336 bitset_windex count = 0;
337 bitset_windex j;
338 for (j = 0; j < TBITSET_SIZE (bset); j++)
340 tbitset_elt *elt = elts[j];
342 if (elt)
344 if (tbitset_elt_zero_p (elt))
346 tbitset_elt_remove (bset, j);
347 count++;
350 else
351 count++;
354 count = j - count;
355 if (!count)
357 /* All the bits are zero. We could shrink the elts.
358 For now just mark BSET as known to be zero. */
359 TBITSET_ZERO_SET (bset);
361 else
362 TBITSET_NONZERO_SET (bset);
364 return count;
368 /* Set all bits in the bitset to zero. */
369 static inline void
370 tbitset_zero (bitset bset)
372 if (TBITSET_ZERO_P (bset))
373 return;
375 tbitset_elts *elts = TBITSET_ELTS (bset);
376 for (bitset_windex j = 0; j < TBITSET_SIZE (bset); j++)
378 tbitset_elt *elt = elts[j];
379 if (elt)
380 tbitset_elt_remove (bset, j);
383 /* All the bits are zero. We could shrink the elts.
384 For now just mark BSET as known to be zero. */
385 TBITSET_ZERO_SET (bset);
389 static inline bool
390 tbitset_equal_p (bitset dst, bitset src)
392 if (src == dst)
393 return true;
395 tbitset_weed (dst);
396 tbitset_weed (src);
398 if (TBITSET_SIZE (src) != TBITSET_SIZE (dst))
399 return false;
401 tbitset_elts *selts = TBITSET_ELTS (src);
402 tbitset_elts *delts = TBITSET_ELTS (dst);
404 for (bitset_windex j = 0; j < TBITSET_SIZE (src); j++)
406 tbitset_elt *selt = selts[j];
407 tbitset_elt *delt = delts[j];
409 if (!selt && !delt)
410 continue;
411 if ((selt && !delt) || (!selt && delt))
412 return false;
414 for (unsigned i = 0; i < TBITSET_ELT_WORDS; i++)
415 if (TBITSET_WORDS (selt)[i] != TBITSET_WORDS (delt)[i])
416 return false;
418 return true;
422 /* Copy bits from bitset SRC to bitset DST. */
423 static inline void
424 tbitset_copy_ (bitset dst, bitset src)
426 if (src == dst)
427 return;
429 tbitset_zero (dst);
431 if (BITSET_NBITS_ (dst) != BITSET_NBITS_ (src))
432 tbitset_resize (dst, BITSET_NBITS_ (src));
434 tbitset_elts *selts = TBITSET_ELTS (src);
435 tbitset_elts *delts = TBITSET_ELTS (dst);
436 for (bitset_windex j = 0; j < TBITSET_SIZE (src); j++)
438 tbitset_elt *selt = selts[j];
439 if (selt)
441 tbitset_elt *tmp = tbitset_elt_alloc ();
442 delts[j] = tmp;
443 memcpy (TBITSET_WORDS (tmp), TBITSET_WORDS (selt),
444 sizeof (TBITSET_WORDS (selt)));
447 TBITSET_NONZERO_SET (dst);
451 /* Copy bits from bitset SRC to bitset DST. Return true if
452 bitsets different. */
453 static inline bool
454 tbitset_copy_cmp (bitset dst, bitset src)
456 if (src == dst)
457 return false;
459 if (TBITSET_ZERO_P (dst))
461 tbitset_copy_ (dst, src);
462 return !TBITSET_ZERO_P (src);
465 if (tbitset_equal_p (dst, src))
466 return false;
468 tbitset_copy_ (dst, src);
469 return true;
473 /* Set bit BITNO in bitset DST. */
474 static void
475 tbitset_set (bitset dst, bitset_bindex bitno)
477 bitset_windex windex = bitno / BITSET_WORD_BITS;
479 tbitset_elt_find (dst, bitno, TBITSET_CREATE);
481 dst->b.cdata[windex - dst->b.cindex] |=
482 (bitset_word) 1 << (bitno % BITSET_WORD_BITS);
486 /* Reset bit BITNO in bitset DST. */
487 static void
488 tbitset_reset (bitset dst, bitset_bindex bitno)
490 bitset_windex windex = bitno / BITSET_WORD_BITS;
492 if (!tbitset_elt_find (dst, bitno, TBITSET_FIND))
493 return;
495 dst->b.cdata[windex - dst->b.cindex] &=
496 ~((bitset_word) 1 << (bitno % BITSET_WORD_BITS));
498 /* If all the data is zero, perhaps we should remove it now...
499 However, there is a good chance that the element will be needed
500 again soon. */
504 /* Test bit BITNO in bitset SRC. */
505 static bool
506 tbitset_test (bitset src, bitset_bindex bitno)
508 bitset_windex windex = bitno / BITSET_WORD_BITS;
510 return (tbitset_elt_find (src, bitno, TBITSET_FIND)
511 && ((src->b.cdata[windex - src->b.cindex]
512 >> (bitno % BITSET_WORD_BITS))
513 & 1));
517 static void
518 tbitset_free (bitset bset)
520 tbitset_zero (bset);
521 free (TBITSET_ELTS (bset));
525 /* Find list of up to NUM bits set in BSET starting from and including
526 *NEXT and store in array LIST. Return with actual number of bits
527 found and with *NEXT indicating where search stopped. */
528 static bitset_bindex
529 tbitset_list_reverse (bitset bset, bitset_bindex *list,
530 bitset_bindex num, bitset_bindex *next)
532 if (TBITSET_ZERO_P (bset))
533 return 0;
535 bitset_windex size = TBITSET_SIZE (bset);
536 bitset_bindex n_bits = size * TBITSET_ELT_BITS;
537 bitset_bindex rbitno = *next;
539 if (rbitno >= n_bits)
540 return 0;
542 tbitset_elts *elts = TBITSET_ELTS (bset);
544 bitset_bindex bitno = n_bits - (rbitno + 1);
546 bitset_windex windex = bitno / BITSET_WORD_BITS;
547 bitset_windex eindex = bitno / TBITSET_ELT_BITS;
548 bitset_windex woffset = windex - eindex * TBITSET_ELT_WORDS;
550 /* If num is 1, we could speed things up with a binary search
551 of the word of interest. */
552 bitset_bindex count = 0;
553 unsigned bitcnt = bitno % BITSET_WORD_BITS;
554 bitset_bindex bitoff = windex * BITSET_WORD_BITS;
558 tbitset_elt *elt = elts[eindex];
559 if (elt)
561 bitset_word *srcp = TBITSET_WORDS (elt);
565 bitset_word word = srcp[woffset];
566 if (bitcnt + 1 < BITSET_WORD_BITS)
567 /* We're starting in the middle of a word: smash bits to ignore. */
568 word &= ((bitset_word) 1 << (bitcnt + 1)) - 1;
569 BITSET_FOR_EACH_BIT_REVERSE(pos, word)
571 list[count++] = bitoff + pos;
572 if (count >= num)
574 *next = n_bits - (bitoff + pos);
575 return count;
578 bitoff -= BITSET_WORD_BITS;
579 bitcnt = BITSET_WORD_BITS - 1;
581 while (woffset--);
584 woffset = TBITSET_ELT_WORDS - 1;
585 bitoff = eindex * TBITSET_ELT_BITS - BITSET_WORD_BITS;
587 while (eindex--);
589 *next = n_bits - (bitoff + 1);
590 return count;
594 /* Find list of up to NUM bits set in BSET starting from and including
595 *NEXT and store in array LIST. Return with actual number of bits
596 found and with *NEXT indicating where search stopped. */
597 static bitset_bindex
598 tbitset_list (bitset bset, bitset_bindex *list,
599 bitset_bindex num, bitset_bindex *next)
601 if (TBITSET_ZERO_P (bset))
602 return 0;
604 bitset_bindex bitno = *next;
605 bitset_bindex count = 0;
607 tbitset_elts *elts = TBITSET_ELTS (bset);
608 bitset_windex size = TBITSET_SIZE (bset);
609 bitset_windex eindex = bitno / TBITSET_ELT_BITS;
611 if (bitno % TBITSET_ELT_BITS)
613 /* We need to start within an element. This is not very common. */
614 tbitset_elt *elt = elts[eindex];
615 if (elt)
617 bitset_word *srcp = TBITSET_WORDS (elt);
618 bitset_windex woffset = eindex * TBITSET_ELT_WORDS;
620 for (bitset_windex windex = bitno / BITSET_WORD_BITS;
621 (windex - woffset) < TBITSET_ELT_WORDS; windex++)
623 bitset_word word = srcp[windex - woffset] >> (bitno % BITSET_WORD_BITS);
625 BITSET_FOR_EACH_BIT (pos, word)
627 list[count++] = bitno + pos;
628 if (count >= num)
630 *next = bitno + pos + 1;
631 return count;
634 bitno = (windex + 1) * BITSET_WORD_BITS;
638 /* Skip to next element. */
639 eindex++;
642 /* If num is 1, we could speed things up with a binary search
643 of the word of interest. */
645 for (; eindex < size; eindex++)
647 tbitset_elt *elt = elts[eindex];
648 if (!elt)
649 continue;
651 bitset_word *srcp = TBITSET_WORDS (elt);
652 bitset_windex windex = eindex * TBITSET_ELT_WORDS;
653 bitno = windex * BITSET_WORD_BITS;
655 /* Is there enough room to avoid checking in each iteration? */
656 if ((count + TBITSET_ELT_BITS) < num)
658 /* The coast is clear, plant boot! */
660 #if TBITSET_ELT_WORDS == 2
661 bitset_word word = srcp[0];
662 if (word)
663 BITSET_FOR_EACH_BIT (pos, word)
664 list[count++] = bitno + pos;
665 windex++;
666 bitno = windex * BITSET_WORD_BITS;
668 word = srcp[1];
669 if (word)
670 BITSET_FOR_EACH_BIT (pos, word)
671 list[count++] = bitno + pos;
672 windex++;
673 bitno = windex * BITSET_WORD_BITS;
674 #else
675 for (int i = 0; i < TBITSET_ELT_WORDS; i++, windex++)
677 bitset_word word = srcp[i];
678 if (word)
679 BITSET_FOR_EACH_BIT (pos, word)
680 list[count++] = bitno + pos;
681 bitno = windex * BITSET_WORD_BITS;
683 #endif
685 else
687 /* Tread more carefully since we need to check
688 if array overflows. */
689 for (int i = 0; i < TBITSET_ELT_WORDS; i++)
691 bitset_word word = srcp[i];
692 if (word)
693 BITSET_FOR_EACH_BIT (pos, word)
695 list[count++] = bitno + pos;
696 if (count >= num)
698 *next = bitno + pos + 1;
699 return count;
702 windex++;
703 bitno = windex * BITSET_WORD_BITS;
708 *next = bitno;
709 return count;
713 /* Ensure that any unused bits within the last element are clear. */
714 static inline void
715 tbitset_unused_clear (bitset dst)
717 bitset_bindex n_bits = BITSET_NBITS_ (dst);
718 unsigned last_bit = n_bits % TBITSET_ELT_BITS;
720 if (last_bit)
722 tbitset_elts *elts = TBITSET_ELTS (dst);
724 bitset_windex eindex = n_bits / TBITSET_ELT_BITS;
726 tbitset_elt *elt = elts[eindex];
727 if (elt)
729 bitset_word *srcp = TBITSET_WORDS (elt);
731 bitset_windex windex = n_bits / BITSET_WORD_BITS;
732 bitset_windex woffset = eindex * TBITSET_ELT_WORDS;
734 srcp[windex - woffset]
735 &= ((bitset_word) 1 << (last_bit % BITSET_WORD_BITS)) - 1;
736 windex++;
737 for (; (windex - woffset) < TBITSET_ELT_WORDS; windex++)
738 srcp[windex - woffset] = 0;
744 static void
745 tbitset_ones (bitset dst)
747 for (bitset_windex j = 0; j < TBITSET_SIZE (dst); j++)
749 /* Create new elements if they cannot be found. Perhaps
750 we should just add pointers to a ones element? */
751 tbitset_elt *elt =
752 tbitset_elt_find (dst, j * TBITSET_ELT_BITS, TBITSET_CREATE);
753 memset (TBITSET_WORDS (elt), -1, sizeof (TBITSET_WORDS (elt)));
755 TBITSET_NONZERO_SET (dst);
756 tbitset_unused_clear (dst);
760 static bool
761 tbitset_empty_p (bitset dst)
763 if (TBITSET_ZERO_P (dst))
764 return true;
766 tbitset_elts *elts = TBITSET_ELTS (dst);
767 for (bitset_windex j = 0; j < TBITSET_SIZE (dst); j++)
769 tbitset_elt *elt = elts[j];
771 if (elt)
773 if (!tbitset_elt_zero_p (elt))
774 return false;
775 /* Do some weeding as we go. */
776 tbitset_elt_remove (dst, j);
780 /* All the bits are zero. We could shrink the elts.
781 For now just mark DST as known to be zero. */
782 TBITSET_ZERO_SET (dst);
783 return true;
787 static void
788 tbitset_not (bitset dst, bitset src)
790 tbitset_resize (dst, BITSET_NBITS_ (src));
792 for (bitset_windex j = 0; j < TBITSET_SIZE (src); j++)
794 /* Create new elements for dst if they cannot be found
795 or substitute zero elements if src elements not found. */
796 tbitset_elt *selt =
797 tbitset_elt_find (src, j * TBITSET_ELT_BITS, TBITSET_SUBST);
798 tbitset_elt *delt =
799 tbitset_elt_find (dst, j * TBITSET_ELT_BITS, TBITSET_CREATE);
801 for (unsigned i = 0; i < TBITSET_ELT_WORDS; i++)
802 TBITSET_WORDS (delt)[i] = ~TBITSET_WORDS (selt)[i];
804 TBITSET_NONZERO_SET (dst);
805 tbitset_unused_clear (dst);
809 /* Is DST == DST | SRC? */
810 static bool
811 tbitset_subset_p (bitset dst, bitset src)
813 tbitset_elts *selts = TBITSET_ELTS (src);
814 tbitset_elts *delts = TBITSET_ELTS (dst);
816 bitset_windex ssize = TBITSET_SIZE (src);
817 bitset_windex dsize = TBITSET_SIZE (dst);
819 for (bitset_windex j = 0; j < ssize; j++)
821 tbitset_elt *selt = j < ssize ? selts[j] : 0;
822 tbitset_elt *delt = j < dsize ? delts[j] : 0;
824 if (!selt && !delt)
825 continue;
827 if (!selt)
828 selt = &tbitset_zero_elts[0];
829 if (!delt)
830 delt = &tbitset_zero_elts[0];
832 for (unsigned i = 0; i < TBITSET_ELT_WORDS; i++)
833 if (TBITSET_WORDS (delt)[i]
834 != (TBITSET_WORDS (selt)[i] | TBITSET_WORDS (delt)[i]))
835 return false;
837 return true;
841 /* Is DST & SRC == 0? */
842 static bool
843 tbitset_disjoint_p (bitset dst, bitset src)
845 tbitset_elts *selts = TBITSET_ELTS (src);
846 tbitset_elts *delts = TBITSET_ELTS (dst);
848 bitset_windex ssize = TBITSET_SIZE (src);
849 bitset_windex dsize = TBITSET_SIZE (dst);
851 for (bitset_windex j = 0; j < ssize; j++)
853 tbitset_elt *selt = j < ssize ? selts[j] : 0;
854 tbitset_elt *delt = j < dsize ? delts[j] : 0;
856 if (!selt || !delt)
857 continue;
859 for (unsigned i = 0; i < TBITSET_ELT_WORDS; i++)
860 if ((TBITSET_WORDS (selt)[i] & TBITSET_WORDS (delt)[i]))
861 return false;
863 return true;
868 static bool
869 tbitset_op3_cmp (bitset dst, bitset src1, bitset src2, enum bitset_ops op)
871 bool changed = false;
873 tbitset_resize (dst, max (BITSET_NBITS_ (src1), BITSET_NBITS_ (src2)));
875 bitset_windex ssize1 = TBITSET_SIZE (src1);
876 bitset_windex ssize2 = TBITSET_SIZE (src2);
877 bitset_windex dsize = TBITSET_SIZE (dst);
878 bitset_windex size = ssize1;
879 if (size < ssize2)
880 size = ssize2;
882 tbitset_elts *selts1 = TBITSET_ELTS (src1);
883 tbitset_elts *selts2 = TBITSET_ELTS (src2);
884 tbitset_elts *delts = TBITSET_ELTS (dst);
886 bitset_windex j = 0;
887 for (j = 0; j < size; j++)
889 tbitset_elt *selt1 = j < ssize1 ? selts1[j] : 0;
890 tbitset_elt *selt2 = j < ssize2 ? selts2[j] : 0;
891 tbitset_elt *delt = j < dsize ? delts[j] : 0;
893 if (!selt1 && !selt2)
895 if (delt)
897 changed = true;
898 tbitset_elt_remove (dst, j);
900 continue;
903 if (!selt1)
904 selt1 = &tbitset_zero_elts[0];
905 if (!selt2)
906 selt2 = &tbitset_zero_elts[0];
907 if (!delt)
908 delt = tbitset_elt_calloc ();
909 else
910 delts[j] = 0;
912 bitset_word *srcp1 = TBITSET_WORDS (selt1);
913 bitset_word *srcp2 = TBITSET_WORDS (selt2);
914 bitset_word *dstp = TBITSET_WORDS (delt);
915 switch (op)
917 default:
918 abort ();
920 case BITSET_OP_OR:
921 for (unsigned i = 0; i < TBITSET_ELT_WORDS; i++, dstp++)
923 bitset_word tmp = *srcp1++ | *srcp2++;
925 if (*dstp != tmp)
927 changed = true;
928 *dstp = tmp;
931 break;
933 case BITSET_OP_AND:
934 for (unsigned i = 0; i < TBITSET_ELT_WORDS; i++, dstp++)
936 bitset_word tmp = *srcp1++ & *srcp2++;
938 if (*dstp != tmp)
940 changed = true;
941 *dstp = tmp;
944 break;
946 case BITSET_OP_XOR:
947 for (unsigned i = 0; i < TBITSET_ELT_WORDS; i++, dstp++)
949 bitset_word tmp = *srcp1++ ^ *srcp2++;
951 if (*dstp != tmp)
953 changed = true;
954 *dstp = tmp;
957 break;
959 case BITSET_OP_ANDN:
960 for (unsigned i = 0; i < TBITSET_ELT_WORDS; i++, dstp++)
962 bitset_word tmp = *srcp1++ & ~(*srcp2++);
964 if (*dstp != tmp)
966 changed = true;
967 *dstp = tmp;
970 break;
973 if (!tbitset_elt_zero_p (delt))
974 tbitset_elt_add (dst, delt, j);
975 else
976 tbitset_elt_free (delt);
979 /* If we have elements of DST left over, free them all. */
980 for (; j < dsize; j++)
982 changed = true;
984 tbitset_elt *delt = delts[j];
985 if (delt)
986 tbitset_elt_remove (dst, j);
989 TBITSET_NONZERO_SET (dst);
990 return changed;
994 static bool
995 tbitset_and_cmp (bitset dst, bitset src1, bitset src2)
997 if (TBITSET_ZERO_P (src2))
999 tbitset_weed (dst);
1000 bool changed = TBITSET_ZERO_P (dst);
1001 tbitset_zero (dst);
1002 return changed;
1004 else if (TBITSET_ZERO_P (src1))
1006 tbitset_weed (dst);
1007 bool changed = TBITSET_ZERO_P (dst);
1008 tbitset_zero (dst);
1009 return changed;
1011 else
1012 return tbitset_op3_cmp (dst, src1, src2, BITSET_OP_AND);
1016 static void
1017 tbitset_and (bitset dst, bitset src1, bitset src2)
1019 tbitset_and_cmp (dst, src1, src2);
1023 static bool
1024 tbitset_andn_cmp (bitset dst, bitset src1, bitset src2)
1026 if (TBITSET_ZERO_P (src2))
1027 return tbitset_copy_cmp (dst, src1);
1028 else if (TBITSET_ZERO_P (src1))
1030 tbitset_weed (dst);
1031 bool changed = TBITSET_ZERO_P (dst);
1032 tbitset_zero (dst);
1033 return changed;
1035 else
1036 return tbitset_op3_cmp (dst, src1, src2, BITSET_OP_ANDN);
1040 static void
1041 tbitset_andn (bitset dst, bitset src1, bitset src2)
1043 tbitset_andn_cmp (dst, src1, src2);
1047 static bool
1048 tbitset_or_cmp (bitset dst, bitset src1, bitset src2)
1050 if (TBITSET_ZERO_P (src2))
1051 return tbitset_copy_cmp (dst, src1);
1052 else if (TBITSET_ZERO_P (src1))
1053 return tbitset_copy_cmp (dst, src2);
1054 else
1055 return tbitset_op3_cmp (dst, src1, src2, BITSET_OP_OR);
1059 static void
1060 tbitset_or (bitset dst, bitset src1, bitset src2)
1062 tbitset_or_cmp (dst, src1, src2);
1066 static bool
1067 tbitset_xor_cmp (bitset dst, bitset src1, bitset src2)
1069 if (TBITSET_ZERO_P (src2))
1070 return tbitset_copy_cmp (dst, src1);
1071 else if (TBITSET_ZERO_P (src1))
1072 return tbitset_copy_cmp (dst, src2);
1073 else
1074 return tbitset_op3_cmp (dst, src1, src2, BITSET_OP_XOR);
1078 static void
1079 tbitset_xor (bitset dst, bitset src1, bitset src2)
1081 tbitset_xor_cmp (dst, src1, src2);
1085 static void
1086 tbitset_copy (bitset dst, bitset src)
1088 if (BITSET_COMPATIBLE_ (dst, src))
1089 tbitset_copy_ (dst, src);
1090 else
1091 bitset_copy_ (dst, src);
1095 /* Vector of operations for linked-list bitsets. */
1096 struct bitset_vtable tbitset_vtable = {
1097 tbitset_set,
1098 tbitset_reset,
1099 bitset_toggle_,
1100 tbitset_test,
1101 tbitset_resize,
1102 bitset_size_,
1103 bitset_count_,
1104 tbitset_empty_p,
1105 tbitset_ones,
1106 tbitset_zero,
1107 tbitset_copy,
1108 tbitset_disjoint_p,
1109 tbitset_equal_p,
1110 tbitset_not,
1111 tbitset_subset_p,
1112 tbitset_and,
1113 tbitset_and_cmp,
1114 tbitset_andn,
1115 tbitset_andn_cmp,
1116 tbitset_or,
1117 tbitset_or_cmp,
1118 tbitset_xor,
1119 tbitset_xor_cmp,
1120 bitset_and_or_,
1121 bitset_and_or_cmp_,
1122 bitset_andn_or_,
1123 bitset_andn_or_cmp_,
1124 bitset_or_and_,
1125 bitset_or_and_cmp_,
1126 tbitset_list,
1127 tbitset_list_reverse,
1128 tbitset_free,
1129 BITSET_TABLE
1133 /* Return size of initial structure. */
1134 size_t
1135 tbitset_bytes (bitset_bindex n_bits MAYBE_UNUSED)
1137 return sizeof (struct tbitset_struct);
1141 /* Initialize a bitset. */
1143 bitset
1144 tbitset_init (bitset bset, bitset_bindex n_bits)
1146 bset->b.vtable = &tbitset_vtable;
1148 bset->b.csize = TBITSET_ELT_WORDS;
1150 TBITSET_ZERO_SET (bset);
1152 TBITSET_ASIZE (bset) = 0;
1153 TBITSET_ELTS (bset) = 0;
1154 tbitset_resize (bset, n_bits);
1156 return bset;
1160 void
1161 tbitset_release_memory (void)
1163 tbitset_free_list = 0;
1164 if (tbitset_obstack_init)
1166 tbitset_obstack_init = false;
1167 obstack_free (&tbitset_obstack, NULL);