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 # define DMALLOC_FUNC_CHECK
29 # endif /* WITH_DMALLOC */
31 /* This file implements fixed size bitsets stored as an array
32 of words. Any unused bits in the last word must be zero. */
34 static void sbitset_unused_clear
PARAMS((bitset
));
36 static int sbitset_small_list
PARAMS((bitset
, bitset_bindex
*, bitset_bindex
,
39 static void sbitset_set
PARAMS((bitset
, bitset_bindex
));
40 static void sbitset_reset
PARAMS((bitset
, bitset_bindex
));
41 static int sbitset_test
PARAMS((bitset
, bitset_bindex
));
42 static int sbitset_size
PARAMS((bitset
));
43 static int sbitset_op1
PARAMS((bitset
, enum bitset_ops
));
44 static int sbitset_op2
PARAMS((bitset
, bitset
, enum bitset_ops
));
45 static int sbitset_op3
PARAMS((bitset
, bitset
, bitset
, enum bitset_ops
));
46 static int sbitset_op4
PARAMS((bitset
, bitset
, bitset
, bitset
,
48 static int sbitset_list
PARAMS((bitset
, bitset_bindex
*, bitset_bindex
,
50 static int sbitset_reverse_list
PARAMS((bitset
, bitset_bindex
*, bitset_bindex
,
53 #define SBITSET_N_WORDS(N) (((N) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
54 #define SBITSET_WORDS(X) ((X)->u.s.words)
55 #define SBITSET_N_BITS(X) ((X)->u.s.n_bits)
58 /* Return size in bits of bitset SRC. */
63 return SBITSET_N_BITS (src
);
67 /* Find list of up to NUM bits set in BSET starting from and including
68 *NEXT and store in array LIST. Return with actual number of bits
69 found and with *NEXT indicating where search stopped. */
71 sbitset_small_list (src
, list
, num
, next
)
82 word
= SBITSET_WORDS (src
)[0];
84 /* Short circuit common case. */
88 size
= SBITSET_N_BITS (src
);
95 /* If num is 1, we could speed things up with a binary search
96 of the word of interest. */
98 if (num
>= BITSET_WORD_BITS
)
100 for (count
= 0; word
; bitno
++)
103 list
[count
++] = bitno
;
109 for (count
= 0; word
; bitno
++)
113 list
[count
++] = bitno
;
129 /* Set bit BITNO in bitset DST. */
131 sbitset_set (dst
, bitno
)
132 bitset dst ATTRIBUTE_UNUSED
;
133 bitset_bindex bitno ATTRIBUTE_UNUSED
;
135 /* This should never occur for sbitsets. */
140 /* Reset bit BITNO in bitset DST. */
142 sbitset_reset (dst
, bitno
)
143 bitset dst ATTRIBUTE_UNUSED
;
144 bitset_bindex bitno ATTRIBUTE_UNUSED
;
146 /* This should never occur for sbitsets. */
151 /* Test bit BITNO in bitset SRC. */
153 sbitset_test (src
, bitno
)
154 bitset src ATTRIBUTE_UNUSED
;
155 bitset_bindex bitno ATTRIBUTE_UNUSED
;
157 /* This should never occur for sbitsets. */
163 /* Find list of up to NUM bits set in BSET in reverse order, starting
164 from and including NEXT and store in array LIST. Return with
165 actual number of bits found and with *NEXT indicating where search
168 sbitset_reverse_list (src
, list
, num
, next
)
175 bitset_bindex rbitno
;
179 bitset_bindex bitoff
;
181 bitset_word
*srcp
= SBITSET_WORDS (src
);
182 bitset_bindex n_bits
= SBITSET_N_BITS (src
);
186 /* If num is 1, we could speed things up with a binary search
187 of the word of interest. */
189 if (rbitno
>= n_bits
)
194 bitno
= n_bits
- (rbitno
+ 1);
196 index
= bitno
/ BITSET_WORD_BITS
;
197 bitcnt
= bitno
% BITSET_WORD_BITS
;
198 bitoff
= index
* BITSET_WORD_BITS
;
200 for (; index
!= ~0U; index
--, bitoff
-= BITSET_WORD_BITS
,
201 bitcnt
= BITSET_WORD_BITS
- 1)
203 word
= srcp
[index
] << (BITSET_WORD_BITS
- 1 - bitcnt
);
204 for (; word
; bitcnt
--)
206 if (word
& BITSET_MSB
)
208 list
[count
++] = bitoff
+ bitcnt
;
211 *next
= n_bits
- (bitoff
+ bitcnt
);
219 *next
= n_bits
- (bitoff
+ 1);
224 /* Find list of up to NUM bits set in BSET starting from and including
225 *NEXT and store in array LIST. Return with actual number of bits
226 found and with *NEXT indicating where search stopped. */
228 sbitset_list (src
, list
, num
, next
)
237 bitset_bindex bitoff
;
238 bitset_windex size
= src
->csize
;
239 bitset_word
*srcp
= SBITSET_WORDS (src
);
247 /* Many bitsets are zero, so make this common case fast. */
248 for (index
= 0; index
< size
&& ! srcp
[index
]; index
++)
253 /* If num is 1, we could speed things up with a binary search
254 of the current word. */
256 bitoff
= index
* BITSET_WORD_BITS
;
260 if (bitno
>= SBITSET_N_BITS (src
))
263 index
= bitno
/ BITSET_WORD_BITS
;
264 bitno
= bitno
% BITSET_WORD_BITS
;
268 /* Handle the case where we start within a word.
269 Most often, this is executed with large bitsets
270 with many set bits where we filled the array
271 on the previous call to this function. */
273 bitoff
= index
* BITSET_WORD_BITS
;
274 word
= srcp
[index
] >> bitno
;
275 for (bitno
= bitoff
+ bitno
; word
; bitno
++)
279 list
[count
++] = bitno
;
290 bitoff
= index
* BITSET_WORD_BITS
;
293 for (; index
< size
; index
++, bitoff
+= BITSET_WORD_BITS
)
295 if (! (word
= srcp
[index
]))
298 if ((count
+ BITSET_WORD_BITS
) < num
)
300 for (bitno
= bitoff
; word
; bitno
++)
303 list
[count
++] = bitno
;
309 for (bitno
= bitoff
; word
; bitno
++)
313 list
[count
++] = bitno
;
330 /* Ensure that any unused bits within the last word are clear. */
332 sbitset_unused_clear (dst
)
335 unsigned int last_bit
;
337 last_bit
= SBITSET_N_BITS (dst
) % BITSET_WORD_BITS
;
339 SBITSET_WORDS (dst
)[dst
->csize
- 1] &= (bitset_word
)((1 << last_bit
) - 1);
344 sbitset_op1 (dst
, op
)
349 bitset_word
*dstp
= SBITSET_WORDS (dst
);
352 bytes
= sizeof (bitset_word
) * dst
->csize
;
357 memset (dstp
, 0, bytes
);
361 memset (dstp
, ~0, bytes
);
362 sbitset_unused_clear (dst
);
366 for (i
= 0; i
< dst
->csize
; i
++)
380 sbitset_op2 (dst
, src
, op
)
386 bitset_word
*srcp
= SBITSET_WORDS (src
);
387 bitset_word
*dstp
= SBITSET_WORDS (dst
);
388 bitset_windex size
= dst
->csize
;
390 #ifdef ENABLE_CHECKING
391 /* Check for compatiblity. */
392 if (src
->ops
!= dst
->ops
|| SBITSET_N_BITS (src
) != SBITSET_N_BITS (dst
))
401 memcpy (dstp
, srcp
, sizeof (bitset_word
) * size
);
405 for (i
= 0; i
< size
; i
++)
406 *dstp
++ = ~(*srcp
++);
407 sbitset_unused_clear (dst
);
411 for (i
= 0; i
< size
; i
++)
412 if (*dstp
++ != *srcp
++)
416 case BITSET_SUBSET_P
:
417 for (i
= 0; i
< size
; i
++, dstp
++, srcp
++)
419 if (*dstp
!= (*srcp
| *dstp
))
433 sbitset_op3 (dst
, src1
, src2
, op
)
441 bitset_word
*src1p
= SBITSET_WORDS (src1
);
442 bitset_word
*src2p
= SBITSET_WORDS (src2
);
443 bitset_word
*dstp
= SBITSET_WORDS (dst
);
444 bitset_windex size
= dst
->csize
;
446 #ifdef ENABLE_CHECKING
447 /* Check for compatiblity. */
448 if (src1
->ops
!= dst
->ops
|| SBITSET_N_BITS (src1
) != SBITSET_N_BITS (dst
)
449 || src2
->ops
!= dst
->ops
|| SBITSET_N_BITS (src2
) != SBITSET_N_BITS (dst
))
456 for (i
= 0; i
< size
; i
++, dstp
++)
458 bitset_word tmp
= *src1p
++ | *src2p
++;
469 for (i
= 0; i
< size
; i
++, dstp
++)
471 bitset_word tmp
= *src1p
++ & *src2p
++;
482 for (i
= 0; i
< size
; i
++, dstp
++)
484 bitset_word tmp
= *src1p
++ ^ *src2p
++;
495 for (i
= 0; i
< size
; i
++, dstp
++)
497 bitset_word tmp
= *src1p
++ & ~(*src2p
++);
508 for (i
= 0; i
< size
; i
++, dstp
++)
510 bitset_word tmp
= *src1p
++ | ~(*src2p
++);
518 sbitset_unused_clear (dst
);
530 sbitset_op4 (dst
, src1
, src2
, src3
, op
)
539 bitset_word
*src1p
= SBITSET_WORDS (src1
);
540 bitset_word
*src2p
= SBITSET_WORDS (src2
);
541 bitset_word
*src3p
= SBITSET_WORDS (src3
);
542 bitset_word
*dstp
= SBITSET_WORDS (dst
);
543 bitset_windex size
= dst
->csize
;
545 #ifdef ENABLE_CHECKING
546 /* Check for compatiblity. */
547 if (src1
->ops
!= dst
->ops
|| SBITSET_N_BITS (src1
) != SBITSET_N_BITS (dst
)
548 || src2
->ops
!= dst
->ops
|| SBITSET_N_BITS (src2
) != SBITSET_N_BITS (dst
)
549 || src3
->ops
!= dst
->ops
|| SBITSET_N_BITS (src3
) != SBITSET_N_BITS (dst
))
556 for (i
= 0; i
< size
; i
++, dstp
++)
558 bitset_word tmp
= (*src1p
++ | *src2p
++) & *src3p
++;
569 for (i
= 0; i
< size
; i
++, dstp
++)
571 bitset_word tmp
= (*src1p
++ & *src2p
++) | *src3p
++;
582 for (i
= 0; i
< size
; i
++, dstp
++)
584 bitset_word tmp
= (*src1p
++ & ~(*src2p
++)) | *src3p
++;
602 /* Vector of operations for single word bitsets. */
603 struct bitset_ops_struct sbitset_small_ops
=
614 sbitset_reverse_list
,
620 /* Vector of operations for multiple word bitsets. */
621 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
->ops
= &sbitset_small_ops
;
666 bset
->ops
= &sbitset_ops
;
670 bset
->cdata
= SBITSET_WORDS (bset
);