]> Savannah Git Hosting - gnulib.git/commitdiff
bitset: use integer_length in array implementation
authorAkim Demaille <akim.demaille@gmail.com>
Sun, 22 Nov 2020 15:46:47 +0000 (16:46 +0100)
committerAkim Demaille <akim.demaille@gmail.com>
Mon, 30 Nov 2020 05:53:53 +0000 (06:53 +0100)
* 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.

ChangeLog
lib/bitset/array.c
lib/bitset/base.h
modules/bitset

index cb85238720ef1e0738a8542e8e36953fc60f9348..c3c5574f8e9c1510450f6edeecff21fc51432712 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2020-11-29  Akim Demaille  <akim@lrde.epita.fr>
+
+       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  <akim@lrde.epita.fr>
 
        bitset: style: use consistent names
index 0e90b6b1fe8c7a7865a3bf7eb8ecbdf49a04a2ae..34773c787335a31ab25f9f923db955406fa89bc0 100644 (file)
@@ -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;
index a124b0df4da7737e92c774525fb5a4447d07f5f8..fe447c269a07fa5a5c0a5f6328a666b4665d2d79 100644 (file)
@@ -27,6 +27,7 @@
 #include <string.h> /* 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  */
index 2516c2861b745dc35097ff85919cf30d230aea0e..8c9cb7cc8956910b534ea97dd1116f0812d4394f 100644 (file)
@@ -22,6 +22,7 @@ c99
 ffsl
 fopen-gnu
 gettext-h
+integer_length_l
 obstack
 xalloc