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.
28 /* This file implements fixed size bitsets stored as an array
29 of words. Any unused bits in the last word must be zero. */
31 typedef struct sbitset_struct
33 unsigned int n_bits
; /* Number of bits. */
34 bitset_word words
[1]; /* The array of bits. */
41 struct bbitset_struct b
;
42 struct sbitset_struct s
;
45 static void sbitset_unused_clear
PARAMS ((bitset
));
47 static int sbitset_small_list
PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
,
50 static void sbitset_set
PARAMS ((bitset
, bitset_bindex
));
51 static void sbitset_reset
PARAMS ((bitset
, bitset_bindex
));
52 static int sbitset_test
PARAMS ((bitset
, bitset_bindex
));
53 static int sbitset_size
PARAMS ((bitset
));
54 static int sbitset_op1
PARAMS ((bitset
, enum bitset_ops
));
55 static int sbitset_op2
PARAMS ((bitset
, bitset
, enum bitset_ops
));
56 static int sbitset_op3
PARAMS ((bitset
, bitset
, bitset
, enum bitset_ops
));
57 static int sbitset_op4
PARAMS ((bitset
, bitset
, bitset
, bitset
,
59 static int sbitset_list
PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
,
61 static int sbitset_reverse_list
62 PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
, bitset_bindex
*));
64 #define SBITSET_N_WORDS(N) (((N) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
65 #define SBITSET_WORDS(X) ((X)->s.words)
66 #define SBITSET_N_BITS(X) ((X)->s.n_bits)
69 /* Return size in bits of bitset SRC. */
74 return SBITSET_N_BITS (src
);
78 /* Find list of up to NUM bits set in BSET starting from and including
79 *NEXT and store in array LIST. Return with actual number of bits
80 found and with *NEXT indicating where search stopped. */
82 sbitset_small_list (src
, list
, num
, next
)
93 word
= SBITSET_WORDS (src
)[0];
95 /* Short circuit common case. */
99 size
= SBITSET_N_BITS (src
);
106 /* If num is 1, we could speed things up with a binary search
107 of the word of interest. */
109 if (num
>= BITSET_WORD_BITS
)
111 for (count
= 0; word
; bitno
++)
114 list
[count
++] = bitno
;
120 for (count
= 0; word
; bitno
++)
124 list
[count
++] = bitno
;
140 /* Set bit BITNO in bitset DST. */
142 sbitset_set (dst
, bitno
)
143 bitset dst ATTRIBUTE_UNUSED
;
144 bitset_bindex bitno ATTRIBUTE_UNUSED
;
146 /* This should never occur for sbitsets. */
151 /* Reset bit BITNO in bitset DST. */
153 sbitset_reset (dst
, bitno
)
154 bitset dst ATTRIBUTE_UNUSED
;
155 bitset_bindex bitno ATTRIBUTE_UNUSED
;
157 /* This should never occur for sbitsets. */
162 /* Test bit BITNO in bitset SRC. */
164 sbitset_test (src
, bitno
)
165 bitset src ATTRIBUTE_UNUSED
;
166 bitset_bindex bitno ATTRIBUTE_UNUSED
;
168 /* This should never occur for sbitsets. */
174 /* Find list of up to NUM bits set in BSET in reverse order, starting
175 from and including NEXT and store in array LIST. Return with
176 actual number of bits found and with *NEXT indicating where search
179 sbitset_reverse_list (src
, list
, num
, next
)
186 bitset_bindex rbitno
;
188 bitset_windex windex
;
190 bitset_bindex bitoff
;
192 bitset_word
*srcp
= SBITSET_WORDS (src
);
193 bitset_bindex n_bits
= SBITSET_N_BITS (src
);
197 /* If num is 1, we could speed things up with a binary search
198 of the word of interest. */
200 if (rbitno
>= n_bits
)
205 bitno
= n_bits
- (rbitno
+ 1);
207 windex
= bitno
/ BITSET_WORD_BITS
;
208 bitcnt
= bitno
% BITSET_WORD_BITS
;
209 bitoff
= windex
* BITSET_WORD_BITS
;
211 for (; windex
!= ~0U; windex
--, bitoff
-= BITSET_WORD_BITS
,
212 bitcnt
= BITSET_WORD_BITS
- 1)
214 word
= srcp
[windex
] << (BITSET_WORD_BITS
- 1 - bitcnt
);
215 for (; word
; bitcnt
--)
217 if (word
& BITSET_MSB
)
219 list
[count
++] = bitoff
+ bitcnt
;
222 *next
= n_bits
- (bitoff
+ bitcnt
);
230 *next
= n_bits
- (bitoff
+ 1);
235 /* Find list of up to NUM bits set in BSET starting from and including
236 *NEXT and store in array LIST. Return with actual number of bits
237 found and with *NEXT indicating where search stopped. */
239 sbitset_list (src
, list
, num
, next
)
247 bitset_windex windex
;
248 bitset_bindex bitoff
;
249 bitset_windex size
= src
->b
.csize
;
250 bitset_word
*srcp
= SBITSET_WORDS (src
);
258 /* Many bitsets are zero, so make this common case fast. */
259 for (windex
= 0; windex
< size
&& !srcp
[windex
]; windex
++)
264 /* If num is 1, we could speed things up with a binary search
265 of the current word. */
267 bitoff
= windex
* BITSET_WORD_BITS
;
271 if (bitno
>= SBITSET_N_BITS (src
))
274 windex
= bitno
/ BITSET_WORD_BITS
;
275 bitno
= bitno
% BITSET_WORD_BITS
;
279 /* Handle the case where we start within a word.
280 Most often, this is executed with large bitsets
281 with many set bits where we filled the array
282 on the previous call to this function. */
284 bitoff
= windex
* BITSET_WORD_BITS
;
285 word
= srcp
[windex
] >> bitno
;
286 for (bitno
= bitoff
+ bitno
; word
; bitno
++)
290 list
[count
++] = bitno
;
301 bitoff
= windex
* BITSET_WORD_BITS
;
304 for (; windex
< size
; windex
++, bitoff
+= BITSET_WORD_BITS
)
306 if (!(word
= srcp
[windex
]))
309 if ((count
+ BITSET_WORD_BITS
) < num
)
311 for (bitno
= bitoff
; word
; bitno
++)
314 list
[count
++] = bitno
;
320 for (bitno
= bitoff
; word
; bitno
++)
324 list
[count
++] = bitno
;
341 /* Ensure that any unused bits within the last word are clear. */
343 sbitset_unused_clear (dst
)
346 unsigned int last_bit
;
348 last_bit
= SBITSET_N_BITS (dst
) % BITSET_WORD_BITS
;
350 SBITSET_WORDS (dst
)[dst
->b
.csize
- 1] &=
351 (bitset_word
) ((1 << last_bit
) - 1);
356 sbitset_op1 (dst
, op
)
361 bitset_word
*dstp
= SBITSET_WORDS (dst
);
364 bytes
= sizeof (bitset_word
) * dst
->b
.csize
;
369 memset (dstp
, 0, bytes
);
373 memset (dstp
, ~0, bytes
);
374 sbitset_unused_clear (dst
);
377 case BITSET_OP_EMPTY_P
:
378 for (i
= 0; i
< dst
->b
.csize
; i
++)
392 sbitset_op2 (dst
, src
, op
)
398 bitset_word
*srcp
= SBITSET_WORDS (src
);
399 bitset_word
*dstp
= SBITSET_WORDS (dst
);
400 bitset_windex size
= dst
->b
.csize
;
402 #ifdef ENABLE_CHECKING
403 /* Check for compatiblity. */
404 if (SBITSET_N_BITS (src
) != SBITSET_N_BITS (dst
))
413 memcpy (dstp
, srcp
, sizeof (bitset_word
) * size
);
417 for (i
= 0; i
< size
; i
++)
418 *dstp
++ = ~(*srcp
++);
419 sbitset_unused_clear (dst
);
422 case BITSET_OP_EQUAL_P
:
423 for (i
= 0; i
< size
; i
++)
424 if (*srcp
++ != *dstp
++)
428 case BITSET_OP_SUBSET_P
:
429 for (i
= 0; i
< size
; i
++, dstp
++, srcp
++)
430 if (*dstp
!= (*srcp
| *dstp
))
434 case BITSET_OP_DISJOINT_P
:
435 for (i
= 0; i
< size
; i
++)
436 if (*srcp
++ & *dstp
++)
449 sbitset_op3 (dst
, src1
, src2
, op
)
457 bitset_word
*src1p
= SBITSET_WORDS (src1
);
458 bitset_word
*src2p
= SBITSET_WORDS (src2
);
459 bitset_word
*dstp
= SBITSET_WORDS (dst
);
460 bitset_windex size
= dst
->b
.csize
;
462 #ifdef ENABLE_CHECKING
463 /* Check for compatiblity. */
464 if (SBITSET_N_BITS (src1
) != SBITSET_N_BITS (dst
)
465 SBITSET_N_BITS (src2
) != SBITSET_N_BITS (dst
))
472 for (i
= 0; i
< size
; i
++, dstp
++)
474 bitset_word tmp
= *src1p
++ | *src2p
++;
485 for (i
= 0; i
< size
; i
++, dstp
++)
487 bitset_word tmp
= *src1p
++ & *src2p
++;
498 for (i
= 0; i
< size
; i
++, dstp
++)
500 bitset_word tmp
= *src1p
++ ^ *src2p
++;
511 for (i
= 0; i
< size
; i
++, dstp
++)
513 bitset_word tmp
= *src1p
++ & ~(*src2p
++);
532 sbitset_op4 (dst
, src1
, src2
, src3
, op
)
541 bitset_word
*src1p
= SBITSET_WORDS (src1
);
542 bitset_word
*src2p
= SBITSET_WORDS (src2
);
543 bitset_word
*src3p
= SBITSET_WORDS (src3
);
544 bitset_word
*dstp
= SBITSET_WORDS (dst
);
545 bitset_windex size
= dst
->b
.csize
;
547 #ifdef ENABLE_CHECKING
548 /* Check for compatiblity. */
549 if (SBITSET_N_BITS (src1
) != SBITSET_N_BITS (dst
)
550 || SBITSET_N_BITS (src2
) != SBITSET_N_BITS (dst
)
551 || SBITSET_N_BITS (src3
) != SBITSET_N_BITS (dst
))
557 case BITSET_OP_OR_AND
:
558 for (i
= 0; i
< size
; i
++, dstp
++)
560 bitset_word tmp
= (*src1p
++ | *src2p
++) & *src3p
++;
570 case BITSET_OP_AND_OR
:
571 for (i
= 0; i
< size
; i
++, dstp
++)
573 bitset_word tmp
= (*src1p
++ & *src2p
++) | *src3p
++;
583 case BITSET_OP_ANDN_OR
:
584 for (i
= 0; i
< size
; i
++, dstp
++)
586 bitset_word tmp
= (*src1p
++ & ~(*src2p
++)) | *src3p
++;
604 /* Vector of operations for single word bitsets. */
605 struct bitset_ops_struct sbitset_small_ops
= {
615 sbitset_reverse_list
,
621 /* Vector of operations for multiple word bitsets. */
622 struct bitset_ops_struct sbitset_ops
= {
632 sbitset_reverse_list
,
639 sbitset_bytes (n_bits
)
640 bitset_bindex n_bits
;
642 unsigned int bytes
, size
;
644 size
= SBITSET_N_WORDS (n_bits
);
645 bytes
= size
* sizeof (bitset_word
);
646 return sizeof (struct bitset_struct
) + bytes
- sizeof (bitset_word
);
651 sbitset_init (bset
, n_bits
)
653 bitset_bindex n_bits
;
657 size
= SBITSET_N_WORDS (n_bits
);
658 SBITSET_N_BITS (bset
) = n_bits
;
660 /* Use optimized routines if bitset fits within a single word.
661 There is probably little merit if using caching since
662 the small bitset will always fit in the cache. */
664 bset
->b
.ops
= &sbitset_small_ops
;
666 bset
->b
.ops
= &sbitset_ops
;
669 bset
->b
.csize
= size
;
670 bset
->b
.cdata
= SBITSET_WORDS (bset
);