2    Copyright (C) 2002 Free Software Foundation, Inc. 
   3    Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz). 
   5    This program is free software; you can redistribute it and/or modify 
   6    it under the terms of the GNU General Public License as published by 
   7    the Free Software Foundation; either version 2 of the License, or 
   8    (at your option) any later version. 
  10    This program is distributed in the hope that it will be useful, 
  11    but WITHOUT ANY WARRANTY; without even the implied warranty of 
  12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  13    GNU General Public License for more details. 
  15    You should have received a copy of the GNU General Public License 
  16    along with this program; if not, write to the Free Software 
  17    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ 
  27 /* This file implements fixed size bitsets stored as an array 
  28    of words.  Any unused bits in the last word must be zero.  */ 
  30 typedef struct sbitset_struct
 
  32   unsigned int n_bits
;  /* Number of bits.  */ 
  33   bitset_word words
[1]; /* The array of bits.  */ 
  40   struct bbitset_struct b
; 
  41   struct sbitset_struct s
; 
  44 static void sbitset_unused_clear 
PARAMS ((bitset
)); 
  46 static int sbitset_small_list 
PARAMS ((bitset
, bitset_bindex 
*, bitset_bindex
, 
  49 static void sbitset_set 
PARAMS ((bitset
, bitset_bindex
)); 
  50 static void sbitset_reset 
PARAMS ((bitset
, bitset_bindex
)); 
  51 static int sbitset_test 
PARAMS ((bitset
, bitset_bindex
)); 
  52 static int sbitset_size 
PARAMS ((bitset
)); 
  53 static int sbitset_op1 
PARAMS ((bitset
, enum bitset_ops
)); 
  54 static int sbitset_op2 
PARAMS ((bitset
, bitset
, enum bitset_ops
)); 
  55 static int sbitset_op3 
PARAMS ((bitset
, bitset
, bitset
, enum bitset_ops
)); 
  56 static int sbitset_op4 
PARAMS ((bitset
, bitset
, bitset
, bitset
, 
  58 static int sbitset_list 
PARAMS ((bitset
, bitset_bindex 
*, bitset_bindex
, 
  60 static int sbitset_reverse_list
 
  61 PARAMS ((bitset
, bitset_bindex 
*, bitset_bindex
, bitset_bindex 
*)); 
  63 #define SBITSET_N_WORDS(N) (((N) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS) 
  64 #define SBITSET_WORDS(X) ((X)->s.words) 
  65 #define SBITSET_N_BITS(X) ((X)->s.n_bits) 
  68 /* Return size in bits of bitset SRC.  */ 
  73   return SBITSET_N_BITS (src
); 
  77 /* Find list of up to NUM bits set in BSET starting from and including 
  78  *NEXT and store in array LIST.  Return with actual number of bits 
  79  found and with *NEXT indicating where search stopped.  */ 
  81 sbitset_small_list (src
, list
, num
, next
) 
  92   word 
= SBITSET_WORDS (src
)[0]; 
  94   /* Short circuit common case.  */ 
  98   size 
= SBITSET_N_BITS (src
); 
 105   /* If num is 1, we could speed things up with a binary search 
 106      of the word of interest.  */ 
 108   if (num 
>= BITSET_WORD_BITS
) 
 110       for (count 
= 0; word
; bitno
++) 
 113             list
[count
++] = bitno
; 
 119       for (count 
= 0; word
; bitno
++) 
 123               list
[count
++] = bitno
; 
 139 /* Set bit BITNO in bitset DST.  */ 
 141 sbitset_set (dst
, bitno
) 
 142      bitset dst ATTRIBUTE_UNUSED
; 
 143      bitset_bindex bitno ATTRIBUTE_UNUSED
; 
 145   /* This should never occur for sbitsets.  */ 
 150 /* Reset bit BITNO in bitset DST.  */ 
 152 sbitset_reset (dst
, bitno
) 
 153      bitset dst ATTRIBUTE_UNUSED
; 
 154      bitset_bindex bitno ATTRIBUTE_UNUSED
; 
 156   /* This should never occur for sbitsets.  */ 
 161 /* Test bit BITNO in bitset SRC.  */ 
 163 sbitset_test (src
, bitno
) 
 164      bitset src ATTRIBUTE_UNUSED
; 
 165      bitset_bindex bitno ATTRIBUTE_UNUSED
; 
 167   /* This should never occur for sbitsets.  */ 
 173 /* Find list of up to NUM bits set in BSET in reverse order, starting 
 174    from and including NEXT and store in array LIST.  Return with 
 175    actual number of bits found and with *NEXT indicating where search 
 178 sbitset_reverse_list (src
, list
, num
, next
) 
 185   bitset_bindex rbitno
; 
 189   bitset_bindex bitoff
; 
 191   bitset_word 
*srcp 
= SBITSET_WORDS (src
); 
 192   bitset_bindex n_bits 
= SBITSET_N_BITS (src
); 
 196   /* If num is 1, we could speed things up with a binary search 
 197      of the word of interest.  */ 
 199   if (rbitno 
>= n_bits
) 
 204   bitno 
= n_bits 
- (rbitno 
+ 1); 
 206   index 
= bitno 
/ BITSET_WORD_BITS
; 
 207   bitcnt 
= bitno 
% BITSET_WORD_BITS
; 
 208   bitoff 
= index 
* BITSET_WORD_BITS
; 
 210   for (; index 
!= ~0U; index
--, bitoff 
-= BITSET_WORD_BITS
, 
 211          bitcnt 
= BITSET_WORD_BITS 
- 1) 
 213       word 
= srcp
[index
] << (BITSET_WORD_BITS 
- 1 - bitcnt
); 
 214       for (; word
; bitcnt
--) 
 216           if (word 
& BITSET_MSB
) 
 218               list
[count
++] = bitoff 
+ bitcnt
; 
 221                   *next 
= n_bits 
- (bitoff 
+ bitcnt
); 
 229   *next 
= n_bits 
- (bitoff 
+ 1); 
 234 /* Find list of up to NUM bits set in BSET starting from and including 
 235  *NEXT and store in array LIST.  Return with actual number of bits 
 236  found and with *NEXT indicating where search stopped.  */ 
 238 sbitset_list (src
, list
, num
, next
) 
 247   bitset_bindex bitoff
; 
 248   bitset_windex size 
= src
->b
.csize
; 
 249   bitset_word 
*srcp 
= SBITSET_WORDS (src
); 
 257       /* Many bitsets are zero, so make this common case fast.  */ 
 258       for (index 
= 0; index 
< size 
&& !srcp
[index
]; index
++) 
 263       /* If num is 1, we could speed things up with a binary search 
 264          of the current word.  */ 
 266       bitoff 
= index 
* BITSET_WORD_BITS
; 
 270       if (bitno 
>= SBITSET_N_BITS (src
)) 
 273       index 
= bitno 
/ BITSET_WORD_BITS
; 
 274       bitno 
= bitno 
% BITSET_WORD_BITS
; 
 278           /* Handle the case where we start within a word. 
 279              Most often, this is executed with large bitsets 
 280              with many set bits where we filled the array 
 281              on the previous call to this function.  */ 
 283           bitoff 
= index 
* BITSET_WORD_BITS
; 
 284           word 
= srcp
[index
] >> bitno
; 
 285           for (bitno 
= bitoff 
+ bitno
; word
; bitno
++) 
 289                   list
[count
++] = bitno
; 
 300       bitoff 
= index 
* BITSET_WORD_BITS
; 
 303   for (; index 
< size
; index
++, bitoff 
+= BITSET_WORD_BITS
) 
 305       if (!(word 
= srcp
[index
])) 
 308       if ((count 
+ BITSET_WORD_BITS
) < num
) 
 310           for (bitno 
= bitoff
; word
; bitno
++) 
 313                 list
[count
++] = bitno
; 
 319           for (bitno 
= bitoff
; word
; bitno
++) 
 323                   list
[count
++] = bitno
; 
 340 /* Ensure that any unused bits within the last word are clear.  */ 
 342 sbitset_unused_clear (dst
) 
 345   unsigned int last_bit
; 
 347   last_bit 
= SBITSET_N_BITS (dst
) % BITSET_WORD_BITS
; 
 349     SBITSET_WORDS (dst
)[dst
->b
.csize 
- 1] &= 
 350       (bitset_word
) ((1 << last_bit
) - 1); 
 355 sbitset_op1 (dst
, op
) 
 360   bitset_word 
*dstp 
= SBITSET_WORDS (dst
); 
 363   bytes 
= sizeof (bitset_word
) * dst
->b
.csize
; 
 368       memset (dstp
, 0, bytes
); 
 372       memset (dstp
, ~0, bytes
); 
 373       sbitset_unused_clear (dst
); 
 376     case BITSET_OP_EMPTY_P
: 
 377       for (i 
= 0; i 
< dst
->b
.csize
; i
++) 
 391 sbitset_op2 (dst
, src
, op
) 
 397   bitset_word 
*srcp 
= SBITSET_WORDS (src
); 
 398   bitset_word 
*dstp 
= SBITSET_WORDS (dst
); 
 399   bitset_windex size 
= dst
->b
.csize
; 
 401 #ifdef ENABLE_CHECKING 
 402   /* Check for compatiblity.  */ 
 403   if (SBITSET_N_BITS (src
) != SBITSET_N_BITS (dst
)) 
 412       memcpy (dstp
, srcp
, sizeof (bitset_word
) * size
); 
 416       for (i 
= 0; i 
< size
; i
++) 
 417         *dstp
++ = ~(*srcp
++); 
 418       sbitset_unused_clear (dst
); 
 421     case BITSET_OP_EQUAL_P
: 
 422       for (i 
= 0; i 
< size
; i
++) 
 423         if (*srcp
++ != *dstp
++) 
 427     case BITSET_OP_SUBSET_P
: 
 428       for (i 
= 0; i 
< size
; i
++, dstp
++, srcp
++) 
 429         if (*dstp 
!= (*srcp 
| *dstp
)) 
 433     case BITSET_OP_DISJOINT_P
: 
 434       for (i 
= 0; i 
< size
; i
++) 
 435         if (*srcp
++ & *dstp
++) 
 448 sbitset_op3 (dst
, src1
, src2
, op
) 
 456   bitset_word 
*src1p 
= SBITSET_WORDS (src1
); 
 457   bitset_word 
*src2p 
= SBITSET_WORDS (src2
); 
 458   bitset_word 
*dstp 
= SBITSET_WORDS (dst
); 
 459   bitset_windex size 
= dst
->b
.csize
; 
 461 #ifdef ENABLE_CHECKING 
 462   /* Check for compatiblity.  */ 
 463   if (SBITSET_N_BITS (src1
) != SBITSET_N_BITS (dst
) 
 464       SBITSET_N_BITS (src2
) != SBITSET_N_BITS (dst
)) 
 471       for (i 
= 0; i 
< size
; i
++, dstp
++) 
 473           bitset_word tmp 
= *src1p
++ | *src2p
++; 
 484       for (i 
= 0; i 
< size
; i
++, dstp
++) 
 486           bitset_word tmp 
= *src1p
++ & *src2p
++; 
 497       for (i 
= 0; i 
< size
; i
++, dstp
++) 
 499           bitset_word tmp 
= *src1p
++ ^ *src2p
++; 
 510       for (i 
= 0; i 
< size
; i
++, dstp
++) 
 512           bitset_word tmp 
= *src1p
++ & ~(*src2p
++); 
 523       for (i 
= 0; i 
< size
; i
++, dstp
++) 
 525           bitset_word tmp 
= *src1p
++ | ~(*src2p
++); 
 533       sbitset_unused_clear (dst
); 
 545 sbitset_op4 (dst
, src1
, src2
, src3
, op
) 
 554   bitset_word 
*src1p 
= SBITSET_WORDS (src1
); 
 555   bitset_word 
*src2p 
= SBITSET_WORDS (src2
); 
 556   bitset_word 
*src3p 
= SBITSET_WORDS (src3
); 
 557   bitset_word 
*dstp 
= SBITSET_WORDS (dst
); 
 558   bitset_windex size 
= dst
->b
.csize
; 
 560 #ifdef ENABLE_CHECKING 
 561   /* Check for compatiblity.  */ 
 562   if (SBITSET_N_BITS (src1
) != SBITSET_N_BITS (dst
) 
 563       || SBITSET_N_BITS (src2
) != SBITSET_N_BITS (dst
) 
 564       || SBITSET_N_BITS (src3
) != SBITSET_N_BITS (dst
)) 
 570     case BITSET_OP_OR_AND
: 
 571       for (i 
= 0; i 
< size
; i
++, dstp
++) 
 573           bitset_word tmp 
= (*src1p
++ | *src2p
++) & *src3p
++; 
 583     case BITSET_OP_AND_OR
: 
 584       for (i 
= 0; i 
< size
; i
++, dstp
++) 
 586           bitset_word tmp 
= (*src1p
++ & *src2p
++) | *src3p
++; 
 596     case BITSET_OP_ANDN_OR
: 
 597       for (i 
= 0; i 
< size
; i
++, dstp
++) 
 599           bitset_word tmp 
= (*src1p
++ & ~(*src2p
++)) | *src3p
++; 
 617 /* Vector of operations for single word bitsets.  */ 
 618 struct bitset_ops_struct sbitset_small_ops 
= { 
 628   sbitset_reverse_list
, 
 634 /* Vector of operations for multiple word bitsets.  */ 
 635 struct bitset_ops_struct sbitset_ops 
= { 
 645   sbitset_reverse_list
, 
 652 sbitset_bytes (n_bits
) 
 653      bitset_bindex n_bits
; 
 655   unsigned int bytes
, size
; 
 657   size 
= SBITSET_N_WORDS (n_bits
); 
 658   bytes 
= size 
* sizeof (bitset_word
); 
 659   return sizeof (struct bitset_struct
) + bytes 
- sizeof (bitset_word
); 
 664 sbitset_init (bset
, n_bits
) 
 666      bitset_bindex n_bits
; 
 670   size 
= SBITSET_N_WORDS (n_bits
); 
 671   SBITSET_N_BITS (bset
) = n_bits
; 
 673   /* Use optimized routines if bitset fits within a single word. 
 674      There is probably little merit if using caching since 
 675      the small bitset will always fit in the cache.  */ 
 677     bset
->b
.ops 
= &sbitset_small_ops
; 
 679     bset
->b
.ops 
= &sbitset_ops
; 
 682   bset
->b
.csize 
= size
; 
 683   bset
->b
.cdata 
= SBITSET_WORDS (bset
);