From: Akim Demaille Date: Sun, 22 Nov 2020 15:46:47 +0000 (+0100) Subject: bitset: use integer_length in array implementation X-Git-Tag: v1.0~3454 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=911aba3a6d5545348a1fc7338901af2e8c383e47;p=gnulib.git bitset: use integer_length in array implementation * modules/bitset (Depends-on): Add integer_length_l. * lib/bitset/base.h (bitset_fls_, BITSET_FOR_EACH_BIT_REVERSE): New. * lib/bitset/array.c (abitset_list_reverse): Use it. --- diff --git a/ChangeLog b/ChangeLog index cb85238720..c3c5574f8e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2020-11-29 Akim Demaille + + bitset: use integer_length in array implementation + * modules/bitset (Depends-on): Add integer_length_l. + * lib/bitset/base.h (bitset_fls_, BITSET_FOR_EACH_BIT_REVERSE): New. + * lib/bitset/array.c (abitset_list_reverse): Use it. + 2020-11-29 Akim Demaille bitset: style: use consistent names diff --git a/lib/bitset/array.c b/lib/bitset/array.c index 0e90b6b1fe..34773c7873 100644 --- a/lib/bitset/array.c +++ b/lib/bitset/array.c @@ -143,19 +143,18 @@ abitset_list_reverse (bitset src, bitset_bindex *list, do { - bitset_word word = srcp[windex] << (BITSET_WORD_BITS - 1 - bitcnt); - for (; word; bitcnt--) + bitset_word word = srcp[windex]; + if (bitcnt + 1 < BITSET_WORD_BITS) + /* We're starting in the middle of a word: smash bits to ignore. */ + word &= ((bitset_word) 1 << (bitcnt + 1)) - 1; + BITSET_FOR_EACH_BIT_REVERSE(pos, word) { - if (word & BITSET_MSB) + list[count++] = bitoff + pos; + if (count >= num) { - list[count++] = bitoff + bitcnt; - if (count >= num) - { - *next = n_bits - (bitoff + bitcnt); - return count; - } + *next = n_bits - (bitoff + pos); + return count; } - word <<= 1; } bitoff -= BITSET_WORD_BITS; bitcnt = BITSET_WORD_BITS - 1; diff --git a/lib/bitset/base.h b/lib/bitset/base.h index a124b0df4d..fe447c269a 100644 --- a/lib/bitset/base.h +++ b/lib/bitset/base.h @@ -27,6 +27,7 @@ #include /* ffsl */ #include "attribute.h" +#include "integer_length.h" #include "xalloc.h" /* Currently we support five flavours of bitsets: @@ -286,6 +287,14 @@ if (!BITSET_COMPATIBLE_ (DST, SRC1) || !BITSET_COMPATIBLE_ (DST, SRC2) \ 0 <= Pos; \ Word ^= 1UL << Pos, Pos = bitset_ffs_ (Word)) +/* Iterate right to left over each set bit of WORD. + Each iteration sets POS to the 0-based index of the next set bit in WORD. + Repeatedly resets bits in WORD in place until it's null. */ +#define BITSET_FOR_EACH_BIT_REVERSE(Pos, Word) \ + for (int Pos = bitset_fls_ (Word); \ + 0 <= Pos; \ + Word ^= 1UL << Pos, Pos = bitset_fls_ (Word)) + /* Private functions for bitset implementations. */ bool bitset_toggle_ (bitset, bitset_bindex); @@ -316,4 +325,12 @@ int bitset_ffs_ (bitset_word word) return ffsl ((long) word) - 1; } +/* Last set bit in WORD. + Indexes start at 0, return -1 if WORD is null. */ +static inline +int bitset_fls_ (bitset_word word) +{ + return integer_length_l (word) - 1; +} + #endif /* _BBITSET_H */ diff --git a/modules/bitset b/modules/bitset index 2516c2861b..8c9cb7cc89 100644 --- a/modules/bitset +++ b/modules/bitset @@ -22,6 +22,7 @@ c99 ffsl fopen-gnu gettext-h +integer_length_l obstack xalloc