]> git.saurik.com Git - bison.git/blame - lib/abitset.c
Sync with GNU tar.
[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
d6eba423 211 do
7086e707 212 {
345cea78 213 word = srcp[windex] << (BITSET_WORD_BITS - 1 - bitcnt);
7086e707
AD
214 for (; word; bitcnt--)
215 {
216 if (word & BITSET_MSB)
217 {
218 list[count++] = bitoff + bitcnt;
219 if (count >= num)
220 {
221 *next = n_bits - (bitoff + bitcnt);
222 return count;
223 }
224 }
225 word <<= 1;
226 }
d6eba423
PE
227 bitoff -= BITSET_WORD_BITS;
228 bitcnt = BITSET_WORD_BITS - 1;
7086e707 229 }
d6eba423 230 while (windex--);
7086e707
AD
231
232 *next = n_bits - (bitoff + 1);
233 return count;
234}
235
236
237/* Find list of up to NUM bits set in BSET starting from and including
ef017502
AD
238 *NEXT and store in array LIST. Return with actual number of bits
239 found and with *NEXT indicating where search stopped. */
7086e707 240static int
613f5e1a 241abitset_list (src, list, num, next)
7086e707
AD
242 bitset src;
243 bitset_bindex *list;
244 bitset_bindex num;
245 bitset_bindex *next;
246{
247 bitset_bindex bitno;
248 bitset_bindex count;
345cea78 249 bitset_windex windex;
7086e707 250 bitset_bindex bitoff;
ef017502 251 bitset_windex size = src->b.csize;
613f5e1a 252 bitset_word *srcp = ABITSET_WORDS (src);
7086e707
AD
253 bitset_word word;
254
255 bitno = *next;
256
257 count = 0;
ef017502 258 if (!bitno)
7086e707
AD
259 {
260 /* Many bitsets are zero, so make this common case fast. */
345cea78 261 for (windex = 0; windex < size && !srcp[windex]; windex++)
7086e707 262 continue;
345cea78 263 if (windex >= size)
7086e707
AD
264 return 0;
265
266 /* If num is 1, we could speed things up with a binary search
267 of the current word. */
268
345cea78 269 bitoff = windex * BITSET_WORD_BITS;
7086e707
AD
270 }
271 else
272 {
613f5e1a 273 if (bitno >= ABITSET_N_BITS (src))
7086e707
AD
274 return 0;
275
345cea78 276 windex = bitno / BITSET_WORD_BITS;
7086e707
AD
277 bitno = bitno % BITSET_WORD_BITS;
278
279 if (bitno)
280 {
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. */
285
345cea78
AD
286 bitoff = windex * BITSET_WORD_BITS;
287 word = srcp[windex] >> bitno;
7086e707
AD
288 for (bitno = bitoff + bitno; word; bitno++)
289 {
290 if (word & 1)
291 {
292 list[count++] = bitno;
293 if (count >= num)
294 {
295 *next = bitno + 1;
296 return count;
297 }
298 }
299 word >>= 1;
300 }
345cea78 301 windex++;
7086e707 302 }
345cea78 303 bitoff = windex * BITSET_WORD_BITS;
7086e707
AD
304 }
305
345cea78 306 for (; windex < size; windex++, bitoff += BITSET_WORD_BITS)
7086e707 307 {
345cea78 308 if (!(word = srcp[windex]))
7086e707
AD
309 continue;
310
311 if ((count + BITSET_WORD_BITS) < num)
ef017502
AD
312 {
313 for (bitno = bitoff; word; bitno++)
314 {
315 if (word & 1)
316 list[count++] = bitno;
317 word >>= 1;
318 }
319 }
7086e707
AD
320 else
321 {
322 for (bitno = bitoff; word; bitno++)
323 {
324 if (word & 1)
325 {
326 list[count++] = bitno;
327 if (count >= num)
328 {
329 *next = bitno + 1;
330 return count;
331 }
332 }
333 word >>= 1;
334 }
335 }
336 }
337
338 *next = bitoff;
339 return count;
340}
341
342
343/* Ensure that any unused bits within the last word are clear. */
344static inline void
613f5e1a 345abitset_unused_clear (dst)
7086e707
AD
346 bitset dst;
347{
348 unsigned int last_bit;
349
613f5e1a 350 last_bit = ABITSET_N_BITS (dst) % BITSET_WORD_BITS;
7086e707 351 if (last_bit)
613f5e1a 352 ABITSET_WORDS (dst)[dst->b.csize - 1] &=
d6eba423 353 ((bitset_word) 1 << last_bit) - 1;
7086e707
AD
354}
355
356
357static int
613f5e1a 358abitset_op1 (dst, op)
7086e707
AD
359 bitset dst;
360 enum bitset_ops op;
361{
362 unsigned int i;
613f5e1a 363 bitset_word *dstp = ABITSET_WORDS (dst);
7086e707
AD
364 unsigned int bytes;
365
ef017502 366 bytes = sizeof (bitset_word) * dst->b.csize;
7086e707
AD
367
368 switch (op)
369 {
ef017502 370 case BITSET_OP_ZERO:
7086e707
AD
371 memset (dstp, 0, bytes);
372 break;
373
ef017502 374 case BITSET_OP_ONES:
d6eba423 375 memset (dstp, -1, bytes);
613f5e1a 376 abitset_unused_clear (dst);
7086e707
AD
377 break;
378
ef017502
AD
379 case BITSET_OP_EMPTY_P:
380 for (i = 0; i < dst->b.csize; i++)
7086e707
AD
381 if (dstp[i])
382 return 0;
383 break;
384
385 default:
386 abort ();
387 }
388
389 return 1;
390}
391
392
393static int
613f5e1a 394abitset_op2 (dst, src, op)
7086e707
AD
395 bitset dst;
396 bitset src;
397 enum bitset_ops op;
398{
399 unsigned int i;
613f5e1a
AD
400 bitset_word *srcp = ABITSET_WORDS (src);
401 bitset_word *dstp = ABITSET_WORDS (dst);
ef017502 402 bitset_windex size = dst->b.csize;
7086e707 403
7086e707
AD
404 switch (op)
405 {
ef017502 406 case BITSET_OP_COPY:
7086e707
AD
407 if (srcp == dstp)
408 break;
409 memcpy (dstp, srcp, sizeof (bitset_word) * size);
410 break;
411
ef017502 412 case BITSET_OP_NOT:
7086e707
AD
413 for (i = 0; i < size; i++)
414 *dstp++ = ~(*srcp++);
613f5e1a 415 abitset_unused_clear (dst);
7086e707
AD
416 break;
417
ef017502 418 case BITSET_OP_EQUAL_P:
7086e707 419 for (i = 0; i < size; i++)
ef017502 420 if (*srcp++ != *dstp++)
7086e707
AD
421 return 0;
422 break;
ef017502
AD
423
424 case BITSET_OP_SUBSET_P:
7086e707 425 for (i = 0; i < size; i++, dstp++, srcp++)
ef017502
AD
426 if (*dstp != (*srcp | *dstp))
427 return 0;
7086e707 428 break;
ef017502
AD
429
430 case BITSET_OP_DISJOINT_P:
431 for (i = 0; i < size; i++)
432 if (*srcp++ & *dstp++)
433 return 0;
434 break;
435
7086e707
AD
436 default:
437 abort ();
438 }
439
440 return 1;
441}
442
443
444static int
613f5e1a 445abitset_op3 (dst, src1, src2, op)
7086e707
AD
446 bitset dst;
447 bitset src1;
448 bitset src2;
449 enum bitset_ops op;
450{
451 unsigned int i;
452 int changed = 0;
613f5e1a
AD
453 bitset_word *src1p = ABITSET_WORDS (src1);
454 bitset_word *src2p = ABITSET_WORDS (src2);
455 bitset_word *dstp = ABITSET_WORDS (dst);
ef017502 456 bitset_windex size = dst->b.csize;
7086e707 457
7086e707
AD
458 switch (op)
459 {
ef017502 460 case BITSET_OP_OR:
7086e707
AD
461 for (i = 0; i < size; i++, dstp++)
462 {
463 bitset_word tmp = *src1p++ | *src2p++;
464
465 if (*dstp != tmp)
466 {
467 changed = 1;
468 *dstp = tmp;
469 }
470 }
471 break;
472
ef017502 473 case BITSET_OP_AND:
7086e707
AD
474 for (i = 0; i < size; i++, dstp++)
475 {
476 bitset_word tmp = *src1p++ & *src2p++;
477
478 if (*dstp != tmp)
479 {
480 changed = 1;
481 *dstp = tmp;
482 }
483 }
484 break;
485
ef017502 486 case BITSET_OP_XOR:
7086e707
AD
487 for (i = 0; i < size; i++, dstp++)
488 {
489 bitset_word tmp = *src1p++ ^ *src2p++;
490
491 if (*dstp != tmp)
492 {
493 changed = 1;
494 *dstp = tmp;
495 }
496 }
497 break;
498
ef017502 499 case BITSET_OP_ANDN:
7086e707
AD
500 for (i = 0; i < size; i++, dstp++)
501 {
502 bitset_word tmp = *src1p++ & ~(*src2p++);
503
504 if (*dstp != tmp)
505 {
506 changed = 1;
507 *dstp = tmp;
508 }
509 }
510 break;
511
7086e707
AD
512 default:
513 abort ();
514 }
515
516 return changed;
517}
518
519
520static int
613f5e1a 521abitset_op4 (dst, src1, src2, src3, op)
7086e707
AD
522 bitset dst;
523 bitset src1;
524 bitset src2;
525 bitset src3;
526 enum bitset_ops op;
527{
528 unsigned int i;
529 int changed = 0;
613f5e1a
AD
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);
ef017502 534 bitset_windex size = dst->b.csize;
7086e707 535
7086e707
AD
536 switch (op)
537 {
ef017502 538 case BITSET_OP_OR_AND:
7086e707
AD
539 for (i = 0; i < size; i++, dstp++)
540 {
541 bitset_word tmp = (*src1p++ | *src2p++) & *src3p++;
542
543 if (*dstp != tmp)
544 {
545 changed = 1;
546 *dstp = tmp;
547 }
548 }
549 break;
550
ef017502 551 case BITSET_OP_AND_OR:
7086e707
AD
552 for (i = 0; i < size; i++, dstp++)
553 {
554 bitset_word tmp = (*src1p++ & *src2p++) | *src3p++;
555
556 if (*dstp != tmp)
557 {
558 changed = 1;
559 *dstp = tmp;
560 }
561 }
562 break;
563
ef017502 564 case BITSET_OP_ANDN_OR:
7086e707
AD
565 for (i = 0; i < size; i++, dstp++)
566 {
567 bitset_word tmp = (*src1p++ & ~(*src2p++)) | *src3p++;
568
569 if (*dstp != tmp)
570 {
571 changed = 1;
572 *dstp = tmp;
573 }
574 }
575 break;
576
577 default:
578 abort ();
579 }
580
581 return changed;
582}
583
584
585/* Vector of operations for single word bitsets. */
613f5e1a
AD
586struct bitset_ops_struct abitset_small_ops = {
587 abitset_set,
588 abitset_reset,
589 abitset_test,
590 abitset_size,
591 abitset_op1,
592 abitset_op2,
593 abitset_op3,
594 abitset_op4,
595 abitset_small_list,
596 abitset_reverse_list,
ef017502
AD
597 NULL,
598 BITSET_ARRAY
599};
7086e707
AD
600
601
602/* Vector of operations for multiple word bitsets. */
613f5e1a
AD
603struct bitset_ops_struct abitset_ops = {
604 abitset_set,
605 abitset_reset,
606 abitset_test,
607 abitset_size,
608 abitset_op1,
609 abitset_op2,
610 abitset_op3,
611 abitset_op4,
612 abitset_list,
613 abitset_reverse_list,
ef017502
AD
614 NULL,
615 BITSET_ARRAY
7086e707
AD
616};
617
618
619int
613f5e1a 620abitset_bytes (n_bits)
7086e707
AD
621 bitset_bindex n_bits;
622{
623 unsigned int bytes, size;
624
613f5e1a 625 size = ABITSET_N_WORDS (n_bits);
7086e707
AD
626 bytes = size * sizeof (bitset_word);
627 return sizeof (struct bitset_struct) + bytes - sizeof (bitset_word);
628}
629
630
631bitset
613f5e1a 632abitset_init (bset, n_bits)
7086e707
AD
633 bitset bset;
634 bitset_bindex n_bits;
635{
636 bitset_windex size;
637
613f5e1a
AD
638 size = ABITSET_N_WORDS (n_bits);
639 ABITSET_N_BITS (bset) = n_bits;
7086e707
AD
640
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. */
644 if (size == 1)
613f5e1a 645 bset->b.ops = &abitset_small_ops;
7086e707 646 else
613f5e1a 647 bset->b.ops = &abitset_ops;
7086e707 648
ef017502
AD
649 bset->b.cindex = 0;
650 bset->b.csize = size;
613f5e1a 651 bset->b.cdata = ABITSET_WORDS (bset);
7086e707
AD
652 return bset;
653}