|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <config.h> |
|
|
|
|
|
#include "bitset/list.h" |
|
|
|
|
|
#include <stddef.h> |
|
|
#include <stdio.h> |
|
|
#include <stdlib.h> |
|
|
#include <string.h> |
|
|
|
|
|
#include "obstack.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define LBITSET_ELT_WORDS 2 |
|
|
|
|
|
typedef bitset_word lbitset_word; |
|
|
|
|
|
#define LBITSET_WORD_BITS BITSET_WORD_BITS |
|
|
|
|
|
|
|
|
#define LBITSET_ELT_BITS \ |
|
|
((unsigned) (LBITSET_ELT_WORDS * LBITSET_WORD_BITS)) |
|
|
|
|
|
|
|
|
|
|
|
typedef struct lbitset_elt_struct |
|
|
{ |
|
|
struct lbitset_elt_struct *next; |
|
|
struct lbitset_elt_struct *prev; |
|
|
bitset_windex index; |
|
|
bitset_word words[LBITSET_ELT_WORDS]; |
|
|
} |
|
|
lbitset_elt; |
|
|
|
|
|
|
|
|
enum lbitset_find_mode |
|
|
{ LBITSET_FIND, LBITSET_CREATE, LBITSET_SUBST }; |
|
|
|
|
|
static lbitset_elt lbitset_zero_elts[3]; |
|
|
|
|
|
|
|
|
static struct obstack lbitset_obstack; |
|
|
static bool lbitset_obstack_init = false; |
|
|
static lbitset_elt *lbitset_free_list; |
|
|
|
|
|
extern void debug_lbitset (bitset); |
|
|
|
|
|
#define LBITSET_CURRENT1(X) \ |
|
|
((lbitset_elt *) (void *) ((char *) (X) - offsetof (lbitset_elt, words))) |
|
|
|
|
|
#define LBITSET_CURRENT(X) LBITSET_CURRENT1((X)->b.cdata) |
|
|
|
|
|
#define LBITSET_HEAD(X) ((X)->l.head) |
|
|
#define LBITSET_TAIL(X) ((X)->l.tail) |
|
|
|
|
|
|
|
|
static inline lbitset_elt * |
|
|
lbitset_elt_alloc (void) |
|
|
{ |
|
|
lbitset_elt *elt; |
|
|
|
|
|
if (lbitset_free_list != NULL) |
|
|
{ |
|
|
elt = lbitset_free_list; |
|
|
lbitset_free_list = elt->next; |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (!lbitset_obstack_init) |
|
|
{ |
|
|
lbitset_obstack_init = true; |
|
|
|
|
|
|
|
|
|
|
|
#ifndef OBSTACK_CHUNK_SIZE |
|
|
# define OBSTACK_CHUNK_SIZE 0 |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#ifndef OBSTACK_CHUNK_ALLOC |
|
|
# define OBSTACK_CHUNK_ALLOC xmalloc |
|
|
#endif |
|
|
|
|
|
#ifndef OBSTACK_CHUNK_FREE |
|
|
# define OBSTACK_CHUNK_FREE free |
|
|
#endif |
|
|
|
|
|
#if !(defined __GNUC__ || defined __clang__) |
|
|
# define __alignof__(type) 0 |
|
|
#endif |
|
|
|
|
|
obstack_specify_allocation (&lbitset_obstack, OBSTACK_CHUNK_SIZE, |
|
|
__alignof__ (lbitset_elt), |
|
|
OBSTACK_CHUNK_ALLOC, |
|
|
OBSTACK_CHUNK_FREE); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
elt = (lbitset_elt *) obstack_alloc (&lbitset_obstack, |
|
|
sizeof (lbitset_elt)); |
|
|
} |
|
|
|
|
|
return elt; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline lbitset_elt * |
|
|
lbitset_elt_calloc (void) |
|
|
{ |
|
|
lbitset_elt *elt = lbitset_elt_alloc (); |
|
|
memset (elt->words, 0, sizeof (elt->words)); |
|
|
return elt; |
|
|
} |
|
|
|
|
|
|
|
|
static inline void |
|
|
lbitset_elt_free (lbitset_elt *elt) |
|
|
{ |
|
|
elt->next = lbitset_free_list; |
|
|
lbitset_free_list = elt; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void |
|
|
lbitset_elt_unlink (bitset bset, lbitset_elt *elt) |
|
|
{ |
|
|
lbitset_elt *next = elt->next; |
|
|
lbitset_elt *prev = elt->prev; |
|
|
|
|
|
if (prev) |
|
|
prev->next = next; |
|
|
|
|
|
if (next) |
|
|
next->prev = prev; |
|
|
|
|
|
if (LBITSET_HEAD (bset) == elt) |
|
|
LBITSET_HEAD (bset) = next; |
|
|
if (LBITSET_TAIL (bset) == elt) |
|
|
LBITSET_TAIL (bset) = prev; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (LBITSET_CURRENT (bset) == elt) |
|
|
{ |
|
|
if (next) |
|
|
{ |
|
|
bset->b.cdata = next->words; |
|
|
bset->b.cindex = next->index; |
|
|
} |
|
|
else if (prev) |
|
|
{ |
|
|
bset->b.cdata = prev->words; |
|
|
bset->b.cindex = prev->index; |
|
|
} |
|
|
else |
|
|
{ |
|
|
bset->b.csize = 0; |
|
|
bset->b.cdata = NULL; |
|
|
} |
|
|
} |
|
|
|
|
|
lbitset_elt_free (elt); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static inline void |
|
|
lbitset_prune (bitset bset, lbitset_elt *elt) |
|
|
{ |
|
|
if (!elt) |
|
|
return; |
|
|
|
|
|
if (elt->prev) |
|
|
{ |
|
|
LBITSET_TAIL (bset) = elt->prev; |
|
|
bset->b.cdata = elt->prev->words; |
|
|
bset->b.cindex = elt->prev->index; |
|
|
elt->prev->next = NULL; |
|
|
} |
|
|
else |
|
|
{ |
|
|
LBITSET_HEAD (bset) = NULL; |
|
|
LBITSET_TAIL (bset) = NULL; |
|
|
bset->b.cdata = NULL; |
|
|
bset->b.csize = 0; |
|
|
} |
|
|
|
|
|
lbitset_elt *next; |
|
|
for (; elt; elt = next) |
|
|
{ |
|
|
next = elt->next; |
|
|
lbitset_elt_free (elt); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline bool |
|
|
lbitset_elt_zero_p (lbitset_elt *elt) |
|
|
{ |
|
|
for (int i = 0; i < LBITSET_ELT_WORDS; i++) |
|
|
if (elt->words[i]) |
|
|
return false; |
|
|
return true; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void |
|
|
lbitset_elt_link (bitset bset, lbitset_elt *elt) |
|
|
{ |
|
|
bitset_windex windex = elt->index; |
|
|
|
|
|
lbitset_elt *current = bset->b.csize ? LBITSET_CURRENT (bset) : LBITSET_HEAD (bset); |
|
|
|
|
|
|
|
|
if (LBITSET_HEAD (bset) == NULL) |
|
|
{ |
|
|
elt->next = elt->prev = NULL; |
|
|
LBITSET_HEAD (bset) = elt; |
|
|
LBITSET_TAIL (bset) = elt; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
else if (windex < bset->b.cindex) |
|
|
{ |
|
|
lbitset_elt *ptr; |
|
|
for (ptr = current; |
|
|
ptr->prev && ptr->prev->index > windex; ptr = ptr->prev) |
|
|
continue; |
|
|
|
|
|
if (ptr->prev) |
|
|
ptr->prev->next = elt; |
|
|
else |
|
|
LBITSET_HEAD (bset) = elt; |
|
|
|
|
|
elt->prev = ptr->prev; |
|
|
elt->next = ptr; |
|
|
ptr->prev = elt; |
|
|
} |
|
|
|
|
|
|
|
|
else |
|
|
{ |
|
|
lbitset_elt *ptr; |
|
|
for (ptr = current; |
|
|
ptr->next && ptr->next->index < windex; ptr = ptr->next) |
|
|
continue; |
|
|
|
|
|
if (ptr->next) |
|
|
ptr->next->prev = elt; |
|
|
else |
|
|
LBITSET_TAIL (bset) = elt; |
|
|
|
|
|
elt->next = ptr->next; |
|
|
elt->prev = ptr; |
|
|
ptr->next = elt; |
|
|
} |
|
|
|
|
|
|
|
|
bset->b.cindex = windex; |
|
|
bset->b.csize = LBITSET_ELT_WORDS; |
|
|
bset->b.cdata = elt->words; |
|
|
} |
|
|
|
|
|
|
|
|
static lbitset_elt * |
|
|
lbitset_elt_find (bitset bset, bitset_windex windex, |
|
|
enum lbitset_find_mode mode) |
|
|
{ |
|
|
lbitset_elt *current; |
|
|
|
|
|
if (bset->b.csize) |
|
|
{ |
|
|
current = LBITSET_CURRENT (bset); |
|
|
|
|
|
if ((windex - bset->b.cindex) < bset->b.csize) |
|
|
return current; |
|
|
} |
|
|
else |
|
|
{ |
|
|
current = LBITSET_HEAD (bset); |
|
|
} |
|
|
|
|
|
if (current) |
|
|
{ |
|
|
lbitset_elt *elt; |
|
|
if (windex < bset->b.cindex) |
|
|
{ |
|
|
for (elt = current; |
|
|
elt->prev && elt->index > windex; elt = elt->prev) |
|
|
continue; |
|
|
} |
|
|
else |
|
|
{ |
|
|
for (elt = current; |
|
|
elt->next && (elt->index + LBITSET_ELT_WORDS - 1) < windex; |
|
|
elt = elt->next) |
|
|
continue; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (windex - elt->index < LBITSET_ELT_WORDS) |
|
|
{ |
|
|
bset->b.cindex = elt->index; |
|
|
bset->b.csize = LBITSET_ELT_WORDS; |
|
|
bset->b.cdata = elt->words; |
|
|
return elt; |
|
|
} |
|
|
} |
|
|
|
|
|
switch (mode) |
|
|
{ |
|
|
default: |
|
|
abort (); |
|
|
|
|
|
case LBITSET_FIND: |
|
|
return NULL; |
|
|
|
|
|
case LBITSET_CREATE: |
|
|
windex -= windex % LBITSET_ELT_WORDS; |
|
|
lbitset_elt *elt = lbitset_elt_calloc (); |
|
|
elt->index = windex; |
|
|
lbitset_elt_link (bset, elt); |
|
|
return elt; |
|
|
|
|
|
case LBITSET_SUBST: |
|
|
return &lbitset_zero_elts[0]; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void |
|
|
lbitset_weed (bitset bset) |
|
|
{ |
|
|
lbitset_elt *next; |
|
|
for (lbitset_elt *elt = LBITSET_HEAD (bset); elt; elt = next) |
|
|
{ |
|
|
next = elt->next; |
|
|
if (lbitset_elt_zero_p (elt)) |
|
|
lbitset_elt_unlink (bset, elt); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
lbitset_zero (bitset bset) |
|
|
{ |
|
|
lbitset_elt *head = LBITSET_HEAD (bset); |
|
|
if (!head) |
|
|
return; |
|
|
|
|
|
|
|
|
lbitset_prune (bset, head); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline bool |
|
|
lbitset_equal_p (bitset dst, bitset src) |
|
|
{ |
|
|
if (src == dst) |
|
|
return true; |
|
|
|
|
|
lbitset_weed (src); |
|
|
lbitset_weed (dst); |
|
|
lbitset_elt *selt; |
|
|
lbitset_elt *delt; |
|
|
for (selt = LBITSET_HEAD (src), delt = LBITSET_HEAD (dst); |
|
|
selt && delt; selt = selt->next, delt = delt->next) |
|
|
{ |
|
|
if (selt->index != delt->index) |
|
|
return false; |
|
|
|
|
|
for (int j = 0; j < LBITSET_ELT_WORDS; j++) |
|
|
if (delt->words[j] != selt->words[j]) |
|
|
return false; |
|
|
} |
|
|
return !selt && !delt; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void |
|
|
lbitset_copy_ (bitset dst, bitset src) |
|
|
{ |
|
|
if (src == dst) |
|
|
return; |
|
|
|
|
|
lbitset_zero (dst); |
|
|
|
|
|
lbitset_elt *head = LBITSET_HEAD (src); |
|
|
if (!head) |
|
|
return; |
|
|
|
|
|
lbitset_elt *prev = NULL; |
|
|
lbitset_elt *tmp; |
|
|
lbitset_elt *elt = head; |
|
|
do |
|
|
{ |
|
|
tmp = lbitset_elt_alloc (); |
|
|
tmp->index = elt->index; |
|
|
tmp->prev = prev; |
|
|
tmp->next = NULL; |
|
|
if (prev) |
|
|
prev->next = tmp; |
|
|
else |
|
|
LBITSET_HEAD (dst) = tmp; |
|
|
prev = tmp; |
|
|
|
|
|
memcpy (tmp->words, elt->words, sizeof (elt->words)); |
|
|
|
|
|
elt = elt->next; |
|
|
} |
|
|
while (elt); |
|
|
LBITSET_TAIL (dst) = tmp; |
|
|
|
|
|
dst->b.csize = LBITSET_ELT_WORDS; |
|
|
dst->b.cdata = LBITSET_HEAD (dst)->words; |
|
|
dst->b.cindex = LBITSET_HEAD (dst)->index; |
|
|
} |
|
|
|
|
|
|
|
|
static void |
|
|
lbitset_copy (bitset dst, bitset src) |
|
|
{ |
|
|
if (BITSET_COMPATIBLE_ (dst, src)) |
|
|
lbitset_copy_ (dst, src); |
|
|
else |
|
|
bitset_copy_ (dst, src); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline bool |
|
|
lbitset_copy_cmp (bitset dst, bitset src) |
|
|
{ |
|
|
if (src == dst) |
|
|
return false; |
|
|
|
|
|
if (!LBITSET_HEAD (dst)) |
|
|
{ |
|
|
lbitset_copy (dst, src); |
|
|
return LBITSET_HEAD (src) != NULL; |
|
|
} |
|
|
|
|
|
if (lbitset_equal_p (dst, src)) |
|
|
return false; |
|
|
|
|
|
lbitset_copy (dst, src); |
|
|
return true; |
|
|
} |
|
|
|
|
|
|
|
|
static bitset_bindex |
|
|
lbitset_resize (bitset src, bitset_bindex size) |
|
|
{ |
|
|
BITSET_NBITS_ (src) = size; |
|
|
|
|
|
|
|
|
return size; |
|
|
} |
|
|
|
|
|
|
|
|
static void |
|
|
lbitset_set (bitset dst, bitset_bindex bitno) |
|
|
{ |
|
|
bitset_windex windex = bitno / BITSET_WORD_BITS; |
|
|
|
|
|
lbitset_elt_find (dst, windex, LBITSET_CREATE); |
|
|
|
|
|
dst->b.cdata[windex - dst->b.cindex] |= |
|
|
(bitset_word) 1 << (bitno % BITSET_WORD_BITS); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
lbitset_reset (bitset dst, bitset_bindex bitno) |
|
|
{ |
|
|
bitset_windex windex = bitno / BITSET_WORD_BITS; |
|
|
|
|
|
if (!lbitset_elt_find (dst, windex, LBITSET_FIND)) |
|
|
return; |
|
|
|
|
|
dst->b.cdata[windex - dst->b.cindex] &= |
|
|
~((bitset_word) 1 << (bitno % BITSET_WORD_BITS)); |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool |
|
|
lbitset_test (bitset src, bitset_bindex bitno) |
|
|
{ |
|
|
bitset_windex windex = bitno / BITSET_WORD_BITS; |
|
|
|
|
|
return (lbitset_elt_find (src, windex, LBITSET_FIND) |
|
|
&& ((src->b.cdata[windex - src->b.cindex] |
|
|
>> (bitno % BITSET_WORD_BITS)) |
|
|
& 1)); |
|
|
} |
|
|
|
|
|
|
|
|
static void |
|
|
lbitset_free (bitset bset) |
|
|
{ |
|
|
lbitset_zero (bset); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bitset_bindex |
|
|
lbitset_list_reverse (bitset bset, bitset_bindex *list, |
|
|
bitset_bindex num, bitset_bindex *next) |
|
|
{ |
|
|
lbitset_elt *elt = LBITSET_TAIL (bset); |
|
|
if (!elt) |
|
|
return 0; |
|
|
|
|
|
bitset_bindex n_bits = (elt->index + LBITSET_ELT_WORDS) * BITSET_WORD_BITS; |
|
|
bitset_bindex rbitno = *next; |
|
|
|
|
|
if (rbitno >= n_bits) |
|
|
return 0; |
|
|
|
|
|
bitset_bindex bitno = n_bits - (rbitno + 1); |
|
|
|
|
|
bitset_windex windex = bitno / BITSET_WORD_BITS; |
|
|
|
|
|
|
|
|
for (; elt && elt->index > windex; elt = elt->prev) |
|
|
continue; |
|
|
|
|
|
if (!elt) |
|
|
return 0; |
|
|
|
|
|
unsigned bitcnt; |
|
|
if (windex >= elt->index + LBITSET_ELT_WORDS) |
|
|
{ |
|
|
|
|
|
|
|
|
bitcnt = BITSET_WORD_BITS - 1; |
|
|
windex = elt->index + LBITSET_ELT_WORDS - 1; |
|
|
} |
|
|
else |
|
|
{ |
|
|
bitcnt = bitno % BITSET_WORD_BITS; |
|
|
} |
|
|
|
|
|
bitset_bindex count = 0; |
|
|
bitset_bindex bitoff = windex * BITSET_WORD_BITS; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while (elt) |
|
|
{ |
|
|
bitset_word *srcp = elt->words; |
|
|
|
|
|
for (; (windex - elt->index) < LBITSET_ELT_WORDS; |
|
|
windex--) |
|
|
{ |
|
|
bitset_word word = srcp[windex - elt->index]; |
|
|
if (bitcnt + 1 < BITSET_WORD_BITS) |
|
|
|
|
|
word &= ((bitset_word) 1 << (bitcnt + 1)) - 1; |
|
|
BITSET_FOR_EACH_BIT_REVERSE(pos, word) |
|
|
{ |
|
|
list[count++] = bitoff + pos; |
|
|
if (count >= num) |
|
|
{ |
|
|
*next = n_bits - (bitoff + pos); |
|
|
return count; |
|
|
} |
|
|
} |
|
|
bitoff -= BITSET_WORD_BITS; |
|
|
bitcnt = BITSET_WORD_BITS - 1; |
|
|
} |
|
|
|
|
|
elt = elt->prev; |
|
|
if (elt) |
|
|
{ |
|
|
windex = elt->index + LBITSET_ELT_WORDS - 1; |
|
|
bitoff = windex * BITSET_WORD_BITS; |
|
|
} |
|
|
} |
|
|
|
|
|
*next = n_bits - (bitoff + 1); |
|
|
return count; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bitset_bindex |
|
|
lbitset_list (bitset bset, bitset_bindex *list, |
|
|
bitset_bindex num, bitset_bindex *next) |
|
|
{ |
|
|
lbitset_elt *head = LBITSET_HEAD (bset); |
|
|
if (!head) |
|
|
return 0; |
|
|
|
|
|
bitset_windex windex; |
|
|
lbitset_elt *elt; |
|
|
|
|
|
bitset_bindex bitno = *next; |
|
|
bitset_bindex count = 0; |
|
|
|
|
|
if (!bitno) |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
elt = head; |
|
|
windex = elt->index; |
|
|
bitno = windex * BITSET_WORD_BITS; |
|
|
} |
|
|
else |
|
|
{ |
|
|
windex = bitno / BITSET_WORD_BITS; |
|
|
|
|
|
|
|
|
for (elt = head; |
|
|
elt && (elt->index + LBITSET_ELT_WORDS - 1) < windex; |
|
|
elt = elt->next) |
|
|
continue; |
|
|
|
|
|
if (!elt) |
|
|
return 0; |
|
|
|
|
|
if (windex < elt->index) |
|
|
{ |
|
|
windex = elt->index; |
|
|
bitno = windex * BITSET_WORD_BITS; |
|
|
} |
|
|
else |
|
|
{ |
|
|
bitset_word *srcp = elt->words; |
|
|
|
|
|
|
|
|
|
|
|
for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++) |
|
|
{ |
|
|
bitset_word word = srcp[windex - elt->index] >> (bitno % BITSET_WORD_BITS); |
|
|
BITSET_FOR_EACH_BIT (pos, word) |
|
|
{ |
|
|
list[count++] = bitno + pos; |
|
|
if (count >= num) |
|
|
{ |
|
|
*next = bitno + pos + 1; |
|
|
return count; |
|
|
} |
|
|
} |
|
|
bitno = (windex + 1) * BITSET_WORD_BITS; |
|
|
} |
|
|
|
|
|
elt = elt->next; |
|
|
if (elt) |
|
|
{ |
|
|
windex = elt->index; |
|
|
bitno = windex * BITSET_WORD_BITS; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
while (elt) |
|
|
{ |
|
|
bitset_word *srcp = elt->words; |
|
|
|
|
|
|
|
|
if ((count + LBITSET_ELT_BITS) < num) |
|
|
{ |
|
|
|
|
|
|
|
|
#if LBITSET_ELT_WORDS == 2 |
|
|
bitset_word word = srcp[0]; |
|
|
if (word) |
|
|
BITSET_FOR_EACH_BIT (pos, word) |
|
|
list[count++] = bitno + pos; |
|
|
windex++; |
|
|
bitno = windex * BITSET_WORD_BITS; |
|
|
|
|
|
word = srcp[1]; |
|
|
if (word) |
|
|
BITSET_FOR_EACH_BIT (pos, word) |
|
|
list[count++] = bitno + pos; |
|
|
windex++; |
|
|
bitno = windex * BITSET_WORD_BITS; |
|
|
#else |
|
|
for (int i = 0; i < LBITSET_ELT_WORDS; i++) |
|
|
{ |
|
|
bitset_word word = srcp[i]; |
|
|
if (word) |
|
|
BITSET_FOR_EACH_BIT (pos, word) |
|
|
list[count++] = bitno + pos; |
|
|
windex++; |
|
|
bitno = windex * BITSET_WORD_BITS; |
|
|
} |
|
|
#endif |
|
|
} |
|
|
else |
|
|
{ |
|
|
|
|
|
|
|
|
for (int i = 0; i < LBITSET_ELT_WORDS; i++) |
|
|
{ |
|
|
bitset_word word = srcp[i]; |
|
|
if (word) |
|
|
BITSET_FOR_EACH_BIT (pos, word) |
|
|
{ |
|
|
list[count++] = bitno + pos; |
|
|
if (count >= num) |
|
|
{ |
|
|
*next = bitno + pos + 1; |
|
|
return count; |
|
|
} |
|
|
} |
|
|
windex++; |
|
|
bitno = windex * BITSET_WORD_BITS; |
|
|
} |
|
|
} |
|
|
|
|
|
elt = elt->next; |
|
|
if (elt) |
|
|
{ |
|
|
windex = elt->index; |
|
|
bitno = windex * BITSET_WORD_BITS; |
|
|
} |
|
|
} |
|
|
|
|
|
*next = bitno; |
|
|
return count; |
|
|
} |
|
|
|
|
|
|
|
|
static bool |
|
|
lbitset_empty_p (bitset dst) |
|
|
{ |
|
|
lbitset_elt *elt; |
|
|
lbitset_elt *next; |
|
|
|
|
|
for (elt = LBITSET_HEAD (dst); elt; elt = next) |
|
|
{ |
|
|
next = elt->next; |
|
|
if (!lbitset_elt_zero_p (elt)) |
|
|
return false; |
|
|
|
|
|
lbitset_elt_unlink (dst, elt); |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static inline void |
|
|
lbitset_unused_clear (bitset dst) |
|
|
{ |
|
|
bitset_bindex n_bits = BITSET_SIZE_ (dst); |
|
|
unsigned last_bit = n_bits % LBITSET_ELT_BITS; |
|
|
|
|
|
if (last_bit) |
|
|
{ |
|
|
lbitset_elt *elt = LBITSET_TAIL (dst); |
|
|
bitset_word *srcp = elt->words; |
|
|
bitset_windex windex = n_bits / BITSET_WORD_BITS; |
|
|
|
|
|
srcp[windex - elt->index] |
|
|
&= ((bitset_word) 1 << (last_bit % BITSET_WORD_BITS)) - 1; |
|
|
windex++; |
|
|
|
|
|
for (; (windex - elt->index) < LBITSET_ELT_WORDS; windex++) |
|
|
srcp[windex - elt->index] = 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
static void |
|
|
lbitset_ones (bitset dst) |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bitset_windex windex |
|
|
= (BITSET_SIZE_ (dst) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS; |
|
|
|
|
|
for (bitset_windex i = 0; i < windex; i += LBITSET_ELT_WORDS) |
|
|
{ |
|
|
|
|
|
lbitset_elt *elt = lbitset_elt_find (dst, i, LBITSET_CREATE); |
|
|
memset (elt->words, -1, sizeof (elt->words)); |
|
|
} |
|
|
|
|
|
lbitset_unused_clear (dst); |
|
|
} |
|
|
|
|
|
|
|
|
static void |
|
|
lbitset_not (bitset dst, bitset src) |
|
|
{ |
|
|
bitset_windex windex |
|
|
= (BITSET_SIZE_ (dst) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS; |
|
|
|
|
|
for (bitset_windex i = 0; i < windex; i += LBITSET_ELT_WORDS) |
|
|
{ |
|
|
|
|
|
|
|
|
lbitset_elt *selt = lbitset_elt_find (src, i, LBITSET_SUBST); |
|
|
lbitset_elt *delt = lbitset_elt_find (dst, i, LBITSET_CREATE); |
|
|
|
|
|
for (unsigned j = 0; j < LBITSET_ELT_WORDS; j++) |
|
|
delt->words[j] = ~selt->words[j]; |
|
|
} |
|
|
lbitset_unused_clear (dst); |
|
|
lbitset_weed (dst); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool |
|
|
lbitset_subset_p (bitset dst, bitset src) |
|
|
{ |
|
|
for (lbitset_elt *selt = LBITSET_HEAD (src), *delt = LBITSET_HEAD (dst); |
|
|
selt || delt; selt = selt->next, delt = delt->next) |
|
|
{ |
|
|
if (!selt) |
|
|
selt = &lbitset_zero_elts[0]; |
|
|
else if (!delt) |
|
|
delt = &lbitset_zero_elts[0]; |
|
|
else if (selt->index != delt->index) |
|
|
{ |
|
|
if (selt->index < delt->index) |
|
|
{ |
|
|
lbitset_zero_elts[2].next = delt; |
|
|
delt = &lbitset_zero_elts[2]; |
|
|
} |
|
|
else |
|
|
{ |
|
|
lbitset_zero_elts[1].next = selt; |
|
|
selt = &lbitset_zero_elts[1]; |
|
|
} |
|
|
} |
|
|
|
|
|
for (unsigned j = 0; j < LBITSET_ELT_WORDS; j++) |
|
|
if (delt->words[j] != (selt->words[j] | delt->words[j])) |
|
|
return false; |
|
|
} |
|
|
return true; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static bool |
|
|
lbitset_disjoint_p (bitset dst, bitset src) |
|
|
{ |
|
|
for (lbitset_elt *selt = LBITSET_HEAD (src), *delt = LBITSET_HEAD (dst); |
|
|
selt && delt; selt = selt->next, delt = delt->next) |
|
|
{ |
|
|
if (selt->index != delt->index) |
|
|
{ |
|
|
if (selt->index < delt->index) |
|
|
{ |
|
|
lbitset_zero_elts[2].next = delt; |
|
|
delt = &lbitset_zero_elts[2]; |
|
|
} |
|
|
else |
|
|
{ |
|
|
lbitset_zero_elts[1].next = selt; |
|
|
selt = &lbitset_zero_elts[1]; |
|
|
} |
|
|
|
|
|
|
|
|
continue; |
|
|
} |
|
|
|
|
|
for (unsigned j = 0; j < LBITSET_ELT_WORDS; j++) |
|
|
if (selt->words[j] & delt->words[j]) |
|
|
return false; |
|
|
} |
|
|
return true; |
|
|
} |
|
|
|
|
|
|
|
|
static bool |
|
|
lbitset_op3_cmp (bitset dst, bitset src1, bitset src2, enum bitset_ops op) |
|
|
{ |
|
|
lbitset_elt *selt1 = LBITSET_HEAD (src1); |
|
|
lbitset_elt *selt2 = LBITSET_HEAD (src2); |
|
|
lbitset_elt *delt = LBITSET_HEAD (dst); |
|
|
bool changed = false; |
|
|
|
|
|
LBITSET_HEAD (dst) = NULL; |
|
|
dst->b.csize = 0; |
|
|
|
|
|
bitset_windex windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX; |
|
|
bitset_windex windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX; |
|
|
|
|
|
while (selt1 || selt2) |
|
|
{ |
|
|
bitset_windex windex; |
|
|
lbitset_elt *stmp1; |
|
|
lbitset_elt *stmp2; |
|
|
|
|
|
|
|
|
|
|
|
if (windex1 == windex2) |
|
|
{ |
|
|
windex = windex1; |
|
|
stmp1 = selt1; |
|
|
stmp2 = selt2; |
|
|
selt1 = selt1->next; |
|
|
windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX; |
|
|
selt2 = selt2->next; |
|
|
windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX; |
|
|
} |
|
|
else if (windex1 < windex2) |
|
|
{ |
|
|
windex = windex1; |
|
|
stmp1 = selt1; |
|
|
stmp2 = &lbitset_zero_elts[0]; |
|
|
selt1 = selt1->next; |
|
|
windex1 = (selt1) ? selt1->index : BITSET_WINDEX_MAX; |
|
|
} |
|
|
else |
|
|
{ |
|
|
windex = windex2; |
|
|
stmp1 = &lbitset_zero_elts[0]; |
|
|
stmp2 = selt2; |
|
|
selt2 = selt2->next; |
|
|
windex2 = (selt2) ? selt2->index : BITSET_WINDEX_MAX; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
lbitset_elt *dtmp; |
|
|
while (delt && delt->index < windex) |
|
|
{ |
|
|
changed = true; |
|
|
dtmp = delt; |
|
|
delt = delt->next; |
|
|
lbitset_elt_free (dtmp); |
|
|
} |
|
|
if (delt && delt->index == windex) |
|
|
{ |
|
|
dtmp = delt; |
|
|
delt = delt->next; |
|
|
} |
|
|
else |
|
|
dtmp = lbitset_elt_calloc (); |
|
|
|
|
|
|
|
|
|
|
|
bitset_word *srcp1 = stmp1->words; |
|
|
bitset_word *srcp2 = stmp2->words; |
|
|
bitset_word *dstp = dtmp->words; |
|
|
switch (op) |
|
|
{ |
|
|
default: |
|
|
abort (); |
|
|
|
|
|
case BITSET_OP_OR: |
|
|
for (unsigned i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) |
|
|
{ |
|
|
bitset_word tmp = *srcp1++ | *srcp2++; |
|
|
|
|
|
if (*dstp != tmp) |
|
|
{ |
|
|
changed = true; |
|
|
*dstp = tmp; |
|
|
} |
|
|
} |
|
|
break; |
|
|
|
|
|
case BITSET_OP_AND: |
|
|
for (unsigned i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) |
|
|
{ |
|
|
bitset_word tmp = *srcp1++ & *srcp2++; |
|
|
|
|
|
if (*dstp != tmp) |
|
|
{ |
|
|
changed = true; |
|
|
*dstp = tmp; |
|
|
} |
|
|
} |
|
|
break; |
|
|
|
|
|
case BITSET_OP_XOR: |
|
|
for (unsigned i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) |
|
|
{ |
|
|
bitset_word tmp = *srcp1++ ^ *srcp2++; |
|
|
|
|
|
if (*dstp != tmp) |
|
|
{ |
|
|
changed = true; |
|
|
*dstp = tmp; |
|
|
} |
|
|
} |
|
|
break; |
|
|
|
|
|
case BITSET_OP_ANDN: |
|
|
for (unsigned i = 0; i < LBITSET_ELT_WORDS; i++, dstp++) |
|
|
{ |
|
|
bitset_word tmp = *srcp1++ & ~(*srcp2++); |
|
|
|
|
|
if (*dstp != tmp) |
|
|
{ |
|
|
changed = true; |
|
|
*dstp = tmp; |
|
|
} |
|
|
} |
|
|
break; |
|
|
} |
|
|
|
|
|
if (!lbitset_elt_zero_p (dtmp)) |
|
|
{ |
|
|
dtmp->index = windex; |
|
|
|
|
|
lbitset_elt_link (dst, dtmp); |
|
|
} |
|
|
else |
|
|
{ |
|
|
lbitset_elt_free (dtmp); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (delt) |
|
|
{ |
|
|
changed = true; |
|
|
lbitset_prune (dst, delt); |
|
|
} |
|
|
|
|
|
return changed; |
|
|
} |
|
|
|
|
|
|
|
|
static bool |
|
|
lbitset_and_cmp (bitset dst, bitset src1, bitset src2) |
|
|
{ |
|
|
lbitset_elt *selt1 = LBITSET_HEAD (src1); |
|
|
lbitset_elt *selt2 = LBITSET_HEAD (src2); |
|
|
|
|
|
if (!selt2) |
|
|
{ |
|
|
lbitset_weed (dst); |
|
|
bool changed = !LBITSET_HEAD (dst); |
|
|
lbitset_zero (dst); |
|
|
return changed; |
|
|
} |
|
|
else if (!selt1) |
|
|
{ |
|
|
lbitset_weed (dst); |
|
|
bool changed = !LBITSET_HEAD (dst); |
|
|
lbitset_zero (dst); |
|
|
return changed; |
|
|
} |
|
|
else |
|
|
return lbitset_op3_cmp (dst, src1, src2, BITSET_OP_AND); |
|
|
} |
|
|
|
|
|
|
|
|
static void |
|
|
lbitset_and (bitset dst, bitset src1, bitset src2) |
|
|
{ |
|
|
lbitset_and_cmp (dst, src1, src2); |
|
|
} |
|
|
|
|
|
|
|
|
static bool |
|
|
lbitset_andn_cmp (bitset dst, bitset src1, bitset src2) |
|
|
{ |
|
|
lbitset_elt *selt1 = LBITSET_HEAD (src1); |
|
|
lbitset_elt *selt2 = LBITSET_HEAD (src2); |
|
|
|
|
|
if (!selt2) |
|
|
{ |
|
|
return lbitset_copy_cmp (dst, src1); |
|
|
} |
|
|
else if (!selt1) |
|
|
{ |
|
|
lbitset_weed (dst); |
|
|
bool changed = !LBITSET_HEAD (dst); |
|
|
lbitset_zero (dst); |
|
|
return changed; |
|
|
} |
|
|
else |
|
|
return lbitset_op3_cmp (dst, src1, src2, BITSET_OP_ANDN); |
|
|
} |
|
|
|
|
|
|
|
|
static void |
|
|
lbitset_andn (bitset dst, bitset src1, bitset src2) |
|
|
{ |
|
|
lbitset_andn_cmp (dst, src1, src2); |
|
|
} |
|
|
|
|
|
|
|
|
static bool |
|
|
lbitset_or_cmp (bitset dst, bitset src1, bitset src2) |
|
|
{ |
|
|
lbitset_elt *selt1 = LBITSET_HEAD (src1); |
|
|
lbitset_elt *selt2 = LBITSET_HEAD (src2); |
|
|
|
|
|
if (!selt2) |
|
|
return lbitset_copy_cmp (dst, src1); |
|
|
else if (!selt1) |
|
|
return lbitset_copy_cmp (dst, src2); |
|
|
else |
|
|
return lbitset_op3_cmp (dst, src1, src2, BITSET_OP_OR); |
|
|
} |
|
|
|
|
|
|
|
|
static void |
|
|
lbitset_or (bitset dst, bitset src1, bitset src2) |
|
|
{ |
|
|
lbitset_or_cmp (dst, src1, src2); |
|
|
} |
|
|
|
|
|
|
|
|
static bool |
|
|
lbitset_xor_cmp (bitset dst, bitset src1, bitset src2) |
|
|
{ |
|
|
lbitset_elt *selt1 = LBITSET_HEAD (src1); |
|
|
lbitset_elt *selt2 = LBITSET_HEAD (src2); |
|
|
|
|
|
if (!selt2) |
|
|
return lbitset_copy_cmp (dst, src1); |
|
|
else if (!selt1) |
|
|
return lbitset_copy_cmp (dst, src2); |
|
|
else |
|
|
return lbitset_op3_cmp (dst, src1, src2, BITSET_OP_XOR); |
|
|
} |
|
|
|
|
|
|
|
|
static void |
|
|
lbitset_xor (bitset dst, bitset src1, bitset src2) |
|
|
{ |
|
|
lbitset_xor_cmp (dst, src1, src2); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct bitset_vtable lbitset_vtable = { |
|
|
lbitset_set, |
|
|
lbitset_reset, |
|
|
bitset_toggle_, |
|
|
lbitset_test, |
|
|
lbitset_resize, |
|
|
bitset_size_, |
|
|
bitset_count_, |
|
|
lbitset_empty_p, |
|
|
lbitset_ones, |
|
|
lbitset_zero, |
|
|
lbitset_copy, |
|
|
lbitset_disjoint_p, |
|
|
lbitset_equal_p, |
|
|
lbitset_not, |
|
|
lbitset_subset_p, |
|
|
lbitset_and, |
|
|
lbitset_and_cmp, |
|
|
lbitset_andn, |
|
|
lbitset_andn_cmp, |
|
|
lbitset_or, |
|
|
lbitset_or_cmp, |
|
|
lbitset_xor, |
|
|
lbitset_xor_cmp, |
|
|
bitset_and_or_, |
|
|
bitset_and_or_cmp_, |
|
|
bitset_andn_or_, |
|
|
bitset_andn_or_cmp_, |
|
|
bitset_or_and_, |
|
|
bitset_or_and_cmp_, |
|
|
lbitset_list, |
|
|
lbitset_list_reverse, |
|
|
lbitset_free, |
|
|
BITSET_LIST |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
size_t |
|
|
lbitset_bytes (MAYBE_UNUSED bitset_bindex n_bits) |
|
|
{ |
|
|
return sizeof (struct lbitset_struct); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bitset |
|
|
lbitset_init (bitset bset, MAYBE_UNUSED bitset_bindex n_bits) |
|
|
{ |
|
|
BITSET_NBITS_ (bset) = n_bits; |
|
|
bset->b.vtable = &lbitset_vtable; |
|
|
return bset; |
|
|
} |
|
|
|
|
|
|
|
|
void |
|
|
lbitset_release_memory (void) |
|
|
{ |
|
|
lbitset_free_list = NULL; |
|
|
if (lbitset_obstack_init) |
|
|
{ |
|
|
lbitset_obstack_init = false; |
|
|
obstack_free (&lbitset_obstack, NULL); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
debug_lbitset (bitset bset) |
|
|
{ |
|
|
if (!bset) |
|
|
return; |
|
|
|
|
|
for (lbitset_elt *elt = LBITSET_HEAD (bset); elt; elt = elt->next) |
|
|
{ |
|
|
fprintf (stderr, "Elt %lu\n", (unsigned long) elt->index); |
|
|
for (unsigned i = 0; i < LBITSET_ELT_WORDS; i++) |
|
|
{ |
|
|
bitset_word word = elt->words[i]; |
|
|
|
|
|
fprintf (stderr, " Word %u:", i); |
|
|
for (unsigned j = 0; j < LBITSET_WORD_BITS; j++) |
|
|
if ((word & ((bitset_word) 1 << j))) |
|
|
fprintf (stderr, " %u", j); |
|
|
fprintf (stderr, "\n"); |
|
|
} |
|
|
} |
|
|
} |
|
|
|