]> git.saurik.com Git - bison.git/blame - lib/abitset.c
(INCLUDES): Do not include from the intl directory, which has been
[bison.git] / lib / abitset.c
CommitLineData
613f5e1a 1/* Array bitsets.
7086e707
AD
2 Copyright (C) 2002 Free Software Foundation, Inc.
3 Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
4
ef017502
AD
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.
7086e707 9
ef017502
AD
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.
7086e707 14
ef017502
AD
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
345cea78
AD
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18*/
7086e707
AD
19
20#ifdef HAVE_CONFIG_H
21#include "config.h"
22#endif
23
613f5e1a 24#include "abitset.h"
7086e707 25#include <stdlib.h>
ef017502 26#include <string.h>
7086e707
AD
27
28/* This file implements fixed size bitsets stored as an array
29 of words. Any unused bits in the last word must be zero. */
30
613f5e1a 31typedef struct abitset_struct
ef017502
AD
32{
33 unsigned int n_bits; /* Number of bits. */
34 bitset_word words[1]; /* The array of bits. */
35}
613f5e1a 36*abitset;
ef017502
AD
37
38
39struct bitset_struct
40{
41 struct bbitset_struct b;
613f5e1a 42 struct abitset_struct a;
ef017502
AD
43};
44
613f5e1a 45static void abitset_unused_clear PARAMS ((bitset));
ef017502 46
613f5e1a 47static int abitset_small_list PARAMS ((bitset, bitset_bindex *, bitset_bindex,
ef017502
AD
48 bitset_bindex *));
49
613f5e1a
AD
50static void abitset_set PARAMS ((bitset, bitset_bindex));
51static void abitset_reset PARAMS ((bitset, bitset_bindex));
52static int abitset_test PARAMS ((bitset, bitset_bindex));
53static int abitset_size PARAMS ((bitset));
54static int abitset_op1 PARAMS ((bitset, enum bitset_ops));
55static int abitset_op2 PARAMS ((bitset, bitset, enum bitset_ops));
56static int abitset_op3 PARAMS ((bitset, bitset, bitset, enum bitset_ops));
57static int abitset_op4 PARAMS ((bitset, bitset, bitset, bitset,
ef017502 58 enum bitset_ops));
613f5e1a 59static int abitset_list PARAMS ((bitset, bitset_bindex *, bitset_bindex,
ef017502 60 bitset_bindex *));
613f5e1a 61static int abitset_reverse_list
ef017502 62PARAMS ((bitset, bitset_bindex *, bitset_bindex, bitset_bindex *));
7086e707 63
613f5e1a
AD
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)
7086e707
AD
67
68
69/* Return size in bits of bitset SRC. */
70static int
613f5e1a 71abitset_size (src)
7086e707
AD
72 bitset src;
73{
613f5e1a 74 return ABITSET_N_BITS (src);
7086e707
AD
75}
76
77
78/* Find list of up to NUM bits set in BSET starting from and including
ef017502
AD
79 *NEXT and store in array LIST. Return with actual number of bits
80 found and with *NEXT indicating where search stopped. */
7086e707 81static int
613f5e1a 82abitset_small_list (src, list, num, next)
7086e707
AD
83 bitset src;
84 bitset_bindex *list;
85 bitset_bindex num;
86 bitset_bindex *next;
87{
88 bitset_bindex bitno;
89 bitset_bindex count;
90 bitset_windex size;
91 bitset_word word;
92
613f5e1a 93 word = ABITSET_WORDS (src)[0];
7086e707
AD
94
95 /* Short circuit common case. */
96 if (!word)
97 return 0;
98
613f5e1a 99 size = ABITSET_N_BITS (src);
7086e707
AD
100 bitno = *next;
101 if (bitno >= size)
102 return 0;
103
104 word >>= bitno;
105
106 /* If num is 1, we could speed things up with a binary search
107 of the word of interest. */
108
109 if (num >= BITSET_WORD_BITS)
ef017502 110 {
7086e707 111 for (count = 0; word; bitno++)
ef017502 112 {
7086e707 113 if (word & 1)
ef017502 114 list[count++] = bitno;
7086e707 115 word >>= 1;
ef017502
AD
116 }
117 }
7086e707 118 else
ef017502 119 {
7086e707 120 for (count = 0; word; bitno++)
ef017502 121 {
7086e707 122 if (word & 1)
ef017502 123 {
7086e707
AD
124 list[count++] = bitno;
125 if (count >= num)
ef017502 126 {
7086e707
AD
127 bitno++;
128 break;
ef017502
AD
129 }
130 }
7086e707 131 word >>= 1;
ef017502
AD
132 }
133 }
7086e707
AD
134
135 *next = bitno;
136 return count;
137}
138
139
140/* Set bit BITNO in bitset DST. */
141static void
613f5e1a 142abitset_set (dst, bitno)
7086e707
AD
143 bitset dst ATTRIBUTE_UNUSED;
144 bitset_bindex bitno ATTRIBUTE_UNUSED;
145{
613f5e1a 146 /* This should never occur for abitsets. */
ef017502 147 abort ();
7086e707
AD
148}
149
150
151/* Reset bit BITNO in bitset DST. */
152static void
613f5e1a 153abitset_reset (dst, bitno)
7086e707
AD
154 bitset dst ATTRIBUTE_UNUSED;
155 bitset_bindex bitno ATTRIBUTE_UNUSED;
156{
613f5e1a 157 /* This should never occur for abitsets. */
ef017502 158 abort ();
7086e707
AD
159}
160
161
162/* Test bit BITNO in bitset SRC. */
163static int
613f5e1a 164abitset_test (src, bitno)
7086e707
AD
165 bitset src ATTRIBUTE_UNUSED;
166 bitset_bindex bitno ATTRIBUTE_UNUSED;
167{
613f5e1a 168 /* This should never occur for abitsets. */
ef017502
AD
169 abort ();
170 return 0;
7086e707
AD
171}
172
173
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
177 stopped. */
178static int
613f5e1a 179abitset_reverse_list (src, list, num, next)
7086e707
AD
180 bitset src;
181 bitset_bindex *list;
182 bitset_bindex num;
183 bitset_bindex *next;
184{
185 bitset_bindex bitno;
186 bitset_bindex rbitno;
187 bitset_bindex count;
345cea78 188 bitset_windex windex;
7086e707
AD
189 unsigned int bitcnt;
190 bitset_bindex bitoff;
191 bitset_word word;
613f5e1a
AD
192 bitset_word *srcp = ABITSET_WORDS (src);
193 bitset_bindex n_bits = ABITSET_N_BITS (src);
7086e707
AD
194
195 rbitno = *next;
196
197 /* If num is 1, we could speed things up with a binary search
198 of the word of interest. */
199
200 if (rbitno >= n_bits)
ef017502 201 return 0;
7086e707
AD
202
203 count = 0;
204
205 bitno = n_bits - (rbitno + 1);
206
345cea78 207 windex = bitno / BITSET_WORD_BITS;
7086e707 208 bitcnt = bitno % BITSET_WORD_BITS;
345cea78 209 bitoff = windex * BITSET_WORD_BITS;
7086e707 210
345cea78 211 for (; windex != ~0U; windex--, bitoff -= BITSET_WORD_BITS,
ef017502 212 bitcnt = BITSET_WORD_BITS - 1)
7086e707 213 {
345cea78 214 word = srcp[windex] << (BITSET_WORD_BITS - 1 - bitcnt);
7086e707
AD
215 for (; word; bitcnt--)
216 {
217 if (word & BITSET_MSB)
218 {
219 list[count++] = bitoff + bitcnt;
220 if (count >= num)
221 {
222 *next = n_bits - (bitoff + bitcnt);
223 return count;
224 }
225 }
226 word <<= 1;
227 }
228 }
229
230 *next = n_bits - (bitoff + 1);
231 return count;
232}
233
234
235/* Find list of up to NUM bits set in BSET starting from and including
ef017502
AD
236 *NEXT and store in array LIST. Return with actual number of bits
237 found and with *NEXT indicating where search stopped. */
7086e707 238static int
613f5e1a 239abitset_list (src, list, num, next)
7086e707
AD
240 bitset src;
241 bitset_bindex *list;
242 bitset_bindex num;
243 bitset_bindex *next;
244{
245 bitset_bindex bitno;
246 bitset_bindex count;
345cea78 247 bitset_windex windex;
7086e707 248 bitset_bindex bitoff;
ef017502 249 bitset_windex size = src->b.csize;
613f5e1a 250 bitset_word *srcp = ABITSET_WORDS (src);
7086e707
AD
251 bitset_word word;
252
253 bitno = *next;
254
255 count = 0;
ef017502 256 if (!bitno)
7086e707
AD
257 {
258 /* Many bitsets are zero, so make this common case fast. */
345cea78 259 for (windex = 0; windex < size && !srcp[windex]; windex++)
7086e707 260 continue;
345cea78 261 if (windex >= size)
7086e707
AD
262 return 0;
263
264 /* If num is 1, we could speed things up with a binary search
265 of the current word. */
266
345cea78 267 bitoff = windex * BITSET_WORD_BITS;
7086e707
AD
268 }
269 else
270 {
613f5e1a 271 if (bitno >= ABITSET_N_BITS (src))
7086e707
AD
272 return 0;
273
345cea78 274 windex = bitno / BITSET_WORD_BITS;
7086e707
AD
275 bitno = bitno % BITSET_WORD_BITS;
276
277 if (bitno)
278 {
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. */
283
345cea78
AD
284 bitoff = windex * BITSET_WORD_BITS;
285 word = srcp[windex] >> bitno;
7086e707
AD
286 for (bitno = bitoff + bitno; word; bitno++)
287 {
288 if (word & 1)
289 {
290 list[count++] = bitno;
291 if (count >= num)
292 {
293 *next = bitno + 1;
294 return count;
295 }
296 }
297 word >>= 1;
298 }
345cea78 299 windex++;
7086e707 300 }
345cea78 301 bitoff = windex * BITSET_WORD_BITS;
7086e707
AD
302 }
303
345cea78 304 for (; windex < size; windex++, bitoff += BITSET_WORD_BITS)
7086e707 305 {
345cea78 306 if (!(word = srcp[windex]))
7086e707
AD
307 continue;
308
309 if ((count + BITSET_WORD_BITS) < num)
ef017502
AD
310 {
311 for (bitno = bitoff; word; bitno++)
312 {
313 if (word & 1)
314 list[count++] = bitno;
315 word >>= 1;
316 }
317 }
7086e707
AD
318 else
319 {
320 for (bitno = bitoff; word; bitno++)
321 {
322 if (word & 1)
323 {
324 list[count++] = bitno;
325 if (count >= num)
326 {
327 *next = bitno + 1;
328 return count;
329 }
330 }
331 word >>= 1;
332 }
333 }
334 }
335
336 *next = bitoff;
337 return count;
338}
339
340
341/* Ensure that any unused bits within the last word are clear. */
342static inline void
613f5e1a 343abitset_unused_clear (dst)
7086e707
AD
344 bitset dst;
345{
346 unsigned int last_bit;
347
613f5e1a 348 last_bit = ABITSET_N_BITS (dst) % BITSET_WORD_BITS;
7086e707 349 if (last_bit)
613f5e1a 350 ABITSET_WORDS (dst)[dst->b.csize - 1] &=
ef017502 351 (bitset_word) ((1 << last_bit) - 1);
7086e707
AD
352}
353
354
355static int
613f5e1a 356abitset_op1 (dst, op)
7086e707
AD
357 bitset dst;
358 enum bitset_ops op;
359{
360 unsigned int i;
613f5e1a 361 bitset_word *dstp = ABITSET_WORDS (dst);
7086e707
AD
362 unsigned int bytes;
363
ef017502 364 bytes = sizeof (bitset_word) * dst->b.csize;
7086e707
AD
365
366 switch (op)
367 {
ef017502 368 case BITSET_OP_ZERO:
7086e707
AD
369 memset (dstp, 0, bytes);
370 break;
371
ef017502 372 case BITSET_OP_ONES:
7086e707 373 memset (dstp, ~0, bytes);
613f5e1a 374 abitset_unused_clear (dst);
7086e707
AD
375 break;
376
ef017502
AD
377 case BITSET_OP_EMPTY_P:
378 for (i = 0; i < dst->b.csize; i++)
7086e707
AD
379 if (dstp[i])
380 return 0;
381 break;
382
383 default:
384 abort ();
385 }
386
387 return 1;
388}
389
390
391static int
613f5e1a 392abitset_op2 (dst, src, op)
7086e707
AD
393 bitset dst;
394 bitset src;
395 enum bitset_ops op;
396{
397 unsigned int i;
613f5e1a
AD
398 bitset_word *srcp = ABITSET_WORDS (src);
399 bitset_word *dstp = ABITSET_WORDS (dst);
ef017502 400 bitset_windex size = dst->b.csize;
7086e707 401
7086e707
AD
402 switch (op)
403 {
ef017502 404 case BITSET_OP_COPY:
7086e707
AD
405 if (srcp == dstp)
406 break;
407 memcpy (dstp, srcp, sizeof (bitset_word) * size);
408 break;
409
ef017502 410 case BITSET_OP_NOT:
7086e707
AD
411 for (i = 0; i < size; i++)
412 *dstp++ = ~(*srcp++);
613f5e1a 413 abitset_unused_clear (dst);
7086e707
AD
414 break;
415
ef017502 416 case BITSET_OP_EQUAL_P:
7086e707 417 for (i = 0; i < size; i++)
ef017502 418 if (*srcp++ != *dstp++)
7086e707
AD
419 return 0;
420 break;
ef017502
AD
421
422 case BITSET_OP_SUBSET_P:
7086e707 423 for (i = 0; i < size; i++, dstp++, srcp++)
ef017502
AD
424 if (*dstp != (*srcp | *dstp))
425 return 0;
7086e707 426 break;
ef017502
AD
427
428 case BITSET_OP_DISJOINT_P:
429 for (i = 0; i < size; i++)
430 if (*srcp++ & *dstp++)
431 return 0;
432 break;
433
7086e707
AD
434 default:
435 abort ();
436 }
437
438 return 1;
439}
440
441
442static int
613f5e1a 443abitset_op3 (dst, src1, src2, op)
7086e707
AD
444 bitset dst;
445 bitset src1;
446 bitset src2;
447 enum bitset_ops op;
448{
449 unsigned int i;
450 int changed = 0;
613f5e1a
AD
451 bitset_word *src1p = ABITSET_WORDS (src1);
452 bitset_word *src2p = ABITSET_WORDS (src2);
453 bitset_word *dstp = ABITSET_WORDS (dst);
ef017502 454 bitset_windex size = dst->b.csize;
7086e707 455
7086e707
AD
456 switch (op)
457 {
ef017502 458 case BITSET_OP_OR:
7086e707
AD
459 for (i = 0; i < size; i++, dstp++)
460 {
461 bitset_word tmp = *src1p++ | *src2p++;
462
463 if (*dstp != tmp)
464 {
465 changed = 1;
466 *dstp = tmp;
467 }
468 }
469 break;
470
ef017502 471 case BITSET_OP_AND:
7086e707
AD
472 for (i = 0; i < size; i++, dstp++)
473 {
474 bitset_word tmp = *src1p++ & *src2p++;
475
476 if (*dstp != tmp)
477 {
478 changed = 1;
479 *dstp = tmp;
480 }
481 }
482 break;
483
ef017502 484 case BITSET_OP_XOR:
7086e707
AD
485 for (i = 0; i < size; i++, dstp++)
486 {
487 bitset_word tmp = *src1p++ ^ *src2p++;
488
489 if (*dstp != tmp)
490 {
491 changed = 1;
492 *dstp = tmp;
493 }
494 }
495 break;
496
ef017502 497 case BITSET_OP_ANDN:
7086e707
AD
498 for (i = 0; i < size; i++, dstp++)
499 {
500 bitset_word tmp = *src1p++ & ~(*src2p++);
501
502 if (*dstp != tmp)
503 {
504 changed = 1;
505 *dstp = tmp;
506 }
507 }
508 break;
509
7086e707
AD
510 default:
511 abort ();
512 }
513
514 return changed;
515}
516
517
518static int
613f5e1a 519abitset_op4 (dst, src1, src2, src3, op)
7086e707
AD
520 bitset dst;
521 bitset src1;
522 bitset src2;
523 bitset src3;
524 enum bitset_ops op;
525{
526 unsigned int i;
527 int changed = 0;
613f5e1a
AD
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);
ef017502 532 bitset_windex size = dst->b.csize;
7086e707 533
7086e707
AD
534 switch (op)
535 {
ef017502 536 case BITSET_OP_OR_AND:
7086e707
AD
537 for (i = 0; i < size; i++, dstp++)
538 {
539 bitset_word tmp = (*src1p++ | *src2p++) & *src3p++;
540
541 if (*dstp != tmp)
542 {
543 changed = 1;
544 *dstp = tmp;
545 }
546 }
547 break;
548
ef017502 549 case BITSET_OP_AND_OR:
7086e707
AD
550 for (i = 0; i < size; i++, dstp++)
551 {
552 bitset_word tmp = (*src1p++ & *src2p++) | *src3p++;
553
554 if (*dstp != tmp)
555 {
556 changed = 1;
557 *dstp = tmp;
558 }
559 }
560 break;
561
ef017502 562 case BITSET_OP_ANDN_OR:
7086e707
AD
563 for (i = 0; i < size; i++, dstp++)
564 {
565 bitset_word tmp = (*src1p++ & ~(*src2p++)) | *src3p++;
566
567 if (*dstp != tmp)
568 {
569 changed = 1;
570 *dstp = tmp;
571 }
572 }
573 break;
574
575 default:
576 abort ();
577 }
578
579 return changed;
580}
581
582
583/* Vector of operations for single word bitsets. */
613f5e1a
AD
584struct bitset_ops_struct abitset_small_ops = {
585 abitset_set,
586 abitset_reset,
587 abitset_test,
588 abitset_size,
589 abitset_op1,
590 abitset_op2,
591 abitset_op3,
592 abitset_op4,
593 abitset_small_list,
594 abitset_reverse_list,
ef017502
AD
595 NULL,
596 BITSET_ARRAY
597};
7086e707
AD
598
599
600/* Vector of operations for multiple word bitsets. */
613f5e1a
AD
601struct bitset_ops_struct abitset_ops = {
602 abitset_set,
603 abitset_reset,
604 abitset_test,
605 abitset_size,
606 abitset_op1,
607 abitset_op2,
608 abitset_op3,
609 abitset_op4,
610 abitset_list,
611 abitset_reverse_list,
ef017502
AD
612 NULL,
613 BITSET_ARRAY
7086e707
AD
614};
615
616
617int
613f5e1a 618abitset_bytes (n_bits)
7086e707
AD
619 bitset_bindex n_bits;
620{
621 unsigned int bytes, size;
622
613f5e1a 623 size = ABITSET_N_WORDS (n_bits);
7086e707
AD
624 bytes = size * sizeof (bitset_word);
625 return sizeof (struct bitset_struct) + bytes - sizeof (bitset_word);
626}
627
628
629bitset
613f5e1a 630abitset_init (bset, n_bits)
7086e707
AD
631 bitset bset;
632 bitset_bindex n_bits;
633{
634 bitset_windex size;
635
613f5e1a
AD
636 size = ABITSET_N_WORDS (n_bits);
637 ABITSET_N_BITS (bset) = n_bits;
7086e707
AD
638
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. */
642 if (size == 1)
613f5e1a 643 bset->b.ops = &abitset_small_ops;
7086e707 644 else
613f5e1a 645 bset->b.ops = &abitset_ops;
7086e707 646
ef017502
AD
647 bset->b.cindex = 0;
648 bset->b.csize = size;
613f5e1a 649 bset->b.cdata = ABITSET_WORDS (bset);
7086e707
AD
650 return bset;
651}