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