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
;
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 abitset_list (src
, list
, num
, next
)
247 bitset_windex windex
;
248 bitset_bindex bitoff
;
249 bitset_windex size
= src
->b
.csize
;
250 bitset_word
*srcp
= ABITSET_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
>= ABITSET_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 abitset_unused_clear (dst
)
346 unsigned int last_bit
;
348 last_bit
= ABITSET_N_BITS (dst
) % BITSET_WORD_BITS
;
350 ABITSET_WORDS (dst
)[dst
->b
.csize
- 1] &=
351 (bitset_word
) ((1 << last_bit
) - 1);
356 abitset_op1 (dst
, op
)
361 bitset_word
*dstp
= ABITSET_WORDS (dst
);
364 bytes
= sizeof (bitset_word
) * dst
->b
.csize
;
369 memset (dstp
, 0, bytes
);
373 memset (dstp
, ~0, bytes
);
374 abitset_unused_clear (dst
);
377 case BITSET_OP_EMPTY_P
:
378 for (i
= 0; i
< dst
->b
.csize
; i
++)
392 abitset_op2 (dst
, src
, op
)
398 bitset_word
*srcp
= ABITSET_WORDS (src
);
399 bitset_word
*dstp
= ABITSET_WORDS (dst
);
400 bitset_windex size
= dst
->b
.csize
;
407 memcpy (dstp
, srcp
, sizeof (bitset_word
) * size
);
411 for (i
= 0; i
< size
; i
++)
412 *dstp
++ = ~(*srcp
++);
413 abitset_unused_clear (dst
);
416 case BITSET_OP_EQUAL_P
:
417 for (i
= 0; i
< size
; i
++)
418 if (*srcp
++ != *dstp
++)
422 case BITSET_OP_SUBSET_P
:
423 for (i
= 0; i
< size
; i
++, dstp
++, srcp
++)
424 if (*dstp
!= (*srcp
| *dstp
))
428 case BITSET_OP_DISJOINT_P
:
429 for (i
= 0; i
< size
; i
++)
430 if (*srcp
++ & *dstp
++)
443 abitset_op3 (dst
, src1
, src2
, op
)
451 bitset_word
*src1p
= ABITSET_WORDS (src1
);
452 bitset_word
*src2p
= ABITSET_WORDS (src2
);
453 bitset_word
*dstp
= ABITSET_WORDS (dst
);
454 bitset_windex size
= dst
->b
.csize
;
459 for (i
= 0; i
< size
; i
++, dstp
++)
461 bitset_word tmp
= *src1p
++ | *src2p
++;
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
++);
519 abitset_op4 (dst
, src1
, src2
, src3
, op
)
528 bitset_word
*src1p
= ABITSET_WORDS (src1
);
529 bitset_word
*src2p
= ABITSET_WORDS (src2
);
530 bitset_word
*src3p
= ABITSET_WORDS (src3
);
531 bitset_word
*dstp
= ABITSET_WORDS (dst
);
532 bitset_windex size
= dst
->b
.csize
;
536 case BITSET_OP_OR_AND
:
537 for (i
= 0; i
< size
; i
++, dstp
++)
539 bitset_word tmp
= (*src1p
++ | *src2p
++) & *src3p
++;
549 case BITSET_OP_AND_OR
:
550 for (i
= 0; i
< size
; i
++, dstp
++)
552 bitset_word tmp
= (*src1p
++ & *src2p
++) | *src3p
++;
562 case BITSET_OP_ANDN_OR
:
563 for (i
= 0; i
< size
; i
++, dstp
++)
565 bitset_word tmp
= (*src1p
++ & ~(*src2p
++)) | *src3p
++;
583 /* Vector of operations for single word bitsets. */
584 struct bitset_ops_struct abitset_small_ops
= {
594 abitset_reverse_list
,
600 /* Vector of operations for multiple word bitsets. */
601 struct bitset_ops_struct abitset_ops
= {
611 abitset_reverse_list
,
618 abitset_bytes (n_bits
)
619 bitset_bindex n_bits
;
621 unsigned int bytes
, size
;
623 size
= ABITSET_N_WORDS (n_bits
);
624 bytes
= size
* sizeof (bitset_word
);
625 return sizeof (struct bitset_struct
) + bytes
- sizeof (bitset_word
);
630 abitset_init (bset
, n_bits
)
632 bitset_bindex n_bits
;
636 size
= ABITSET_N_WORDS (n_bits
);
637 ABITSET_N_BITS (bset
) = n_bits
;
639 /* Use optimized routines if bitset fits within a single word.
640 There is probably little merit if using caching since
641 the small bitset will always fit in the cache. */
643 bset
->b
.ops
= &abitset_small_ops
;
645 bset
->b
.ops
= &abitset_ops
;
648 bset
->b
.csize
= size
;
649 bset
->b
.cdata
= ABITSET_WORDS (bset
);