static inline bool tbitset_equal_p (bitset dst, bitset src) { if (src == dst) return true; tbitset_weed (dst); tbitset_weed (src); if (EBITSET_SIZE (src) != EBITSET_SIZE (dst)) return false; tbitset_elts *selts = EBITSET_ELTS (src); tbitset_elts *delts = EBITSET_ELTS (dst); for (bitset_windex j = 0; j < EBITSET_SIZE (src); j++) { tbitset_elt *selt = selts[j]; tbitset_elt *delt = delts[j]; if (!selt && !delt) continue; if ((selt && !delt) || (!selt && delt)) return false; for (unsigned i = 0; i < EBITSET_ELT_WORDS; i++) if (EBITSET_WORDS (selt)[i] != EBITSET_WORDS (delt)[i]) return false; } return true; }
/* Copy bits from bitset SRC to bitset DST. */ static inline void tbitset_copy_ (bitset dst, bitset src) { if (src == dst) return; tbitset_zero (dst); if (BITSET_NBITS_ (dst) != BITSET_NBITS_ (src)) tbitset_resize (dst, BITSET_NBITS_ (src)); tbitset_elts *selts = EBITSET_ELTS (src); tbitset_elts *delts = EBITSET_ELTS (dst); for (bitset_windex j = 0; j < EBITSET_SIZE (src); j++) { tbitset_elt *selt = selts[j]; if (selt) { tbitset_elt *tmp = tbitset_elt_alloc (); delts[j] = tmp; memcpy (EBITSET_WORDS (tmp), EBITSET_WORDS (selt), sizeof (EBITSET_WORDS (selt))); } } EBITSET_NONZERO_SET (dst); }
static bitset_bindex ebitset_resize (bitset src, bitset_bindex n_bits) { bitset_windex oldsize; bitset_windex newsize; if (n_bits == BITSET_NBITS_ (src)) return n_bits; oldsize = EBITSET_SIZE (src); newsize = EBITSET_N_ELTS (n_bits); if (oldsize < newsize) { bitset_windex size; /* The bitset needs to grow. If we already have enough memory allocated, then just zero what we need. */ if (newsize > EBITSET_ASIZE (src)) { /* We need to allocate more memory. When oldsize is non-zero this means that we are changing the size, so grow the bitset 25% larger than requested to reduce number of reallocations. */ if (oldsize == 0) size = newsize; else size = newsize + newsize / 4; EBITSET_ELTS (src) = realloc (EBITSET_ELTS (src), size * sizeof (ebitset_elt *)); EBITSET_ASIZE (src) = size; } memset (EBITSET_ELTS (src) + oldsize, 0, (newsize - oldsize) * sizeof (ebitset_elt *)); } else { /* The bitset needs to shrink. There's no point deallocating the memory unless it is shrinking by a reasonable amount. */ if ((oldsize - newsize) >= oldsize / 2) { EBITSET_ELTS (src) = realloc (EBITSET_ELTS (src), newsize * sizeof (ebitset_elt *)); EBITSET_ASIZE (src) = newsize; } /* Need to prune any excess bits. FIXME. */ } BITSET_NBITS_ (src) = n_bits; return n_bits; }
/* Add ELT into elts at index EINDEX of bitset BSET. */ static inline void tbitset_elt_add (bitset bset, tbitset_elt *elt, bitset_windex eindex) { tbitset_elts *elts = EBITSET_ELTS (bset); /* Assume that the elts entry not allocated. */ elts[eindex] = elt; }
/* Find list of up to NUM bits set in BSET starting from and including *NEXT and store in array LIST. Return with actual number of bits found and with *NEXT indicating where search stopped. */ static bitset_bindex ebitset_list (bitset bset, bitset_bindex *list, bitset_bindex num, bitset_bindex *next) { bitset_bindex bitno; bitset_windex windex; bitset_windex eindex; bitset_bindex count; bitset_windex size; ebitset_elt *elt; bitset_word word; ebitset_elts *elts; if (EBITSET_ZERO_P (bset)) return 0; bitno = *next; count = 0; elts = EBITSET_ELTS (bset); size = EBITSET_SIZE (bset); eindex = bitno / EBITSET_ELT_BITS; if (bitno % EBITSET_ELT_BITS) { /* We need to start within an element. This is not very common. */ elt = elts[eindex]; if (elt) { bitset_windex woffset; bitset_word *srcp = EBITSET_WORDS (elt); windex = bitno / BITSET_WORD_BITS; woffset = eindex * EBITSET_ELT_WORDS; for (; (windex - woffset) < EBITSET_ELT_WORDS; windex++) { word = srcp[windex - woffset] >> (bitno % BITSET_WORD_BITS); for (; word; bitno++) { if (word & 1) { list[count++] = bitno; if (count >= num) { *next = bitno + 1; return count; } } word >>= 1; } bitno = (windex + 1) * BITSET_WORD_BITS; } } /* Skip to next element. */ eindex++; }
/* Remove element with index EINDEX from bitset BSET. */ static inline void tbitset_elt_remove (bitset bset, bitset_windex eindex) { tbitset_elts *elts = EBITSET_ELTS (bset); tbitset_elt *elt = elts[eindex]; elts[eindex] = 0; tbitset_elt_free (elt); }
static ebitset_elt * ebitset_elt_find (bitset bset, bitset_bindex bindex, enum ebitset_find_mode mode) { ebitset_elt *elt; bitset_windex size; bitset_windex eindex; ebitset_elts *elts; eindex = bindex / EBITSET_ELT_BITS; elts = EBITSET_ELTS (bset); size = EBITSET_SIZE (bset); if (eindex < size) { if ((elt = elts[eindex])) { if (EBITSET_WORDS (elt) == bset->b.cdata) return elt; EBITSET_CACHE_SET (bset, eindex); return elt; } } /* The element could not be found. */ switch (mode) { default: abort (); case EBITSET_FIND: return 0; case EBITSET_CREATE: if (eindex >= size) ebitset_resize (bset, bindex); /* Create a new element. */ elt = ebitset_elt_calloc (); ebitset_elt_add (bset, elt, eindex); EBITSET_CACHE_SET (bset, eindex); return elt; case EBITSET_SUBST: return &ebitset_zero_elts[0]; } }
/* Set all bits in the bitset to zero. */ static inline void tbitset_zero (bitset bset) { if (EBITSET_ZERO_P (bset)) return; tbitset_elts *elts = EBITSET_ELTS (bset); for (bitset_windex j = 0; j < EBITSET_SIZE (bset); j++) { tbitset_elt *elt = elts[j]; if (elt) tbitset_elt_remove (bset, j); } /* All the bits are zero. We could shrink the elts. For now just mark BSET as known to be zero. */ EBITSET_ZERO_SET (bset); }
/* Weed out the zero elements from the elts. */ static inline bitset_windex ebitset_weed (bitset bset) { ebitset_elts *elts; bitset_windex j; bitset_windex count; if (EBITSET_ZERO_P (bset)) return 0; elts = EBITSET_ELTS (bset); count = 0; for (j = 0; j < EBITSET_SIZE (bset); j++) { ebitset_elt *elt = elts[j]; if (elt) { if (ebitset_elt_zero_p (elt)) { ebitset_elt_remove (bset, j); count++; } } else count++; } count = j - count; if (!count) { /* All the bits are zero. We could shrink the elts. For now just mark BSET as known to be zero. */ EBITSET_ZERO_SET (bset); } else EBITSET_NONZERO_SET (bset); return count; }
/* Find list of up to NUM bits set in BSET starting from and including *NEXT and store in array LIST. Return with actual number of bits found and with *NEXT indicating where search stopped. */ static bitset_bindex tbitset_list_reverse (bitset bset, bitset_bindex *list, bitset_bindex num, bitset_bindex *next) { if (EBITSET_ZERO_P (bset)) return 0; bitset_windex size = EBITSET_SIZE (bset); bitset_bindex n_bits = size * EBITSET_ELT_BITS; bitset_bindex rbitno = *next; if (rbitno >= n_bits) return 0; tbitset_elts *elts = EBITSET_ELTS (bset); bitset_bindex bitno = n_bits - (rbitno + 1); bitset_windex windex = bitno / BITSET_WORD_BITS; bitset_windex eindex = bitno / EBITSET_ELT_BITS; bitset_windex woffset = windex - eindex * EBITSET_ELT_WORDS; /* If num is 1, we could speed things up with a binary search of the word of interest. */ bitset_bindex count = 0; unsigned bcount = bitno % BITSET_WORD_BITS; bitset_bindex boffset = windex * BITSET_WORD_BITS; do { tbitset_elt *elt = elts[eindex]; if (elt) { bitset_word *srcp = EBITSET_WORDS (elt); do { for (bitset_word word = srcp[woffset] << (BITSET_WORD_BITS - 1 - bcount); word; bcount--) { if (word & BITSET_MSB) { list[count++] = boffset + bcount; if (count >= num) { *next = n_bits - (boffset + bcount); return count; } } word <<= 1; } boffset -= BITSET_WORD_BITS; bcount = BITSET_WORD_BITS - 1; } while (woffset--); } woffset = EBITSET_ELT_WORDS - 1; boffset = eindex * EBITSET_ELT_BITS - BITSET_WORD_BITS; } while (eindex--); *next = n_bits - (boffset + 1); return count; }
static void tbitset_free (bitset bset) { tbitset_zero (bset); free (EBITSET_ELTS (bset)); }