/* Functions to support link list bitsets.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
This program is free software; you can redistribute it and/or modify
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
/* This file implements linked-list bitsets. These bitsets can be of
arbitrary length and are more efficient than arrays of bits for
/* Number of words to use for each element. The larger the value the
greater the size of the cache and the shorter the time to find a given bit
but the more memory wasted for sparse bitsets and the longer the time
- to search for set bits. */
+ to search for set bits.
+
+ The routines that dominate timing profiles are lbitset_elt_find
+ and lbitset_elt_link, especially when accessing the bits randomly. */
#define LBITSET_ELT_WORDS 2
/* Obstack to allocate bitset elements from. */
static struct obstack lbitset_obstack;
-static int lbitset_obstack_init = 0;
+static bool lbitset_obstack_init = false;
static lbitset_elt *lbitset_free_list; /* Free list of bitset elements. */
extern void debug_lbitset PARAMS ((bitset));
{
if (!lbitset_obstack_init)
{
- lbitset_obstack_init = 1;
+ lbitset_obstack_init = true;
/* Let particular systems override the size of a chunk. */
}
-/* Return nonzero if all bits in an element are zero. */
-static inline int
+/* Are all bits in an element zero? */
+static inline bool
lbitset_elt_zero_p (lbitset_elt *elt)
{
int i;
for (i = 0; i < LBITSET_ELT_WORDS; i++)
if (elt->words[i])
- return 0;
+ return false;
- return 1;
+ return true;
}
}
-/* Return 1 if DST == SRC. */
-static inline int
+/* Is DST == SRC? */
+static inline bool
lbitset_equal_p (bitset dst, bitset src)
{
lbitset_elt *selt;
int j;
if (src == dst)
- return 1;
+ return true;
lbitset_weed (src);
lbitset_weed (dst);
selt && delt; selt = selt->next, delt = delt->next)
{
if (selt->index != delt->index)
- return 0;
+ return false;
for (j = 0; j < LBITSET_ELT_WORDS; j++)
if (delt->words[j] != selt->words[j])
- return 0;
+ return false;
}
return !selt && !delt;
}
}
-/* Copy bits from bitset SRC to bitset DST. Return non-zero if
+/* Copy bits from bitset SRC to bitset DST. Return true if
bitsets different. */
-static inline int
+static inline bool
lbitset_copy_cmp (bitset dst, bitset src)
{
if (src == dst)
- return 0;
+ return false;
if (!LBITSET_HEAD (dst))
{
}
if (lbitset_equal_p (dst, src))
- return 0;
+ return false;
lbitset_copy (dst, src);
- return 1;
+ return true;
}
-/* Return size in bits of bitset SRC. */
static bitset_bindex
-lbitset_size (bitset src)
+lbitset_resize (bitset src, bitset_bindex size)
{
- lbitset_elt *elt;
-
- elt = LBITSET_TAIL (src);
- if (!elt)
- return 0;
+ BITSET_NBITS_ (src) = size;
- /* Return current size of bitset in bits. */
- return (elt->index + LBITSET_ELT_WORDS) * BITSET_WORD_BITS;
+ /* Need to prune any excess bits. FIXME. */
+ return size;
}
-
/* Set bit BITNO in bitset DST. */
static void
lbitset_set (bitset dst, bitset_bindex bitno)
/* Test bit BITNO in bitset SRC. */
-static int
+static bool
lbitset_test (bitset src, bitset_bindex bitno)
{
bitset_windex windex = bitno / BITSET_WORD_BITS;
- if (!lbitset_elt_find (src, windex, LBITSET_FIND))
- return 0;
-
- return (src->b.cdata[windex - src->b.cindex]
- >> (bitno % BITSET_WORD_BITS)) & 1;
+ return (lbitset_elt_find (src, windex, LBITSET_FIND)
+ && ((src->b.cdata[windex - src->b.cindex]
+ >> (bitno % BITSET_WORD_BITS))
+ & 1));
}
}
-static int
+static bool
lbitset_empty_p (bitset dst)
{
- lbitset_weed (dst);
- if (LBITSET_HEAD (dst))
- return 0;
+ lbitset_elt *elt;
+ lbitset_elt *next;
+
+ for (elt = LBITSET_HEAD (dst); elt; elt = next)
+ {
+ next = elt->next;
+ if (!lbitset_elt_zero_p (elt))
+ return 0;
+ /* Weed as we go. */
+ lbitset_elt_unlink (dst, elt);
+ }
+
return 1;
}
+/* Ensure that any unused bits within the last element are clear. */
+static inline void
+lbitset_unused_clear (bitset dst)
+{
+ unsigned int last_bit;
+ bitset_bindex n_bits;
+
+ n_bits = BITSET_SIZE_ (dst);
+ last_bit = n_bits % LBITSET_ELT_BITS;
+
+ if (last_bit)
+ {
+ lbitset_elt *elt;
+ bitset_windex windex;
+ bitset_word *srcp;
+
+ elt = LBITSET_TAIL (dst);
+ srcp = elt->words;
+ windex = n_bits / BITSET_WORD_BITS;
+
+ srcp[windex - elt->index] &= ((bitset_word) 1 << last_bit) - 1;
+ windex++;
+
+ for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++)
+ srcp[windex - elt->index] = 0;
+ }
+}
+
+
static void
lbitset_ones (bitset dst)
{
bitset! It makes a sparse bitset become dense. An alternative
is to have a flag that indicates that the bitset stores the
complement of what it indicates. */
- elt = LBITSET_TAIL (dst);
- /* Ignore empty set. */
- if (!elt)
- return;
- windex = elt->index;
+ windex = (BITSET_SIZE_ (dst) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS;
+
for (i = 0; i < windex; i += LBITSET_ELT_WORDS)
{
/* Create new elements if they cannot be found. */
elt = lbitset_elt_find (dst, i, LBITSET_CREATE);
memset (elt->words, -1, sizeof (elt->words));
}
+
+ lbitset_unused_clear (dst);
}
/* This is another unfriendly operation for a linked list
bitset! */
elt = LBITSET_TAIL (dst);
- /* Ignore empty set. */
- if (!elt)
- return;
- windex = elt->index;
+ windex = (BITSET_SIZE_ (dst) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS;
+
for (i = 0; i < windex; i += LBITSET_ELT_WORDS)
{
/* Create new elements for dst if they cannot be found
for (j = 0; j < LBITSET_ELT_WORDS; j++)
delt->words[j] = ~selt->words[j];
}
+ lbitset_unused_clear (dst);
lbitset_weed (dst);
return;
}
-/* Return 1 if DST == DST | SRC. */
-static int
+/* Is DST == DST | SRC? */
+static bool
lbitset_subset_p (bitset dst, bitset src)
{
lbitset_elt *selt;
for (j = 0; j < LBITSET_ELT_WORDS; j++)
if (delt->words[j] != (selt->words[j] | delt->words[j]))
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-/* Return 1 if DST & SRC == 0. */
-static int
+/* Is DST & SRC == 0? */
+static bool
lbitset_disjoint_p (bitset dst, bitset src)
{
lbitset_elt *selt;
for (j = 0; j < LBITSET_ELT_WORDS; j++)
if (selt->words[j] & delt->words[j])
- return 0;
+ return false;
}
- return 1;
+ return true;
}
-static int
+static bool
lbitset_op3_cmp (bitset dst, bitset src1, bitset src2, enum bitset_ops op)
{
lbitset_elt *selt1 = LBITSET_HEAD (src1);
bitset_word *srcp1;
bitset_word *srcp2;
bitset_word *dstp;
- int changed = 0;
+ bool changed = false;
unsigned int i;
LBITSET_HEAD (dst) = 0;
elements that we've skipped. */
while (delt && delt->index < windex)
{
- changed = 1;
+ changed = true;
dtmp = delt;
delt = delt->next;
lbitset_elt_free (dtmp);
if (*dstp != tmp)
{
- changed = 1;
+ changed = true;
*dstp = tmp;
}
}
if (*dstp != tmp)
{
- changed = 1;
+ changed = true;
*dstp = tmp;
}
}
if (*dstp != tmp)
{
- changed = 1;
+ changed = true;
*dstp = tmp;
}
}
if (*dstp != tmp)
{
- changed = 1;
+ changed = true;
*dstp = tmp;
}
}
/* If we have elements of DST left over, free them all. */
if (delt)
{
- changed = 1;
+ changed = true;
lbitset_prune (dst, delt);
}
}
-static int
+static bool
lbitset_and_cmp (bitset dst, bitset src1, bitset src2)
{
lbitset_elt *selt1 = LBITSET_HEAD (src1);
lbitset_elt *selt2 = LBITSET_HEAD (src2);
- int changed;
+ bool changed;
if (!selt2)
{
}
-static int
+static bool
lbitset_andn_cmp (bitset dst, bitset src1, bitset src2)
{
lbitset_elt *selt1 = LBITSET_HEAD (src1);
lbitset_elt *selt2 = LBITSET_HEAD (src2);
- int changed;
+ bool changed;
if (!selt2)
{
}
-static int
+static bool
lbitset_or_cmp (bitset dst, bitset src1, bitset src2)
{
lbitset_elt *selt1 = LBITSET_HEAD (src1);
}
-static int
+static bool
lbitset_xor_cmp (bitset dst, bitset src1, bitset src2)
{
lbitset_elt *selt1 = LBITSET_HEAD (src1);
lbitset_reset,
bitset_toggle_,
lbitset_test,
- lbitset_size,
+ lbitset_resize,
+ bitset_size_,
bitset_count_,
lbitset_empty_p,
lbitset_ones,
bitset
lbitset_init (bitset bset, bitset_bindex n_bits ATTRIBUTE_UNUSED)
{
+ BITSET_NBITS_ (bset) = n_bits;
bset->b.vtable = &lbitset_vtable;
return bset;
}
lbitset_free_list = 0;
if (lbitset_obstack_init)
{
- lbitset_obstack_init = 0;
+ lbitset_obstack_init = false;
obstack_free (&lbitset_obstack, NULL);
}
}