1 /* Array bitsets.
2
3 Copyright (C) 2002-2003, 2006, 2009-2015, 2018-2020 Free Software
4 Foundation, Inc.
5
6 Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <https://www.gnu.org/licenses/>. */
20
21 #include <config.h>
22
23 #include "bitset/array.h"
24 #include <stddef.h>
25 #include <stdlib.h>
26 #include <string.h>
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
31 #define ABITSET_N_WORDS(N) (((N) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
32 #define ABITSET_WORDS(X) ((X)->a.words)
33
34
35 static bitset_bindex
abitset_resize(bitset src,bitset_bindex size)36 abitset_resize (bitset src, bitset_bindex size)
37 {
38 /* These bitsets have a fixed size. */
39 if (BITSET_SIZE_ (src) != size)
40 abort ();
41
42 return size;
43 }
44
45 /* Find list of up to NUM bits set in BSET starting from and including
46 *NEXT and store in array LIST. Return with actual number of bits
47 found and with *NEXT indicating where search stopped. */
48 static bitset_bindex
abitset_small_list(bitset src,bitset_bindex * list,bitset_bindex num,bitset_bindex * next)49 abitset_small_list (bitset src, bitset_bindex *list,
50 bitset_bindex num, bitset_bindex *next)
51 {
52 bitset_word word = ABITSET_WORDS (src)[0];
53
54 /* Short circuit common case. */
55 if (!word)
56 return 0;
57
58 bitset_windex size = BITSET_SIZE_ (src);
59 bitset_bindex bitno = *next;
60 if (bitno >= size)
61 return 0;
62
63 word >>= bitno;
64
65 /* If num is 1, we could speed things up with a binary search
66 of the word of interest. */
67
68 bitset_bindex count;
69 if (num >= BITSET_WORD_BITS)
70 {
71 for (count = 0; word; bitno++)
72 {
73 if (word & 1)
74 list[count++] = bitno;
75 word >>= 1;
76 }
77 }
78 else
79 {
80 for (count = 0; word; bitno++)
81 {
82 if (word & 1)
83 {
84 list[count++] = bitno;
85 if (count >= num)
86 {
87 bitno++;
88 break;
89 }
90 }
91 word >>= 1;
92 }
93 }
94
95 *next = bitno;
96 return count;
97 }
98
99
100 /* Set bit BITNO in bitset DST. */
101 static void
abitset_set(bitset dst MAYBE_UNUSED,bitset_bindex bitno MAYBE_UNUSED)102 abitset_set (bitset dst MAYBE_UNUSED, bitset_bindex bitno MAYBE_UNUSED)
103 {
104 /* This should never occur for abitsets since we should always hit
105 the cache. It is likely someone is trying to access outside the
106 bounds of the bitset. */
107 abort ();
108 }
109
110
111 /* Reset bit BITNO in bitset DST. */
112 static void
abitset_reset(bitset dst MAYBE_UNUSED,bitset_bindex bitno MAYBE_UNUSED)113 abitset_reset (bitset dst MAYBE_UNUSED,
114 bitset_bindex bitno MAYBE_UNUSED)
115 {
116 /* This should never occur for abitsets since we should always hit
117 the cache. It is likely someone is trying to access outside the
118 bounds of the bitset. Since the bit is zero anyway, let it pass. */
119 }
120
121
122 /* Test bit BITNO in bitset SRC. */
123 static bool
abitset_test(bitset src MAYBE_UNUSED,bitset_bindex bitno MAYBE_UNUSED)124 abitset_test (bitset src MAYBE_UNUSED,
125 bitset_bindex bitno MAYBE_UNUSED)
126 {
127 /* This should never occur for abitsets since we should always
128 hit the cache. */
129 return false;
130 }
131
132
133 /* Find list of up to NUM bits set in BSET in reverse order, starting
134 from and including NEXT and store in array LIST. Return with
135 actual number of bits found and with *NEXT indicating where search
136 stopped. */
137 static bitset_bindex
abitset_list_reverse(bitset src,bitset_bindex * list,bitset_bindex num,bitset_bindex * next)138 abitset_list_reverse (bitset src, bitset_bindex *list,
139 bitset_bindex num, bitset_bindex *next)
140 {
141 bitset_bindex rbitno = *next;
142 bitset_word *srcp = ABITSET_WORDS (src);
143 bitset_bindex n_bits = BITSET_SIZE_ (src);
144
145 /* If num is 1, we could speed things up with a binary search
146 of the word of interest. */
147
148 if (rbitno >= n_bits)
149 return 0;
150
151 bitset_bindex count = 0;
152
153 bitset_bindex bitno = n_bits - (rbitno + 1);
154
155 bitset_windex windex = bitno / BITSET_WORD_BITS;
156 unsigned bitcnt = bitno % BITSET_WORD_BITS;
157 bitset_bindex bitoff = windex * BITSET_WORD_BITS;
158
159 do
160 {
161 bitset_word word = srcp[windex] << (BITSET_WORD_BITS - 1 - bitcnt);
162 for (; word; bitcnt--)
163 {
164 if (word & BITSET_MSB)
165 {
166 list[count++] = bitoff + bitcnt;
167 if (count >= num)
168 {
169 *next = n_bits - (bitoff + bitcnt);
170 return count;
171 }
172 }
173 word <<= 1;
174 }
175 bitoff -= BITSET_WORD_BITS;
176 bitcnt = BITSET_WORD_BITS - 1;
177 }
178 while (windex--);
179
180 *next = n_bits - (bitoff + 1);
181 return count;
182 }
183
184
185 /* Find list of up to NUM bits set in BSET starting from and including
186 *NEXT and store in array LIST. Return with actual number of bits
187 found and with *NEXT indicating where search stopped. */
188 static bitset_bindex
abitset_list(bitset src,bitset_bindex * list,bitset_bindex num,bitset_bindex * next)189 abitset_list (bitset src, bitset_bindex *list,
190 bitset_bindex num, bitset_bindex *next)
191 {
192 bitset_windex windex;
193 bitset_bindex bitoff;
194 bitset_windex size = src->b.csize;
195 bitset_word *srcp = ABITSET_WORDS (src);
196
197 bitset_bindex bitno = *next;
198
199 bitset_bindex count = 0;
200 if (!bitno)
201 {
202 /* Many bitsets are zero, so make this common case fast. */
203 for (windex = 0; windex < size && !srcp[windex]; windex++)
204 continue;
205 if (windex >= size)
206 return 0;
207
208 /* If num is 1, we could speed things up with a binary search
209 of the current word. */
210
211 bitoff = windex * BITSET_WORD_BITS;
212 }
213 else
214 {
215 if (bitno >= BITSET_SIZE_ (src))
216 return 0;
217
218 windex = bitno / BITSET_WORD_BITS;
219 bitno = bitno % BITSET_WORD_BITS;
220
221 if (bitno)
222 {
223 /* Handle the case where we start within a word.
224 Most often, this is executed with large bitsets
225 with many set bits where we filled the array
226 on the previous call to this function. */
227
228 bitoff = windex * BITSET_WORD_BITS;
229 bitset_word word = srcp[windex] >> bitno;
230 for (bitno = bitoff + bitno; word; bitno++)
231 {
232 if (word & 1)
233 {
234 list[count++] = bitno;
235 if (count >= num)
236 {
237 *next = bitno + 1;
238 return count;
239 }
240 }
241 word >>= 1;
242 }
243 windex++;
244 }
245 bitoff = windex * BITSET_WORD_BITS;
246 }
247
248 for (; windex < size; windex++, bitoff += BITSET_WORD_BITS)
249 {
250 bitset_word word = srcp[windex];
251 if (!word)
252 continue;
253
254 if ((count + BITSET_WORD_BITS) < num)
255 {
256 for (bitno = bitoff; word; bitno++)
257 {
258 if (word & 1)
259 list[count++] = bitno;
260 word >>= 1;
261 }
262 }
263 else
264 {
265 for (bitno = bitoff; word; bitno++)
266 {
267 if (word & 1)
268 {
269 list[count++] = bitno;
270 if (count >= num)
271 {
272 *next = bitno + 1;
273 return count;
274 }
275 }
276 word >>= 1;
277 }
278 }
279 }
280
281 *next = bitoff;
282 return count;
283 }
284
285
286 /* Ensure that any unused bits within the last word are clear. */
287 static inline void
abitset_unused_clear(bitset dst)288 abitset_unused_clear (bitset dst)
289 {
290 unsigned last_bit = BITSET_SIZE_ (dst) % BITSET_WORD_BITS;
291 if (last_bit)
292 ABITSET_WORDS (dst)[dst->b.csize - 1] &=
293 ((bitset_word) 1 << last_bit) - 1;
294 }
295
296
297 static void
abitset_ones(bitset dst)298 abitset_ones (bitset dst)
299 {
300 bitset_word *dstp = ABITSET_WORDS (dst);
301 size_t bytes = sizeof (bitset_word) * dst->b.csize;
302
303 memset (dstp, -1, bytes);
304 abitset_unused_clear (dst);
305 }
306
307
308 static void
abitset_zero(bitset dst)309 abitset_zero (bitset dst)
310 {
311 bitset_word *dstp = ABITSET_WORDS (dst);
312 size_t bytes = sizeof (bitset_word) * dst->b.csize;
313
314 memset (dstp, 0, bytes);
315 }
316
317
318 static bool
abitset_empty_p(bitset dst)319 abitset_empty_p (bitset dst)
320 {
321 bitset_word *dstp = ABITSET_WORDS (dst);
322
323 for (bitset_windex i = 0; i < dst->b.csize; i++)
324 if (dstp[i])
325 return false;
326 return true;
327 }
328
329
330 static void
abitset_copy1(bitset dst,bitset src)331 abitset_copy1 (bitset dst, bitset src)
332 {
333 bitset_word *srcp = ABITSET_WORDS (src);
334 bitset_word *dstp = ABITSET_WORDS (dst);
335 if (srcp == dstp)
336 return;
337 bitset_windex size = dst->b.csize;
338 memcpy (dstp, srcp, sizeof (bitset_word) * size);
339 }
340
341
342 static void
abitset_not(bitset dst,bitset src)343 abitset_not (bitset dst, bitset src)
344 {
345 bitset_word *srcp = ABITSET_WORDS (src);
346 bitset_word *dstp = ABITSET_WORDS (dst);
347 bitset_windex size = dst->b.csize;
348
349 for (bitset_windex i = 0; i < size; i++)
350 *dstp++ = ~(*srcp++);
351 abitset_unused_clear (dst);
352 }
353
354
355 static bool
abitset_equal_p(bitset dst,bitset src)356 abitset_equal_p (bitset dst, bitset src)
357 {
358 bitset_word *srcp = ABITSET_WORDS (src);
359 bitset_word *dstp = ABITSET_WORDS (dst);
360 bitset_windex size = dst->b.csize;
361
362 for (bitset_windex i = 0; i < size; i++)
363 if (*srcp++ != *dstp++)
364 return false;
365 return true;
366 }
367
368
369 static bool
abitset_subset_p(bitset dst,bitset src)370 abitset_subset_p (bitset dst, bitset src)
371 {
372 bitset_word *srcp = ABITSET_WORDS (src);
373 bitset_word *dstp = ABITSET_WORDS (dst);
374 bitset_windex size = dst->b.csize;
375
376 for (bitset_windex i = 0; i < size; i++, dstp++, srcp++)
377 if (*dstp != (*srcp | *dstp))
378 return false;
379 return true;
380 }
381
382
383 static bool
abitset_disjoint_p(bitset dst,bitset src)384 abitset_disjoint_p (bitset dst, bitset src)
385 {
386 bitset_word *srcp = ABITSET_WORDS (src);
387 bitset_word *dstp = ABITSET_WORDS (dst);
388 bitset_windex size = dst->b.csize;
389
390 for (bitset_windex i = 0; i < size; i++)
391 if (*srcp++ & *dstp++)
392 return false;
393 return true;
394 }
395
396
397 static void
abitset_and(bitset dst,bitset src1,bitset src2)398 abitset_and (bitset dst, bitset src1, bitset src2)
399 {
400 bitset_word *src1p = ABITSET_WORDS (src1);
401 bitset_word *src2p = ABITSET_WORDS (src2);
402 bitset_word *dstp = ABITSET_WORDS (dst);
403 bitset_windex size = dst->b.csize;
404
405 for (bitset_windex i = 0; i < size; i++)
406 *dstp++ = *src1p++ & *src2p++;
407 }
408
409
410 static bool
abitset_and_cmp(bitset dst,bitset src1,bitset src2)411 abitset_and_cmp (bitset dst, bitset src1, bitset src2)
412 {
413 bool changed = false;
414 bitset_word *src1p = ABITSET_WORDS (src1);
415 bitset_word *src2p = ABITSET_WORDS (src2);
416 bitset_word *dstp = ABITSET_WORDS (dst);
417 bitset_windex size = dst->b.csize;
418
419 for (bitset_windex i = 0; i < size; i++, dstp++)
420 {
421 bitset_word tmp = *src1p++ & *src2p++;
422 if (*dstp != tmp)
423 {
424 changed = true;
425 *dstp = tmp;
426 }
427 }
428 return changed;
429 }
430
431
432 static void
abitset_andn(bitset dst,bitset src1,bitset src2)433 abitset_andn (bitset dst, bitset src1, bitset src2)
434 {
435 bitset_word *src1p = ABITSET_WORDS (src1);
436 bitset_word *src2p = ABITSET_WORDS (src2);
437 bitset_word *dstp = ABITSET_WORDS (dst);
438 bitset_windex size = dst->b.csize;
439
440 for (bitset_windex i = 0; i < size; i++)
441 *dstp++ = *src1p++ & ~(*src2p++);
442 }
443
444
445 static bool
abitset_andn_cmp(bitset dst,bitset src1,bitset src2)446 abitset_andn_cmp (bitset dst, bitset src1, bitset src2)
447 {
448 bool changed = false;
449 bitset_word *src1p = ABITSET_WORDS (src1);
450 bitset_word *src2p = ABITSET_WORDS (src2);
451 bitset_word *dstp = ABITSET_WORDS (dst);
452 bitset_windex size = dst->b.csize;
453
454 for (bitset_windex i = 0; i < size; i++, dstp++)
455 {
456 bitset_word tmp = *src1p++ & ~(*src2p++);
457 if (*dstp != tmp)
458 {
459 changed = true;
460 *dstp = tmp;
461 }
462 }
463 return changed;
464 }
465
466
467 static void
abitset_or(bitset dst,bitset src1,bitset src2)468 abitset_or (bitset dst, bitset src1, bitset src2)
469 {
470 bitset_word *src1p = ABITSET_WORDS (src1);
471 bitset_word *src2p = ABITSET_WORDS (src2);
472 bitset_word *dstp = ABITSET_WORDS (dst);
473 bitset_windex size = dst->b.csize;
474
475 for (bitset_windex i = 0; i < size; i++)
476 *dstp++ = *src1p++ | *src2p++;
477 }
478
479
480 static bool
abitset_or_cmp(bitset dst,bitset src1,bitset src2)481 abitset_or_cmp (bitset dst, bitset src1, bitset src2)
482 {
483 bool changed = false;
484 bitset_word *src1p = ABITSET_WORDS (src1);
485 bitset_word *src2p = ABITSET_WORDS (src2);
486 bitset_word *dstp = ABITSET_WORDS (dst);
487 bitset_windex size = dst->b.csize;
488
489 for (bitset_windex i = 0; i < size; i++, dstp++)
490 {
491 bitset_word tmp = *src1p++ | *src2p++;
492
493 if (*dstp != tmp)
494 {
495 changed = true;
496 *dstp = tmp;
497 }
498 }
499 return changed;
500 }
501
502
503 static void
abitset_xor(bitset dst,bitset src1,bitset src2)504 abitset_xor (bitset dst, bitset src1, bitset src2)
505 {
506 bitset_word *src1p = ABITSET_WORDS (src1);
507 bitset_word *src2p = ABITSET_WORDS (src2);
508 bitset_word *dstp = ABITSET_WORDS (dst);
509 bitset_windex size = dst->b.csize;
510
511 for (bitset_windex i = 0; i < size; i++)
512 *dstp++ = *src1p++ ^ *src2p++;
513 }
514
515
516 static bool
abitset_xor_cmp(bitset dst,bitset src1,bitset src2)517 abitset_xor_cmp (bitset dst, bitset src1, bitset src2)
518 {
519 bool changed = false;
520 bitset_word *src1p = ABITSET_WORDS (src1);
521 bitset_word *src2p = ABITSET_WORDS (src2);
522 bitset_word *dstp = ABITSET_WORDS (dst);
523 bitset_windex size = dst->b.csize;
524
525 for (bitset_windex i = 0; i < size; i++, dstp++)
526 {
527 bitset_word tmp = *src1p++ ^ *src2p++;
528
529 if (*dstp != tmp)
530 {
531 changed = true;
532 *dstp = tmp;
533 }
534 }
535 return changed;
536 }
537
538
539 static void
abitset_and_or(bitset dst,bitset src1,bitset src2,bitset src3)540 abitset_and_or (bitset dst, bitset src1, bitset src2, bitset src3)
541 {
542 bitset_word *src1p = ABITSET_WORDS (src1);
543 bitset_word *src2p = ABITSET_WORDS (src2);
544 bitset_word *src3p = ABITSET_WORDS (src3);
545 bitset_word *dstp = ABITSET_WORDS (dst);
546 bitset_windex size = dst->b.csize;
547
548 for (bitset_windex i = 0; i < size; i++)
549 *dstp++ = (*src1p++ & *src2p++) | *src3p++;
550 }
551
552
553 static bool
abitset_and_or_cmp(bitset dst,bitset src1,bitset src2,bitset src3)554 abitset_and_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
555 {
556 bool changed = false;
557 bitset_word *src1p = ABITSET_WORDS (src1);
558 bitset_word *src2p = ABITSET_WORDS (src2);
559 bitset_word *src3p = ABITSET_WORDS (src3);
560 bitset_word *dstp = ABITSET_WORDS (dst);
561 bitset_windex size = dst->b.csize;
562
563 for (bitset_windex i = 0; i < size; i++, dstp++)
564 {
565 bitset_word tmp = (*src1p++ & *src2p++) | *src3p++;
566 if (*dstp != tmp)
567 {
568 changed = true;
569 *dstp = tmp;
570 }
571 }
572 return changed;
573 }
574
575
576 static void
abitset_andn_or(bitset dst,bitset src1,bitset src2,bitset src3)577 abitset_andn_or (bitset dst, bitset src1, bitset src2, bitset src3)
578 {
579 bitset_word *src1p = ABITSET_WORDS (src1);
580 bitset_word *src2p = ABITSET_WORDS (src2);
581 bitset_word *src3p = ABITSET_WORDS (src3);
582 bitset_word *dstp = ABITSET_WORDS (dst);
583 bitset_windex size = dst->b.csize;
584
585 for (bitset_windex i = 0; i < size; i++)
586 *dstp++ = (*src1p++ & ~(*src2p++)) | *src3p++;
587 }
588
589
590 static bool
abitset_andn_or_cmp(bitset dst,bitset src1,bitset src2,bitset src3)591 abitset_andn_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
592 {
593 bool changed = false;
594 bitset_word *src1p = ABITSET_WORDS (src1);
595 bitset_word *src2p = ABITSET_WORDS (src2);
596 bitset_word *src3p = ABITSET_WORDS (src3);
597 bitset_word *dstp = ABITSET_WORDS (dst);
598 bitset_windex size = dst->b.csize;
599
600 for (bitset_windex i = 0; i < size; i++, dstp++)
601 {
602 bitset_word tmp = (*src1p++ & ~(*src2p++)) | *src3p++;
603 if (*dstp != tmp)
604 {
605 changed = true;
606 *dstp = tmp;
607 }
608 }
609 return changed;
610 }
611
612
613 static void
abitset_or_and(bitset dst,bitset src1,bitset src2,bitset src3)614 abitset_or_and (bitset dst, bitset src1, bitset src2, bitset src3)
615 {
616 bitset_word *src1p = ABITSET_WORDS (src1);
617 bitset_word *src2p = ABITSET_WORDS (src2);
618 bitset_word *src3p = ABITSET_WORDS (src3);
619 bitset_word *dstp = ABITSET_WORDS (dst);
620 bitset_windex size = dst->b.csize;
621
622 for (bitset_windex i = 0; i < size; i++)
623 *dstp++ = (*src1p++ | *src2p++) & *src3p++;
624 }
625
626
627 static bool
abitset_or_and_cmp(bitset dst,bitset src1,bitset src2,bitset src3)628 abitset_or_and_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
629 {
630 bool changed = false;
631 bitset_word *src1p = ABITSET_WORDS (src1);
632 bitset_word *src2p = ABITSET_WORDS (src2);
633 bitset_word *src3p = ABITSET_WORDS (src3);
634 bitset_word *dstp = ABITSET_WORDS (dst);
635 bitset_windex size = dst->b.csize;
636
637 for (bitset_windex i = 0; i < size; i++, dstp++)
638 {
639 bitset_word tmp = (*src1p++ | *src2p++) & *src3p++;
640 if (*dstp != tmp)
641 {
642 changed = true;
643 *dstp = tmp;
644 }
645 }
646 return changed;
647 }
648
649
650 static void
abitset_copy(bitset dst,bitset src)651 abitset_copy (bitset dst, bitset src)
652 {
653 if (BITSET_COMPATIBLE_ (dst, src))
654 abitset_copy1 (dst, src);
655 else
656 bitset_copy_ (dst, src);
657 }
658
659
660 /* Vector of operations for single word bitsets. */
661 struct bitset_vtable abitset_small_vtable = {
662 abitset_set,
663 abitset_reset,
664 bitset_toggle_,
665 abitset_test,
666 abitset_resize,
667 bitset_size_,
668 bitset_count_,
669 abitset_empty_p,
670 abitset_ones,
671 abitset_zero,
672 abitset_copy,
673 abitset_disjoint_p,
674 abitset_equal_p,
675 abitset_not,
676 abitset_subset_p,
677 abitset_and,
678 abitset_and_cmp,
679 abitset_andn,
680 abitset_andn_cmp,
681 abitset_or,
682 abitset_or_cmp,
683 abitset_xor,
684 abitset_xor_cmp,
685 abitset_and_or,
686 abitset_and_or_cmp,
687 abitset_andn_or,
688 abitset_andn_or_cmp,
689 abitset_or_and,
690 abitset_or_and_cmp,
691 abitset_small_list,
692 abitset_list_reverse,
693 NULL,
694 BITSET_ARRAY
695 };
696
697
698 /* Vector of operations for multiple word bitsets. */
699 struct bitset_vtable abitset_vtable = {
700 abitset_set,
701 abitset_reset,
702 bitset_toggle_,
703 abitset_test,
704 abitset_resize,
705 bitset_size_,
706 bitset_count_,
707 abitset_empty_p,
708 abitset_ones,
709 abitset_zero,
710 abitset_copy,
711 abitset_disjoint_p,
712 abitset_equal_p,
713 abitset_not,
714 abitset_subset_p,
715 abitset_and,
716 abitset_and_cmp,
717 abitset_andn,
718 abitset_andn_cmp,
719 abitset_or,
720 abitset_or_cmp,
721 abitset_xor,
722 abitset_xor_cmp,
723 abitset_and_or,
724 abitset_and_or_cmp,
725 abitset_andn_or,
726 abitset_andn_or_cmp,
727 abitset_or_and,
728 abitset_or_and_cmp,
729 abitset_list,
730 abitset_list_reverse,
731 NULL,
732 BITSET_ARRAY
733 };
734
735
736 size_t
abitset_bytes(bitset_bindex n_bits)737 abitset_bytes (bitset_bindex n_bits)
738 {
739 size_t header_size = offsetof (union bitset_union, a.words);
740 struct bitset_align_struct { char a; union bitset_union b; };
741 size_t bitset_alignment = offsetof (struct bitset_align_struct, b);
742
743 bitset_windex size = ABITSET_N_WORDS (n_bits);
744 size_t bytes = header_size + size * sizeof (bitset_word);
745
746 /* Align the size properly for a vector of abitset objects. */
747 if (header_size % bitset_alignment != 0
748 || sizeof (bitset_word) % bitset_alignment != 0)
749 {
750 bytes += bitset_alignment - 1;
751 bytes -= bytes % bitset_alignment;
752 }
753
754 return bytes;
755 }
756
757
758 bitset
abitset_init(bitset bset,bitset_bindex n_bits)759 abitset_init (bitset bset, bitset_bindex n_bits)
760 {
761 bitset_windex size = ABITSET_N_WORDS (n_bits);
762 BITSET_NBITS_ (bset) = n_bits;
763
764 /* Use optimized routines if bitset fits within a single word.
765 There is probably little merit if using caching since
766 the small bitset will always fit in the cache. */
767 bset->b.vtable = size == 1 ? &abitset_small_vtable : &abitset_vtable;
768 bset->b.cindex = 0;
769 bset->b.csize = size;
770 bset->b.cdata = ABITSET_WORDS (bset);
771 return bset;
772 }
773