24 |
#include "ebitset.h" |
#include "ebitset.h" |
25 |
#include "obstack.h" |
#include "obstack.h" |
26 |
#include <stdlib.h> |
#include <stdlib.h> |
27 |
|
#include <string.h> |
28 |
|
|
29 |
/* This file implements expandable bitsets. These bitsets can be of |
/* This file implements expandable bitsets. These bitsets can be of |
30 |
arbitrary length and are more efficient than arrays of bits for |
arbitrary length and are more efficient than arrays of bits for |
76 |
#define EBITSET_INITIAL_SIZE 2 |
#define EBITSET_INITIAL_SIZE 2 |
77 |
#endif |
#endif |
78 |
|
|
|
/* Minimum number of elements to grow table. */ |
|
|
|
|
|
#ifndef EBITSET_GROW_SIZE |
|
|
#define EBITSET_GROW_SIZE 4 |
|
|
#endif |
|
79 |
|
|
80 |
enum ebitset_find_mode |
enum ebitset_find_mode |
81 |
{ EBITSET_FIND, EBITSET_CREATE, EBITSET_SUBST }; |
{ EBITSET_FIND, EBITSET_CREATE, EBITSET_SUBST }; |
87 |
static bool ebitset_obstack_init = false; |
static bool ebitset_obstack_init = false; |
88 |
static ebitset_elt *ebitset_free_list; /* Free list of bitset elements. */ |
static ebitset_elt *ebitset_free_list; /* Free list of bitset elements. */ |
89 |
|
|
90 |
|
#define EBITSET_N_ELTS(N) (((N) + EBITSET_ELT_BITS - 1) / EBITSET_ELT_BITS) |
91 |
#define EBITSET_ELTS(BSET) ((BSET)->e.elts) |
#define EBITSET_ELTS(BSET) ((BSET)->e.elts) |
92 |
#define EBITSET_SIZE(BSET) ((BSET)->e.size) |
#define EBITSET_SIZE(BSET) EBITSET_N_ELTS (BITSET_NBITS_ (BSET)) |
93 |
|
#define EBITSET_ASIZE(BSET) ((BSET)->e.size) |
94 |
|
|
95 |
#define EBITSET_NEXT(ELT) ((ELT)->u.next) |
#define EBITSET_NEXT(ELT) ((ELT)->u.next) |
96 |
#define EBITSET_WORDS(ELT) ((ELT)->u.words) |
#define EBITSET_WORDS(ELT) ((ELT)->u.words) |
116 |
(BSET)->b.cdata = EBITSET_WORDS (EBITSET_ELTS (BSET) [EINDEX])) |
(BSET)->b.cdata = EBITSET_WORDS (EBITSET_ELTS (BSET) [EINDEX])) |
117 |
|
|
118 |
|
|
119 |
/* Grow the expandable table for BSET by SIZE elements. */ |
#define min(a, b) ((a) > (b) ? (b) : (a)) |
120 |
static void |
#define max(a, b) ((a) > (b) ? (a) : (b)) |
121 |
ebitset_elts_grow (bitset bset, bitset_windex size) |
|
122 |
|
|
123 |
|
static bitset_bindex |
124 |
|
ebitset_resize (bitset src, bitset_bindex n_bits) |
125 |
{ |
{ |
126 |
bitset_windex oldsize; |
bitset_windex oldsize; |
127 |
bitset_windex newsize; |
bitset_windex newsize; |
128 |
|
|
129 |
oldsize = EBITSET_SIZE (bset); |
if (n_bits == BITSET_NBITS_ (src)) |
130 |
newsize = oldsize + size; |
return n_bits; |
131 |
|
|
132 |
|
oldsize = EBITSET_SIZE (src); |
133 |
|
newsize = EBITSET_N_ELTS (n_bits); |
134 |
|
|
135 |
|
if (oldsize < newsize) |
136 |
|
{ |
137 |
|
bitset_windex size; |
138 |
|
|
139 |
|
/* The bitset needs to grow. If we already have enough memory |
140 |
|
allocated, then just zero what we need. */ |
141 |
|
if (newsize > EBITSET_ASIZE (src)) |
142 |
|
{ |
143 |
|
/* We need to allocate more memory. When oldsize is |
144 |
|
non-zero this means that we are changing the size, so |
145 |
|
grow the bitset 25% larger than requested to reduce |
146 |
|
number of reallocations. */ |
147 |
|
|
148 |
|
if (oldsize == 0) |
149 |
|
size = newsize; |
150 |
|
else |
151 |
|
size = newsize + newsize / 4; |
152 |
|
|
153 |
|
EBITSET_ELTS (src) |
154 |
|
= realloc (EBITSET_ELTS (src), size * sizeof (ebitset_elt *)); |
155 |
|
EBITSET_ASIZE (src) = size; |
156 |
|
} |
157 |
|
|
158 |
if (BITSET_SIZE_MAX / sizeof (ebitset_elt *) < newsize) |
memset (EBITSET_ELTS (src) + oldsize, 0, |
159 |
xalloc_die (); |
(newsize - oldsize) * sizeof (ebitset_elt *)); |
160 |
|
} |
161 |
|
else |
162 |
|
{ |
163 |
|
/* The bitset needs to shrink. There's no point deallocating |
164 |
|
the memory unless it is shrinking by a reasonable amount. */ |
165 |
|
if ((oldsize - newsize) >= oldsize / 2) |
166 |
|
{ |
167 |
|
EBITSET_ELTS (src) |
168 |
|
= realloc (EBITSET_ELTS (src), newsize * sizeof (ebitset_elt *)); |
169 |
|
EBITSET_ASIZE (src) = newsize; |
170 |
|
} |
171 |
|
|
172 |
EBITSET_ELTS (bset) = xrealloc (EBITSET_ELTS (bset), |
/* Need to prune any excess bits. FIXME. */ |
173 |
newsize * sizeof (ebitset_elt *)); |
} |
|
EBITSET_SIZE (bset) = newsize; |
|
174 |
|
|
175 |
memset (EBITSET_ELTS (bset) + oldsize, 0, size * sizeof (ebitset_elt *)); |
BITSET_NBITS_ (src) = n_bits; |
176 |
|
return n_bits; |
177 |
} |
} |
178 |
|
|
179 |
|
|
295 |
|
|
296 |
|
|
297 |
static ebitset_elt * |
static ebitset_elt * |
298 |
ebitset_elt_find (bitset bset, bitset_windex windex, |
ebitset_elt_find (bitset bset, bitset_bindex bindex, |
299 |
enum ebitset_find_mode mode) |
enum ebitset_find_mode mode) |
300 |
{ |
{ |
301 |
ebitset_elt *elt; |
ebitset_elt *elt; |
303 |
bitset_windex eindex; |
bitset_windex eindex; |
304 |
ebitset_elts *elts; |
ebitset_elts *elts; |
305 |
|
|
306 |
eindex = windex / EBITSET_ELT_WORDS; |
eindex = bindex / EBITSET_ELT_BITS; |
307 |
|
|
308 |
elts = EBITSET_ELTS (bset); |
elts = EBITSET_ELTS (bset); |
309 |
size = EBITSET_SIZE (bset); |
size = EBITSET_SIZE (bset); |
329 |
|
|
330 |
case EBITSET_CREATE: |
case EBITSET_CREATE: |
331 |
if (eindex >= size) |
if (eindex >= size) |
332 |
{ |
ebitset_resize (bset, bindex); |
|
bitset_windex extra; |
|
|
|
|
|
extra = eindex - size + 1; |
|
|
|
|
|
/* We need to expand the table by EXTRA elements. It may be |
|
|
better with large bitsets to grow the number of |
|
|
elements by some fraction of the current size otherwise |
|
|
we can spend a lot of time slowly increasing the size of the |
|
|
bitset. */ |
|
|
if (extra < EBITSET_GROW_SIZE) |
|
|
extra = EBITSET_GROW_SIZE; |
|
|
|
|
|
ebitset_elts_grow (bset, extra); |
|
|
} |
|
333 |
|
|
334 |
/* Create a new element. */ |
/* Create a new element. */ |
335 |
elt = ebitset_elt_calloc (); |
elt = ebitset_elt_calloc (); |
346 |
} |
} |
347 |
|
|
348 |
|
|
|
static inline ebitset_elt * |
|
|
ebitset_elt_last (bitset bset) |
|
|
{ |
|
|
ebitset_elts *elts; |
|
|
|
|
|
elts = EBITSET_ELTS (bset); |
|
|
|
|
|
/* Assume that have at least one element in elts. */ |
|
|
return elts[EBITSET_SIZE (bset) - 1]; |
|
|
} |
|
|
|
|
|
|
|
349 |
/* Weed out the zero elements from the elts. */ |
/* Weed out the zero elements from the elts. */ |
350 |
static inline bitset_windex |
static inline bitset_windex |
351 |
ebitset_weed (bitset bset) |
ebitset_weed (bitset bset) |
365 |
|
|
366 |
if (elt) |
if (elt) |
367 |
{ |
{ |
368 |
if (elt && ebitset_elt_zero_p (elt)) |
if (ebitset_elt_zero_p (elt)) |
369 |
{ |
{ |
370 |
ebitset_elt_remove (bset, j); |
ebitset_elt_remove (bset, j); |
371 |
count++; |
count++; |
465 |
|
|
466 |
ebitset_zero (dst); |
ebitset_zero (dst); |
467 |
|
|
468 |
if (EBITSET_SIZE (dst) < EBITSET_SIZE (src)) |
if (BITSET_NBITS_ (dst) != BITSET_NBITS_ (src)) |
469 |
ebitset_elts_grow (dst, EBITSET_SIZE (src) - EBITSET_SIZE (dst)); |
ebitset_resize (dst, BITSET_NBITS_ (src)); |
470 |
|
|
471 |
selts = EBITSET_ELTS (src); |
selts = EBITSET_ELTS (src); |
472 |
delts = EBITSET_ELTS (dst); |
delts = EBITSET_ELTS (dst); |
510 |
} |
} |
511 |
|
|
512 |
|
|
|
/* Return size in bits of bitset SRC. */ |
|
|
static bitset_bindex |
|
|
ebitset_size (bitset src) |
|
|
{ |
|
|
/* Return current size of bitset in bits. */ |
|
|
return EBITSET_SIZE (src) * EBITSET_ELT_BITS; |
|
|
} |
|
|
|
|
|
|
|
513 |
/* Set bit BITNO in bitset DST. */ |
/* Set bit BITNO in bitset DST. */ |
514 |
static void |
static void |
515 |
ebitset_set (bitset dst, bitset_bindex bitno) |
ebitset_set (bitset dst, bitset_bindex bitno) |
516 |
{ |
{ |
517 |
bitset_windex windex = bitno / BITSET_WORD_BITS; |
bitset_windex windex = bitno / BITSET_WORD_BITS; |
518 |
|
|
519 |
ebitset_elt_find (dst, windex, EBITSET_CREATE); |
ebitset_elt_find (dst, bitno, EBITSET_CREATE); |
520 |
|
|
521 |
dst->b.cdata[windex - dst->b.cindex] |= |
dst->b.cdata[windex - dst->b.cindex] |= |
522 |
(bitset_word) 1 << (bitno % BITSET_WORD_BITS); |
(bitset_word) 1 << (bitno % BITSET_WORD_BITS); |
529 |
{ |
{ |
530 |
bitset_windex windex = bitno / BITSET_WORD_BITS; |
bitset_windex windex = bitno / BITSET_WORD_BITS; |
531 |
|
|
532 |
if (!ebitset_elt_find (dst, windex, EBITSET_FIND)) |
if (!ebitset_elt_find (dst, bitno, EBITSET_FIND)) |
533 |
return; |
return; |
534 |
|
|
535 |
dst->b.cdata[windex - dst->b.cindex] &= |
dst->b.cdata[windex - dst->b.cindex] &= |
547 |
{ |
{ |
548 |
bitset_windex windex = bitno / BITSET_WORD_BITS; |
bitset_windex windex = bitno / BITSET_WORD_BITS; |
549 |
|
|
550 |
return (ebitset_elt_find (src, windex, EBITSET_FIND) |
return (ebitset_elt_find (src, bitno, EBITSET_FIND) |
551 |
&& ((src->b.cdata[windex - src->b.cindex] |
&& ((src->b.cdata[windex - src->b.cindex] |
552 |
>> (bitno % BITSET_WORD_BITS)) |
>> (bitno % BITSET_WORD_BITS)) |
553 |
& 1)); |
& 1)); |
734 |
{ |
{ |
735 |
/* The coast is clear, plant boot! */ |
/* The coast is clear, plant boot! */ |
736 |
|
|
737 |
|
#if EBITSET_ELT_WORDS == 2 |
738 |
|
word = srcp[0]; |
739 |
|
if (word) |
740 |
|
{ |
741 |
|
if (!(word & 0xffff)) |
742 |
|
{ |
743 |
|
word >>= 16; |
744 |
|
bitno += 16; |
745 |
|
} |
746 |
|
if (!(word & 0xff)) |
747 |
|
{ |
748 |
|
word >>= 8; |
749 |
|
bitno += 8; |
750 |
|
} |
751 |
|
for (; word; bitno++) |
752 |
|
{ |
753 |
|
if (word & 1) |
754 |
|
list[count++] = bitno; |
755 |
|
word >>= 1; |
756 |
|
} |
757 |
|
} |
758 |
|
windex++; |
759 |
|
bitno = windex * BITSET_WORD_BITS; |
760 |
|
|
761 |
|
word = srcp[1]; |
762 |
|
if (word) |
763 |
|
{ |
764 |
|
if (!(word & 0xffff)) |
765 |
|
{ |
766 |
|
word >>= 16; |
767 |
|
bitno += 16; |
768 |
|
} |
769 |
|
for (; word; bitno++) |
770 |
|
{ |
771 |
|
if (word & 1) |
772 |
|
list[count++] = bitno; |
773 |
|
word >>= 1; |
774 |
|
} |
775 |
|
} |
776 |
|
windex++; |
777 |
|
bitno = windex * BITSET_WORD_BITS; |
778 |
|
#else |
779 |
for (i = 0; i < EBITSET_ELT_WORDS; i++, windex++) |
for (i = 0; i < EBITSET_ELT_WORDS; i++, windex++) |
780 |
{ |
{ |
781 |
bitno = windex * BITSET_WORD_BITS; |
bitno = windex * BITSET_WORD_BITS; |
801 |
} |
} |
802 |
} |
} |
803 |
} |
} |
804 |
|
#endif |
805 |
} |
} |
806 |
else |
else |
807 |
{ |
{ |
834 |
} |
} |
835 |
|
|
836 |
|
|
837 |
|
/* Ensure that any unused bits within the last element are clear. */ |
838 |
|
static inline void |
839 |
|
ebitset_unused_clear (bitset dst) |
840 |
|
{ |
841 |
|
unsigned int last_bit; |
842 |
|
bitset_bindex n_bits; |
843 |
|
|
844 |
|
n_bits = BITSET_NBITS_ (dst); |
845 |
|
last_bit = n_bits % EBITSET_ELT_BITS; |
846 |
|
|
847 |
|
if (last_bit) |
848 |
|
{ |
849 |
|
bitset_windex eindex; |
850 |
|
ebitset_elts *elts; |
851 |
|
ebitset_elt *elt; |
852 |
|
|
853 |
|
elts = EBITSET_ELTS (dst); |
854 |
|
|
855 |
|
eindex = n_bits / EBITSET_ELT_BITS; |
856 |
|
|
857 |
|
elt = elts[eindex]; |
858 |
|
if (elt) |
859 |
|
{ |
860 |
|
bitset_windex windex; |
861 |
|
bitset_windex woffset; |
862 |
|
bitset_word *srcp = EBITSET_WORDS (elt); |
863 |
|
|
864 |
|
windex = n_bits / BITSET_WORD_BITS; |
865 |
|
woffset = eindex * EBITSET_ELT_WORDS; |
866 |
|
|
867 |
|
srcp[windex - woffset] &= ((bitset_word) 1 << last_bit) - 1; |
868 |
|
windex++; |
869 |
|
for (; (windex - woffset) < EBITSET_ELT_WORDS; windex++) |
870 |
|
srcp[windex - woffset] = 0; |
871 |
|
} |
872 |
|
} |
873 |
|
} |
874 |
|
|
875 |
|
|
876 |
static void |
static void |
877 |
ebitset_ones (bitset dst) |
ebitset_ones (bitset dst) |
878 |
{ |
{ |
879 |
bitset_windex j; |
bitset_windex j; |
880 |
ebitset_elt *elt; |
ebitset_elt *elt; |
881 |
|
|
|
|
|
882 |
for (j = 0; j < EBITSET_SIZE (dst); j++) |
for (j = 0; j < EBITSET_SIZE (dst); j++) |
883 |
{ |
{ |
884 |
/* Create new elements if they cannot be found. Perhaps |
/* Create new elements if they cannot be found. Perhaps |
885 |
we should just add pointers to a ones element. */ |
we should just add pointers to a ones element? */ |
886 |
elt = |
elt = |
887 |
ebitset_elt_find (dst, j * EBITSET_ELT_WORDS, EBITSET_CREATE); |
ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_CREATE); |
888 |
memset (EBITSET_WORDS (elt), -1, sizeof (EBITSET_WORDS (elt))); |
memset (EBITSET_WORDS (elt), -1, sizeof (EBITSET_WORDS (elt))); |
889 |
} |
} |
890 |
EBITSET_NONZERO_SET (dst); |
EBITSET_NONZERO_SET (dst); |
891 |
|
ebitset_unused_clear (dst); |
892 |
} |
} |
893 |
|
|
894 |
|
|
895 |
static bool |
static bool |
896 |
ebitset_empty_p (bitset dst) |
ebitset_empty_p (bitset dst) |
897 |
{ |
{ |
898 |
return !ebitset_weed (dst); |
ebitset_elts *elts; |
899 |
|
bitset_windex j; |
900 |
|
|
901 |
|
if (EBITSET_ZERO_P (dst)) |
902 |
|
return 1; |
903 |
|
|
904 |
|
elts = EBITSET_ELTS (dst); |
905 |
|
for (j = 0; j < EBITSET_SIZE (dst); j++) |
906 |
|
{ |
907 |
|
ebitset_elt *elt = elts[j]; |
908 |
|
|
909 |
|
if (elt) |
910 |
|
{ |
911 |
|
if (!ebitset_elt_zero_p (elt)) |
912 |
|
return 0; |
913 |
|
/* Do some weeding as we go. */ |
914 |
|
ebitset_elt_remove (dst, j); |
915 |
|
} |
916 |
|
} |
917 |
|
|
918 |
|
/* All the bits are zero. We could shrink the elts. |
919 |
|
For now just mark DST as known to be zero. */ |
920 |
|
EBITSET_ZERO_SET (dst); |
921 |
|
return 1; |
922 |
} |
} |
923 |
|
|
924 |
|
|
930 |
ebitset_elt *delt; |
ebitset_elt *delt; |
931 |
bitset_windex j; |
bitset_windex j; |
932 |
|
|
933 |
|
ebitset_resize (dst, BITSET_NBITS_ (src)); |
934 |
|
|
935 |
for (j = 0; j < EBITSET_SIZE (src); j++) |
for (j = 0; j < EBITSET_SIZE (src); j++) |
936 |
{ |
{ |
937 |
/* Create new elements for dst if they cannot be found |
/* Create new elements for dst if they cannot be found |
938 |
or substitute zero elements if src elements not found. */ |
or substitute zero elements if src elements not found. */ |
939 |
selt = |
selt = |
940 |
ebitset_elt_find (dst, j * EBITSET_ELT_WORDS, EBITSET_SUBST); |
ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_SUBST); |
941 |
delt = |
delt = |
942 |
ebitset_elt_find (dst, j * EBITSET_ELT_WORDS, EBITSET_CREATE); |
ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_CREATE); |
943 |
|
|
944 |
for (i = 0; i < EBITSET_ELT_WORDS; i++) |
for (i = 0; i < EBITSET_ELT_WORDS; i++) |
945 |
EBITSET_WORDS (delt)[i] = ~EBITSET_WORDS (selt)[i]; |
EBITSET_WORDS (delt)[i] = ~EBITSET_WORDS (selt)[i]; |
946 |
} |
} |
947 |
EBITSET_NONZERO_SET (dst); |
EBITSET_NONZERO_SET (dst); |
948 |
|
ebitset_unused_clear (dst); |
949 |
} |
} |
950 |
|
|
951 |
|
|
1045 |
unsigned int i; |
unsigned int i; |
1046 |
bitset_windex j; |
bitset_windex j; |
1047 |
|
|
1048 |
|
ebitset_resize (dst, max (BITSET_NBITS_ (src1), BITSET_NBITS_ (src2))); |
1049 |
|
|
1050 |
ssize1 = EBITSET_SIZE (src1); |
ssize1 = EBITSET_SIZE (src1); |
1051 |
ssize2 = EBITSET_SIZE (src2); |
ssize2 = EBITSET_SIZE (src2); |
1052 |
dsize = EBITSET_SIZE (dst); |
dsize = EBITSET_SIZE (dst); |
1054 |
if (size < ssize2) |
if (size < ssize2) |
1055 |
size = ssize2; |
size = ssize2; |
1056 |
|
|
|
if (size > dsize) |
|
|
ebitset_elts_grow (dst, size - dsize); |
|
|
|
|
1057 |
selts1 = EBITSET_ELTS (src1); |
selts1 = EBITSET_ELTS (src1); |
1058 |
selts2 = EBITSET_ELTS (src2); |
selts2 = EBITSET_ELTS (src2); |
1059 |
delts = EBITSET_ELTS (dst); |
delts = EBITSET_ELTS (dst); |
1293 |
ebitset_reset, |
ebitset_reset, |
1294 |
bitset_toggle_, |
bitset_toggle_, |
1295 |
ebitset_test, |
ebitset_test, |
1296 |
ebitset_size, |
ebitset_resize, |
1297 |
|
bitset_size_, |
1298 |
bitset_count_, |
bitset_count_, |
1299 |
ebitset_empty_p, |
ebitset_empty_p, |
1300 |
ebitset_ones, |
ebitset_ones, |
1349 |
size = n_bits ? (n_bits + EBITSET_ELT_BITS - 1) / EBITSET_ELT_BITS |
size = n_bits ? (n_bits + EBITSET_ELT_BITS - 1) / EBITSET_ELT_BITS |
1350 |
: EBITSET_INITIAL_SIZE; |
: EBITSET_INITIAL_SIZE; |
1351 |
|
|
1352 |
EBITSET_SIZE (bset) = 0; |
EBITSET_ASIZE (bset) = 0; |
1353 |
EBITSET_ELTS (bset) = 0; |
EBITSET_ELTS (bset) = 0; |
1354 |
ebitset_elts_grow (bset, size); |
ebitset_resize (bset, n_bits); |
1355 |
|
|
1356 |
return bset; |
return bset; |
1357 |
} |
} |