/[bison]/bison/lib/ebitset.c
ViewVC logotype

Diff of /bison/lib/ebitset.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.11 by eggert, Sat May 24 19:16:02 2003 UTC revision 1.12 by eggert, Tue Jun 17 07:23:46 2003 UTC
# Line 24  Line 24 
24  #include "ebitset.h"  #include "ebitset.h"
25  #include "obstack.h"  #include "obstack.h"
26  #include <stdlib.h>  #include <stdlib.h>
27    #include <string.h>
28    
29  /* This file implements expandable bitsets.  These bitsets can be of  /* This file implements expandable bitsets.  These bitsets can be of
30     arbitrary length and are more efficient than arrays of bits for     arbitrary length and are more efficient than arrays of bits for
# Line 75  typedef ebitset_elt *ebitset_elts; Line 76  typedef ebitset_elt *ebitset_elts;
76  #define EBITSET_INITIAL_SIZE 2  #define EBITSET_INITIAL_SIZE 2
77  #endif  #endif
78    
 /* Minimum number of elements to grow table.  */  
   
 #ifndef EBITSET_GROW_SIZE  
 #define EBITSET_GROW_SIZE 4  
 #endif  
79    
80  enum ebitset_find_mode  enum ebitset_find_mode
81    { EBITSET_FIND, EBITSET_CREATE, EBITSET_SUBST };    { EBITSET_FIND, EBITSET_CREATE, EBITSET_SUBST };
# Line 91  static struct obstack ebitset_obstack; Line 87  static struct obstack ebitset_obstack;
87  static bool ebitset_obstack_init = false;  static bool ebitset_obstack_init = false;
88  static ebitset_elt *ebitset_free_list;  /* Free list of bitset elements.  */  static ebitset_elt *ebitset_free_list;  /* Free list of bitset elements.  */
89    
90    #define EBITSET_N_ELTS(N) (((N) + EBITSET_ELT_BITS - 1) / EBITSET_ELT_BITS)
91  #define EBITSET_ELTS(BSET) ((BSET)->e.elts)  #define EBITSET_ELTS(BSET) ((BSET)->e.elts)
92  #define EBITSET_SIZE(BSET) ((BSET)->e.size)  #define EBITSET_SIZE(BSET) EBITSET_N_ELTS (BITSET_NBITS_ (BSET))
93    #define EBITSET_ASIZE(BSET) ((BSET)->e.size)
94    
95  #define EBITSET_NEXT(ELT) ((ELT)->u.next)  #define EBITSET_NEXT(ELT) ((ELT)->u.next)
96  #define EBITSET_WORDS(ELT) ((ELT)->u.words)  #define EBITSET_WORDS(ELT) ((ELT)->u.words)
# Line 118  static ebitset_elt *ebitset_free_list; / Line 116  static ebitset_elt *ebitset_free_list; /
116    (BSET)->b.cdata = EBITSET_WORDS (EBITSET_ELTS (BSET) [EINDEX]))    (BSET)->b.cdata = EBITSET_WORDS (EBITSET_ELTS (BSET) [EINDEX]))
117    
118    
119  /* Grow the expandable table for BSET by SIZE elements.  */  #define min(a, b) ((a) > (b) ? (b) : (a))
120  static void  #define max(a, b) ((a) > (b) ? (a) : (b))
121  ebitset_elts_grow (bitset bset, bitset_windex size)  
122    
123    static bitset_bindex
124    ebitset_resize (bitset src, bitset_bindex n_bits)
125  {  {
126    bitset_windex oldsize;    bitset_windex oldsize;
127    bitset_windex newsize;    bitset_windex newsize;
128    
129    oldsize = EBITSET_SIZE (bset);    if (n_bits == BITSET_NBITS_ (src))
130    newsize = oldsize + size;      return n_bits;
131    
132      oldsize = EBITSET_SIZE (src);
133      newsize = EBITSET_N_ELTS (n_bits);
134    
135      if (oldsize < newsize)
136        {
137          bitset_windex size;
138    
139          /* The bitset needs to grow.  If we already have enough memory
140             allocated, then just zero what we need.  */
141          if (newsize > EBITSET_ASIZE (src))
142            {
143              /* We need to allocate more memory.  When oldsize is
144                 non-zero this means that we are changing the size, so
145                 grow the bitset 25% larger than requested to reduce
146                 number of reallocations.  */
147    
148              if (oldsize == 0)
149                size = newsize;
150              else
151                size = newsize + newsize / 4;
152              
153              EBITSET_ELTS (src)
154                = realloc (EBITSET_ELTS (src), size * sizeof (ebitset_elt *));
155              EBITSET_ASIZE (src) = size;
156            }
157    
158    if (BITSET_SIZE_MAX / sizeof (ebitset_elt *) < newsize)        memset (EBITSET_ELTS (src) + oldsize, 0,
159      xalloc_die ();                (newsize - oldsize) * sizeof (ebitset_elt *));
160        }
161      else
162        {
163          /* The bitset needs to shrink.  There's no point deallocating
164             the memory unless it is shrinking by a reasonable amount.  */
165          if ((oldsize - newsize) >= oldsize / 2)
166            {
167              EBITSET_ELTS (src)
168                = realloc (EBITSET_ELTS (src), newsize * sizeof (ebitset_elt *));
169              EBITSET_ASIZE (src) = newsize;
170            }
171    
172    EBITSET_ELTS (bset) = xrealloc (EBITSET_ELTS (bset),        /* Need to prune any excess bits.  FIXME.  */
173                                    newsize * sizeof (ebitset_elt *));      }
   EBITSET_SIZE (bset) = newsize;  
174    
175    memset (EBITSET_ELTS (bset) + oldsize, 0, size * sizeof (ebitset_elt *));    BITSET_NBITS_ (src) = n_bits;
176      return n_bits;
177  }  }
178    
179    
# Line 257  ebitset_elt_zero_p (ebitset_elt *elt) Line 295  ebitset_elt_zero_p (ebitset_elt *elt)
295    
296    
297  static ebitset_elt *  static ebitset_elt *
298  ebitset_elt_find (bitset bset, bitset_windex windex,  ebitset_elt_find (bitset bset, bitset_bindex bindex,
299                    enum ebitset_find_mode mode)                    enum ebitset_find_mode mode)
300  {  {
301    ebitset_elt *elt;    ebitset_elt *elt;
# Line 265  ebitset_elt_find (bitset bset, bitset_wi Line 303  ebitset_elt_find (bitset bset, bitset_wi
303    bitset_windex eindex;    bitset_windex eindex;
304    ebitset_elts *elts;    ebitset_elts *elts;
305    
306    eindex = windex / EBITSET_ELT_WORDS;    eindex = bindex / EBITSET_ELT_BITS;
307    
308    elts = EBITSET_ELTS (bset);    elts = EBITSET_ELTS (bset);
309    size = EBITSET_SIZE (bset);    size = EBITSET_SIZE (bset);
# Line 291  ebitset_elt_find (bitset bset, bitset_wi Line 329  ebitset_elt_find (bitset bset, bitset_wi
329    
330      case EBITSET_CREATE:      case EBITSET_CREATE:
331        if (eindex >= size)        if (eindex >= size)
332          {          ebitset_resize (bset, bindex);
           bitset_windex extra;  
   
           extra = eindex - size + 1;  
   
           /* We need to expand the table by EXTRA elements.  It may be  
              better with large bitsets to grow the number of  
              elements by some fraction of the current size otherwise  
              we can spend a lot of time slowly increasing the size of the  
              bitset.  */  
           if (extra < EBITSET_GROW_SIZE)  
             extra = EBITSET_GROW_SIZE;  
   
           ebitset_elts_grow (bset, extra);  
         }  
333    
334        /* Create a new element.  */        /* Create a new element.  */
335        elt = ebitset_elt_calloc ();        elt = ebitset_elt_calloc ();
# Line 322  ebitset_elt_find (bitset bset, bitset_wi Line 346  ebitset_elt_find (bitset bset, bitset_wi
346  }  }
347    
348    
 static inline ebitset_elt *  
 ebitset_elt_last (bitset bset)  
 {  
   ebitset_elts *elts;  
   
   elts = EBITSET_ELTS (bset);  
   
   /* Assume that have at least one element in elts.  */  
   return elts[EBITSET_SIZE (bset) - 1];  
 }  
   
   
349  /* Weed out the zero elements from the elts.  */  /* Weed out the zero elements from the elts.  */
350  static inline bitset_windex  static inline bitset_windex
351  ebitset_weed (bitset bset)  ebitset_weed (bitset bset)
# Line 353  ebitset_weed (bitset bset) Line 365  ebitset_weed (bitset bset)
365    
366        if (elt)        if (elt)
367          {          {
368            if (elt && ebitset_elt_zero_p (elt))            if (ebitset_elt_zero_p (elt))
369              {              {
370                ebitset_elt_remove (bset, j);                ebitset_elt_remove (bset, j);
371                count++;                count++;
# Line 453  ebitset_copy_ (bitset dst, bitset src) Line 465  ebitset_copy_ (bitset dst, bitset src)
465    
466    ebitset_zero (dst);    ebitset_zero (dst);
467    
468    if (EBITSET_SIZE (dst) < EBITSET_SIZE (src))    if (BITSET_NBITS_ (dst) != BITSET_NBITS_ (src))
469      ebitset_elts_grow (dst, EBITSET_SIZE (src) - EBITSET_SIZE (dst));      ebitset_resize (dst, BITSET_NBITS_ (src));
470    
471    selts = EBITSET_ELTS (src);    selts = EBITSET_ELTS (src);
472    delts = EBITSET_ELTS (dst);    delts = EBITSET_ELTS (dst);
# Line 498  ebitset_copy_cmp (bitset dst, bitset src Line 510  ebitset_copy_cmp (bitset dst, bitset src
510  }  }
511    
512    
 /* Return size in bits of bitset SRC.  */  
 static bitset_bindex  
 ebitset_size (bitset src)  
 {  
   /* Return current size of bitset in bits.  */  
   return EBITSET_SIZE (src) * EBITSET_ELT_BITS;  
 }  
   
   
513  /* Set bit BITNO in bitset DST.  */  /* Set bit BITNO in bitset DST.  */
514  static void  static void
515  ebitset_set (bitset dst, bitset_bindex bitno)  ebitset_set (bitset dst, bitset_bindex bitno)
516  {  {
517    bitset_windex windex = bitno / BITSET_WORD_BITS;    bitset_windex windex = bitno / BITSET_WORD_BITS;
518    
519    ebitset_elt_find (dst, windex, EBITSET_CREATE);    ebitset_elt_find (dst, bitno, EBITSET_CREATE);
520    
521    dst->b.cdata[windex - dst->b.cindex] |=    dst->b.cdata[windex - dst->b.cindex] |=
522      (bitset_word) 1 << (bitno % BITSET_WORD_BITS);      (bitset_word) 1 << (bitno % BITSET_WORD_BITS);
# Line 526  ebitset_reset (bitset dst, bitset_bindex Line 529  ebitset_reset (bitset dst, bitset_bindex
529  {  {
530    bitset_windex windex = bitno / BITSET_WORD_BITS;    bitset_windex windex = bitno / BITSET_WORD_BITS;
531    
532    if (!ebitset_elt_find (dst, windex, EBITSET_FIND))    if (!ebitset_elt_find (dst, bitno, EBITSET_FIND))
533      return;      return;
534    
535    dst->b.cdata[windex - dst->b.cindex] &=    dst->b.cdata[windex - dst->b.cindex] &=
# Line 544  ebitset_test (bitset src, bitset_bindex Line 547  ebitset_test (bitset src, bitset_bindex
547  {  {
548    bitset_windex windex = bitno / BITSET_WORD_BITS;    bitset_windex windex = bitno / BITSET_WORD_BITS;
549    
550    return (ebitset_elt_find (src, windex, EBITSET_FIND)    return (ebitset_elt_find (src, bitno, EBITSET_FIND)
551            && ((src->b.cdata[windex - src->b.cindex]            && ((src->b.cdata[windex - src->b.cindex]
552                 >> (bitno % BITSET_WORD_BITS))                 >> (bitno % BITSET_WORD_BITS))
553                & 1));                & 1));
# Line 731  ebitset_list (bitset bset, bitset_bindex Line 734  ebitset_list (bitset bset, bitset_bindex
734          {          {
735            /* The coast is clear, plant boot!  */            /* The coast is clear, plant boot!  */
736    
737    #if EBITSET_ELT_WORDS == 2
738              word = srcp[0];
739              if (word)
740                {
741                  if (!(word & 0xffff))
742                    {
743                      word >>= 16;
744                      bitno += 16;
745                    }
746                  if (!(word & 0xff))
747                    {
748                      word >>= 8;
749                      bitno += 8;
750                    }
751                  for (; word; bitno++)
752                    {
753                      if (word & 1)
754                        list[count++] = bitno;
755                      word >>= 1;
756                    }
757                }
758              windex++;
759              bitno = windex * BITSET_WORD_BITS;
760    
761              word = srcp[1];
762              if (word)
763                {
764                  if (!(word & 0xffff))
765                    {
766                      word >>= 16;
767                      bitno += 16;
768                    }
769                  for (; word; bitno++)
770                    {
771                      if (word & 1)
772                        list[count++] = bitno;
773                      word >>= 1;
774                    }
775                }
776              windex++;
777              bitno = windex * BITSET_WORD_BITS;
778    #else
779            for (i = 0; i < EBITSET_ELT_WORDS; i++, windex++)            for (i = 0; i < EBITSET_ELT_WORDS; i++, windex++)
780              {              {
781                bitno = windex * BITSET_WORD_BITS;                bitno = windex * BITSET_WORD_BITS;
# Line 756  ebitset_list (bitset bset, bitset_bindex Line 801  ebitset_list (bitset bset, bitset_bindex
801                      }                      }
802                  }                  }
803              }              }
804    #endif
805          }          }
806        else        else
807          {          {
# Line 788  ebitset_list (bitset bset, bitset_bindex Line 834  ebitset_list (bitset bset, bitset_bindex
834  }  }
835    
836    
837    /* Ensure that any unused bits within the last element are clear.  */
838    static inline void
839    ebitset_unused_clear (bitset dst)
840    {
841      unsigned int last_bit;
842      bitset_bindex n_bits;
843      
844      n_bits = BITSET_NBITS_ (dst);
845      last_bit = n_bits % EBITSET_ELT_BITS;
846      
847      if (last_bit)
848        {
849          bitset_windex eindex;
850          ebitset_elts *elts;
851          ebitset_elt *elt;
852    
853          elts = EBITSET_ELTS (dst);
854          
855          eindex = n_bits / EBITSET_ELT_BITS;
856          
857          elt = elts[eindex];
858          if (elt)
859            {
860              bitset_windex windex;
861              bitset_windex woffset;
862              bitset_word *srcp = EBITSET_WORDS (elt);
863              
864              windex = n_bits / BITSET_WORD_BITS;
865              woffset = eindex * EBITSET_ELT_WORDS;
866              
867              srcp[windex - woffset] &= ((bitset_word) 1 << last_bit) - 1;    
868              windex++;
869              for (; (windex - woffset) < EBITSET_ELT_WORDS; windex++)
870                srcp[windex - woffset] = 0;
871            }
872        }
873    }
874    
875    
876  static void  static void
877  ebitset_ones (bitset dst)  ebitset_ones (bitset dst)
878  {  {
879    bitset_windex j;    bitset_windex j;
880    ebitset_elt *elt;    ebitset_elt *elt;
881    
   
882    for (j = 0; j < EBITSET_SIZE (dst); j++)    for (j = 0; j < EBITSET_SIZE (dst); j++)
883      {      {
884        /* Create new elements if they cannot be found.  Perhaps        /* Create new elements if they cannot be found.  Perhaps
885           we should just add pointers to a ones element.  */           we should just add pointers to a ones element?  */
886        elt =        elt =
887          ebitset_elt_find (dst, j * EBITSET_ELT_WORDS, EBITSET_CREATE);          ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_CREATE);
888        memset (EBITSET_WORDS (elt), -1, sizeof (EBITSET_WORDS (elt)));        memset (EBITSET_WORDS (elt), -1, sizeof (EBITSET_WORDS (elt)));
889      }      }
890    EBITSET_NONZERO_SET (dst);    EBITSET_NONZERO_SET (dst);
891      ebitset_unused_clear (dst);
892  }  }
893    
894    
895  static bool  static bool
896  ebitset_empty_p (bitset dst)  ebitset_empty_p (bitset dst)
897  {  {
898    return !ebitset_weed (dst);    ebitset_elts *elts;
899      bitset_windex j;
900    
901      if (EBITSET_ZERO_P (dst))
902        return 1;
903    
904      elts = EBITSET_ELTS (dst);
905      for (j = 0; j < EBITSET_SIZE (dst); j++)
906        {
907          ebitset_elt *elt = elts[j];
908    
909          if (elt)
910            {
911              if (!ebitset_elt_zero_p (elt))
912                return 0;
913              /* Do some weeding as we go.  */
914              ebitset_elt_remove (dst, j);
915            }
916        }
917    
918      /* All the bits are zero.  We could shrink the elts.
919         For now just mark DST as known to be zero.  */
920      EBITSET_ZERO_SET (dst);
921      return 1;
922  }  }
923    
924    
# Line 822  ebitset_not (bitset dst, bitset src) Line 930  ebitset_not (bitset dst, bitset src)
930    ebitset_elt *delt;    ebitset_elt *delt;
931    bitset_windex j;    bitset_windex j;
932    
933      ebitset_resize (dst, BITSET_NBITS_ (src));
934    
935    for (j = 0; j < EBITSET_SIZE (src); j++)    for (j = 0; j < EBITSET_SIZE (src); j++)
936      {      {
937        /* Create new elements for dst if they cannot be found        /* Create new elements for dst if they cannot be found
938               or substitute zero elements if src elements not found.  */           or substitute zero elements if src elements not found.  */
939        selt =        selt =
940          ebitset_elt_find (dst, j * EBITSET_ELT_WORDS, EBITSET_SUBST);          ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_SUBST);
941        delt =        delt =
942          ebitset_elt_find (dst, j * EBITSET_ELT_WORDS, EBITSET_CREATE);          ebitset_elt_find (dst, j * EBITSET_ELT_BITS, EBITSET_CREATE);
943    
944        for (i = 0; i < EBITSET_ELT_WORDS; i++)        for (i = 0; i < EBITSET_ELT_WORDS; i++)
945          EBITSET_WORDS (delt)[i] = ~EBITSET_WORDS (selt)[i];          EBITSET_WORDS (delt)[i] = ~EBITSET_WORDS (selt)[i];
946      }      }
947    EBITSET_NONZERO_SET (dst);    EBITSET_NONZERO_SET (dst);
948      ebitset_unused_clear (dst);
949  }  }
950    
951    
# Line 934  ebitset_op3_cmp (bitset dst, bitset src1 Line 1045  ebitset_op3_cmp (bitset dst, bitset src1
1045    unsigned int i;    unsigned int i;
1046    bitset_windex j;    bitset_windex j;
1047    
1048      ebitset_resize (dst, max (BITSET_NBITS_ (src1), BITSET_NBITS_ (src2)));
1049    
1050    ssize1 = EBITSET_SIZE (src1);    ssize1 = EBITSET_SIZE (src1);
1051    ssize2 = EBITSET_SIZE (src2);    ssize2 = EBITSET_SIZE (src2);
1052    dsize = EBITSET_SIZE (dst);    dsize = EBITSET_SIZE (dst);
# Line 941  ebitset_op3_cmp (bitset dst, bitset src1 Line 1054  ebitset_op3_cmp (bitset dst, bitset src1
1054    if (size < ssize2)    if (size < ssize2)
1055      size = ssize2;      size = ssize2;
1056    
   if (size > dsize)  
     ebitset_elts_grow (dst, size - dsize);  
   
1057    selts1 = EBITSET_ELTS (src1);    selts1 = EBITSET_ELTS (src1);
1058    selts2 = EBITSET_ELTS (src2);    selts2 = EBITSET_ELTS (src2);
1059    delts = EBITSET_ELTS (dst);    delts = EBITSET_ELTS (dst);
# Line 1183  struct bitset_vtable ebitset_vtable = { Line 1293  struct bitset_vtable ebitset_vtable = {
1293    ebitset_reset,    ebitset_reset,
1294    bitset_toggle_,    bitset_toggle_,
1295    ebitset_test,    ebitset_test,
1296    ebitset_size,    ebitset_resize,
1297      bitset_size_,
1298    bitset_count_,    bitset_count_,
1299    ebitset_empty_p,    ebitset_empty_p,
1300    ebitset_ones,    ebitset_ones,
# Line 1238  ebitset_init (bitset bset, bitset_bindex Line 1349  ebitset_init (bitset bset, bitset_bindex
1349    size = n_bits ? (n_bits + EBITSET_ELT_BITS - 1) / EBITSET_ELT_BITS    size = n_bits ? (n_bits + EBITSET_ELT_BITS - 1) / EBITSET_ELT_BITS
1350      : EBITSET_INITIAL_SIZE;      : EBITSET_INITIAL_SIZE;
1351    
1352    EBITSET_SIZE (bset) = 0;    EBITSET_ASIZE (bset) = 0;
1353    EBITSET_ELTS (bset) = 0;    EBITSET_ELTS (bset) = 0;
1354    ebitset_elts_grow (bset, size);    ebitset_resize (bset, n_bits);
1355    
1356    return bset;    return bset;
1357  }  }

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.12

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26