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
);