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 abitset_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 abitset_struct a
;
45 static void abitset_unused_clear
PARAMS ((bitset
));
47 static int abitset_small_list
PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
,
50 static void abitset_set
PARAMS ((bitset
, bitset_bindex
));
51 static void abitset_reset
PARAMS ((bitset
, bitset_bindex
));
52 static int abitset_test
PARAMS ((bitset
, bitset_bindex
));
53 static int abitset_size
PARAMS ((bitset
));
54 static int abitset_op1
PARAMS ((bitset
, enum bitset_ops
));
55 static int abitset_op2
PARAMS ((bitset
, bitset
, enum bitset_ops
));
56 static int abitset_op3
PARAMS ((bitset
, bitset
, bitset
, enum bitset_ops
));
57 static int abitset_op4
PARAMS ((bitset
, bitset
, bitset
, bitset
,
59 static int abitset_list
PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
,
61 static int abitset_reverse_list
62 PARAMS ((bitset
, bitset_bindex
*, bitset_bindex
, bitset_bindex
*));
64 #define ABITSET_N_WORDS(N) (((N) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
65 #define ABITSET_WORDS(X) ((X)->a.words)
66 #define ABITSET_N_BITS(X) ((X)->a.n_bits)
69 /* Return size in bits of bitset SRC. */
74 return ABITSET_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 abitset_small_list (src
, list
, num
, next
)
93 word
= ABITSET_WORDS (src
)[0];
95 /* Short circuit common case. */
99 size
= ABITSET_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 abitset_set (dst
, bitno
)
143 bitset dst ATTRIBUTE_UNUSED
;
144 bitset_bindex bitno ATTRIBUTE_UNUSED
;
146 /* This should never occur for abitsets. */
151 /* Reset bit BITNO in bitset DST. */
153 abitset_reset (dst
, bitno
)
154 bitset dst ATTRIBUTE_UNUSED
;
155 bitset_bindex bitno ATTRIBUTE_UNUSED
;
157 /* This should never occur for abitsets. */
162 /* Test bit BITNO in bitset SRC. */
164 abitset_test (src
, bitno
)
165 bitset src ATTRIBUTE_UNUSED
;
166 bitset_bindex bitno ATTRIBUTE_UNUSED
;
168 /* This should never occur for abitsets. */
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 abitset_reverse_list (src
, list
, num
, next
)
186 bitset_bindex rbitno
;
188 bitset_windex windex
;
190 bitset_bindex bitoff
;
192 bitset_word
*srcp
= ABITSET_WORDS (src
);
193 bitset_bindex n_bits
= ABITSET_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
;
213 word
= srcp
[windex
] << (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
);
227 bitoff
-= BITSET_WORD_BITS
;
228 bitcnt
= BITSET_WORD_BITS
- 1;
232 *next
= n_bits
- (bitoff
+ 1);
237 /* Find list of up to NUM bits set in BSET starting from and including
238 *NEXT and store in array LIST. Return with actual number of bits
239 found and with *NEXT indicating where search stopped. */
241 abitset_list (src
, list
, num
, next
)
249 bitset_windex windex
;
250 bitset_bindex bitoff
;
251 bitset_windex size
= src
->b
.csize
;
252 bitset_word
*srcp
= ABITSET_WORDS (src
);
260 /* Many bitsets are zero, so make this common case fast. */
261 for (windex
= 0; windex
< size
&& !srcp
[windex
]; windex
++)
266 /* If num is 1, we could speed things up with a binary search
267 of the current word. */
269 bitoff
= windex
* BITSET_WORD_BITS
;
273 if (bitno
>= ABITSET_N_BITS (src
))
276 windex
= bitno
/ BITSET_WORD_BITS
;
277 bitno
= bitno
% BITSET_WORD_BITS
;
281 /* Handle the case where we start within a word.
282 Most often, this is executed with large bitsets
283 with many set bits where we filled the array
284 on the previous call to this function. */
286 bitoff
= windex
* BITSET_WORD_BITS
;
287 word
= srcp
[windex
] >> bitno
;
288 for (bitno
= bitoff
+ bitno
; word
; bitno
++)
292 list
[count
++] = bitno
;
303 bitoff
= windex
* BITSET_WORD_BITS
;
306 for (; windex
< size
; windex
++, bitoff
+= BITSET_WORD_BITS
)
308 if (!(word
= srcp
[windex
]))
311 if ((count
+ BITSET_WORD_BITS
) < num
)
313 for (bitno
= bitoff
; word
; bitno
++)
316 list
[count
++] = bitno
;
322 for (bitno
= bitoff
; word
; bitno
++)
326 list
[count
++] = bitno
;
343 /* Ensure that any unused bits within the last word are clear. */
345 abitset_unused_clear (dst
)
348 unsigned int last_bit
;
350 last_bit
= ABITSET_N_BITS (dst
) % BITSET_WORD_BITS
;
352 ABITSET_WORDS (dst
)[dst
->b
.csize
- 1] &=
353 ((bitset_word
) 1 << last_bit
) - 1;
358 abitset_op1 (dst
, op
)
363 bitset_word
*dstp
= ABITSET_WORDS (dst
);
366 bytes
= sizeof (bitset_word
) * dst
->b
.csize
;
371 memset (dstp
, 0, bytes
);
375 memset (dstp
, -1, bytes
);
376 abitset_unused_clear (dst
);
379 case BITSET_OP_EMPTY_P
:
380 for (i
= 0; i
< dst
->b
.csize
; i
++)
394 abitset_op2 (dst
, src
, op
)
400 bitset_word
*srcp
= ABITSET_WORDS (src
);
401 bitset_word
*dstp
= ABITSET_WORDS (dst
);
402 bitset_windex size
= dst
->b
.csize
;
409 memcpy (dstp
, srcp
, sizeof (bitset_word
) * size
);
413 for (i
= 0; i
< size
; i
++)
414 *dstp
++ = ~(*srcp
++);
415 abitset_unused_clear (dst
);
418 case BITSET_OP_EQUAL_P
:
419 for (i
= 0; i
< size
; i
++)
420 if (*srcp
++ != *dstp
++)
424 case BITSET_OP_SUBSET_P
:
425 for (i
= 0; i
< size
; i
++, dstp
++, srcp
++)
426 if (*dstp
!= (*srcp
| *dstp
))
430 case BITSET_OP_DISJOINT_P
:
431 for (i
= 0; i
< size
; i
++)
432 if (*srcp
++ & *dstp
++)
445 abitset_op3 (dst
, src1
, src2
, op
)
453 bitset_word
*src1p
= ABITSET_WORDS (src1
);
454 bitset_word
*src2p
= ABITSET_WORDS (src2
);
455 bitset_word
*dstp
= ABITSET_WORDS (dst
);
456 bitset_windex size
= dst
->b
.csize
;
461 for (i
= 0; i
< size
; i
++, dstp
++)
463 bitset_word tmp
= *src1p
++ | *src2p
++;
474 for (i
= 0; i
< size
; i
++, dstp
++)
476 bitset_word tmp
= *src1p
++ & *src2p
++;
487 for (i
= 0; i
< size
; i
++, dstp
++)
489 bitset_word tmp
= *src1p
++ ^ *src2p
++;
500 for (i
= 0; i
< size
; i
++, dstp
++)
502 bitset_word tmp
= *src1p
++ & ~(*src2p
++);
521 abitset_op4 (dst
, src1
, src2
, src3
, op
)
530 bitset_word
*src1p
= ABITSET_WORDS (src1
);
531 bitset_word
*src2p
= ABITSET_WORDS (src2
);
532 bitset_word
*src3p
= ABITSET_WORDS (src3
);
533 bitset_word
*dstp
= ABITSET_WORDS (dst
);
534 bitset_windex size
= dst
->b
.csize
;
538 case BITSET_OP_OR_AND
:
539 for (i
= 0; i
< size
; i
++, dstp
++)
541 bitset_word tmp
= (*src1p
++ | *src2p
++) & *src3p
++;
551 case BITSET_OP_AND_OR
:
552 for (i
= 0; i
< size
; i
++, dstp
++)
554 bitset_word tmp
= (*src1p
++ & *src2p
++) | *src3p
++;
564 case BITSET_OP_ANDN_OR
:
565 for (i
= 0; i
< size
; i
++, dstp
++)
567 bitset_word tmp
= (*src1p
++ & ~(*src2p
++)) | *src3p
++;
585 /* Vector of operations for single word bitsets. */
586 struct bitset_ops_struct abitset_small_ops
= {
596 abitset_reverse_list
,
602 /* Vector of operations for multiple word bitsets. */
603 struct bitset_ops_struct abitset_ops
= {
613 abitset_reverse_list
,
620 abitset_bytes (n_bits
)
621 bitset_bindex n_bits
;
623 unsigned int bytes
, size
;
625 size
= ABITSET_N_WORDS (n_bits
);
626 bytes
= size
* sizeof (bitset_word
);
627 return sizeof (struct bitset_struct
) + bytes
- sizeof (bitset_word
);
632 abitset_init (bset
, n_bits
)
634 bitset_bindex n_bits
;
638 size
= ABITSET_N_WORDS (n_bits
);
639 ABITSET_N_BITS (bset
) = n_bits
;
641 /* Use optimized routines if bitset fits within a single word.
642 There is probably little merit if using caching since
643 the small bitset will always fit in the cache. */
645 bset
->b
.ops
= &abitset_small_ops
;
647 bset
->b
.ops
= &abitset_ops
;
650 bset
->b
.csize
= size
;
651 bset
->b
.cdata
= ABITSET_WORDS (bset
);