26 |
#include <stddef.h> |
#include <stddef.h> |
27 |
#include <stdlib.h> |
#include <stdlib.h> |
28 |
#include <stdio.h> |
#include <stdio.h> |
29 |
|
#include <string.h> |
30 |
|
|
31 |
/* This file implements linked-list bitsets. These bitsets can be of |
/* This file implements linked-list bitsets. These bitsets can be of |
32 |
arbitrary length and are more efficient than arrays of bits for |
arbitrary length and are more efficient than arrays of bits for |
41 |
/* Number of words to use for each element. The larger the value the |
/* Number of words to use for each element. The larger the value the |
42 |
greater the size of the cache and the shorter the time to find a given bit |
greater the size of the cache and the shorter the time to find a given bit |
43 |
but the more memory wasted for sparse bitsets and the longer the time |
but the more memory wasted for sparse bitsets and the longer the time |
44 |
to search for set bits. */ |
to search for set bits. |
45 |
|
|
46 |
|
The routines that dominate timing profiles are lbitset_elt_find |
47 |
|
and lbitset_elt_link, especially when accessing the bits randomly. */ |
48 |
|
|
49 |
#define LBITSET_ELT_WORDS 2 |
#define LBITSET_ELT_WORDS 2 |
50 |
|
|
506 |
} |
} |
507 |
|
|
508 |
|
|
|
/* Return size in bits of bitset SRC. */ |
|
509 |
static bitset_bindex |
static bitset_bindex |
510 |
lbitset_size (bitset src) |
lbitset_resize (bitset src, bitset_bindex size) |
511 |
{ |
{ |
512 |
lbitset_elt *elt; |
BITSET_NBITS_ (src) = size; |
|
|
|
|
elt = LBITSET_TAIL (src); |
|
|
if (!elt) |
|
|
return 0; |
|
513 |
|
|
514 |
/* Return current size of bitset in bits. */ |
/* Need to prune any excess bits. FIXME. */ |
515 |
return (elt->index + LBITSET_ELT_WORDS) * BITSET_WORD_BITS; |
return size; |
516 |
} |
} |
517 |
|
|
|
|
|
518 |
/* Set bit BITNO in bitset DST. */ |
/* Set bit BITNO in bitset DST. */ |
519 |
static void |
static void |
520 |
lbitset_set (bitset dst, bitset_bindex bitno) |
lbitset_set (bitset dst, bitset_bindex bitno) |
865 |
static bool |
static bool |
866 |
lbitset_empty_p (bitset dst) |
lbitset_empty_p (bitset dst) |
867 |
{ |
{ |
868 |
lbitset_weed (dst); |
lbitset_elt *elt; |
869 |
return !LBITSET_HEAD (dst); |
lbitset_elt *next; |
870 |
|
|
871 |
|
for (elt = LBITSET_HEAD (dst); elt; elt = next) |
872 |
|
{ |
873 |
|
next = elt->next; |
874 |
|
if (!lbitset_elt_zero_p (elt)) |
875 |
|
return 0; |
876 |
|
/* Weed as we go. */ |
877 |
|
lbitset_elt_unlink (dst, elt); |
878 |
|
} |
879 |
|
|
880 |
|
return 1; |
881 |
|
} |
882 |
|
|
883 |
|
|
884 |
|
/* Ensure that any unused bits within the last element are clear. */ |
885 |
|
static inline void |
886 |
|
lbitset_unused_clear (bitset dst) |
887 |
|
{ |
888 |
|
unsigned int last_bit; |
889 |
|
bitset_bindex n_bits; |
890 |
|
|
891 |
|
n_bits = BITSET_SIZE_ (dst); |
892 |
|
last_bit = n_bits % LBITSET_ELT_BITS; |
893 |
|
|
894 |
|
if (last_bit) |
895 |
|
{ |
896 |
|
lbitset_elt *elt; |
897 |
|
bitset_windex windex; |
898 |
|
bitset_word *srcp; |
899 |
|
|
900 |
|
elt = LBITSET_TAIL (dst); |
901 |
|
srcp = elt->words; |
902 |
|
windex = n_bits / BITSET_WORD_BITS; |
903 |
|
|
904 |
|
srcp[windex - elt->index] &= ((bitset_word) 1 << last_bit) - 1; |
905 |
|
windex++; |
906 |
|
|
907 |
|
for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++) |
908 |
|
srcp[windex - elt->index] = 0; |
909 |
|
} |
910 |
} |
} |
911 |
|
|
912 |
|
|
921 |
bitset! It makes a sparse bitset become dense. An alternative |
bitset! It makes a sparse bitset become dense. An alternative |
922 |
is to have a flag that indicates that the bitset stores the |
is to have a flag that indicates that the bitset stores the |
923 |
complement of what it indicates. */ |
complement of what it indicates. */ |
|
elt = LBITSET_TAIL (dst); |
|
|
/* Ignore empty set. */ |
|
|
if (!elt) |
|
|
return; |
|
924 |
|
|
925 |
windex = elt->index; |
windex = (BITSET_SIZE_ (dst) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS; |
926 |
|
|
927 |
for (i = 0; i < windex; i += LBITSET_ELT_WORDS) |
for (i = 0; i < windex; i += LBITSET_ELT_WORDS) |
928 |
{ |
{ |
929 |
/* Create new elements if they cannot be found. */ |
/* Create new elements if they cannot be found. */ |
930 |
elt = lbitset_elt_find (dst, i, LBITSET_CREATE); |
elt = lbitset_elt_find (dst, i, LBITSET_CREATE); |
931 |
memset (elt->words, -1, sizeof (elt->words)); |
memset (elt->words, -1, sizeof (elt->words)); |
932 |
} |
} |
933 |
|
|
934 |
|
lbitset_unused_clear (dst); |
935 |
} |
} |
936 |
|
|
937 |
|
|
948 |
/* This is another unfriendly operation for a linked list |
/* This is another unfriendly operation for a linked list |
949 |
bitset! */ |
bitset! */ |
950 |
elt = LBITSET_TAIL (dst); |
elt = LBITSET_TAIL (dst); |
|
/* Ignore empty set. */ |
|
|
if (!elt) |
|
|
return; |
|
951 |
|
|
952 |
windex = elt->index; |
windex = (BITSET_SIZE_ (dst) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS; |
953 |
|
|
954 |
for (i = 0; i < windex; i += LBITSET_ELT_WORDS) |
for (i = 0; i < windex; i += LBITSET_ELT_WORDS) |
955 |
{ |
{ |
956 |
/* Create new elements for dst if they cannot be found |
/* Create new elements for dst if they cannot be found |
961 |
for (j = 0; j < LBITSET_ELT_WORDS; j++) |
for (j = 0; j < LBITSET_ELT_WORDS; j++) |
962 |
delt->words[j] = ~selt->words[j]; |
delt->words[j] = ~selt->words[j]; |
963 |
} |
} |
964 |
|
lbitset_unused_clear (dst); |
965 |
lbitset_weed (dst); |
lbitset_weed (dst); |
966 |
return; |
return; |
967 |
} |
} |
1316 |
lbitset_reset, |
lbitset_reset, |
1317 |
bitset_toggle_, |
bitset_toggle_, |
1318 |
lbitset_test, |
lbitset_test, |
1319 |
lbitset_size, |
lbitset_resize, |
1320 |
|
bitset_size_, |
1321 |
bitset_count_, |
bitset_count_, |
1322 |
lbitset_empty_p, |
lbitset_empty_p, |
1323 |
lbitset_ones, |
lbitset_ones, |
1360 |
bitset |
bitset |
1361 |
lbitset_init (bitset bset, bitset_bindex n_bits ATTRIBUTE_UNUSED) |
lbitset_init (bitset bset, bitset_bindex n_bits ATTRIBUTE_UNUSED) |
1362 |
{ |
{ |
1363 |
|
BITSET_NBITS_ (bset) = n_bits; |
1364 |
bset->b.vtable = &lbitset_vtable; |
bset->b.vtable = &lbitset_vtable; |
1365 |
return bset; |
return bset; |
1366 |
} |
} |