1 /* Variable array bitsets.
2 
3    Copyright (C) 2002-2006, 2009-2015, 2018-2020 Free Software Foundation, Inc.
4 
5    Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
6 
7    This program is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
19 
20 #include <config.h>
21 
22 #include "bitset/vector.h"
23 
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "xalloc.h"
28 
29 /* This file implements variable size bitsets stored as a variable
30    length array of words.  Any unused bits in the last word must be
31    zero.
32 
33    Note that binary or ternary operations assume that each bitset operand
34    has the same size.
35 */
36 
37 static void vbitset_unused_clear (bitset);
38 
39 static void vbitset_set (bitset, bitset_bindex);
40 static void vbitset_reset (bitset, bitset_bindex);
41 static bool vbitset_test (bitset, bitset_bindex);
42 static bitset_bindex vbitset_list (bitset, bitset_bindex *,
43                                    bitset_bindex, bitset_bindex *);
44 static bitset_bindex vbitset_list_reverse (bitset, bitset_bindex *,
45                                            bitset_bindex, bitset_bindex *);
46 
47 #define VBITSET_N_WORDS(N) (((N) + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS)
48 #define VBITSET_WORDS(X) ((X)->b.cdata)
49 #define VBITSET_SIZE(X) ((X)->b.csize)
50 #define VBITSET_ASIZE(X) ((X)->v.size)
51 
52 #undef min
53 #undef max
54 #define min(a, b) ((a) > (b) ? (b) : (a))
55 #define max(a, b) ((a) > (b) ? (a) : (b))
56 
57 static bitset_bindex
vbitset_resize(bitset src,bitset_bindex n_bits)58 vbitset_resize (bitset src, bitset_bindex n_bits)
59 {
60   if (n_bits == BITSET_NBITS_ (src))
61     return n_bits;
62 
63   bitset_windex oldsize = VBITSET_SIZE (src);
64   bitset_windex newsize = VBITSET_N_WORDS (n_bits);
65 
66   if (oldsize < newsize)
67     {
68       /* The bitset needs to grow.  If we already have enough memory
69          allocated, then just zero what we need.  */
70       if (newsize > VBITSET_ASIZE (src))
71         {
72           /* We need to allocate more memory.  When oldsize is
73              non-zero this means that we are changing the size, so
74              grow the bitset 25% larger than requested to reduce
75              number of reallocations.  */
76 
77           bitset_windex size = oldsize == 0 ? newsize : newsize + newsize / 4;
78           VBITSET_WORDS (src)
79             = xrealloc (VBITSET_WORDS (src), size * sizeof (bitset_word));
80           VBITSET_ASIZE (src) = size;
81         }
82 
83       memset (VBITSET_WORDS (src) + oldsize, 0,
84               (newsize - oldsize) * sizeof (bitset_word));
85     }
86   else
87     {
88       /* The bitset needs to shrink.  There's no point deallocating
89          the memory unless it is shrinking by a reasonable amount.  */
90       if ((oldsize - newsize) >= oldsize / 2)
91         {
92           void *p
93             = realloc (VBITSET_WORDS (src), newsize * sizeof (bitset_word));
94           if (p)
95             {
96               VBITSET_WORDS (src) = p;
97               VBITSET_ASIZE (src) = newsize;
98             }
99         }
100 
101       /* Need to prune any excess bits.  FIXME.  */
102     }
103 
104   VBITSET_SIZE (src) = newsize;
105   BITSET_NBITS_ (src) = n_bits;
106   return n_bits;
107 }
108 
109 
110 /* Set bit BITNO in bitset DST.  */
111 static void
vbitset_set(bitset dst,bitset_bindex bitno)112 vbitset_set (bitset dst, bitset_bindex bitno)
113 {
114   bitset_windex windex = bitno / BITSET_WORD_BITS;
115 
116   /* Perhaps we should abort.  The user should explicitly call
117      bitset_resize since this will not catch the case when we set a
118      bit larger than the current size but smaller than the allocated
119      size.  */
120   vbitset_resize (dst, bitno);
121 
122   dst->b.cdata[windex - dst->b.cindex] |=
123     (bitset_word) 1 << (bitno % BITSET_WORD_BITS);
124 }
125 
126 
127 /* Reset bit BITNO in bitset DST.  */
128 static void
vbitset_reset(bitset dst MAYBE_UNUSED,bitset_bindex bitno MAYBE_UNUSED)129 vbitset_reset (bitset dst MAYBE_UNUSED, bitset_bindex bitno MAYBE_UNUSED)
130 {
131   /* We must be accessing outside the cache so the bit is
132      zero anyway.  */
133 }
134 
135 
136 /* Test bit BITNO in bitset SRC.  */
137 static bool
vbitset_test(bitset src MAYBE_UNUSED,bitset_bindex bitno MAYBE_UNUSED)138 vbitset_test (bitset src MAYBE_UNUSED,
139               bitset_bindex bitno MAYBE_UNUSED)
140 {
141   /* We must be accessing outside the cache so the bit is
142      zero anyway.  */
143   return false;
144 }
145 
146 
147 /* Find list of up to NUM bits set in BSET in reverse order, starting
148    from and including NEXT and store in array LIST.  Return with
149    actual number of bits found and with *NEXT indicating where search
150    stopped.  */
151 static bitset_bindex
vbitset_list_reverse(bitset src,bitset_bindex * list,bitset_bindex num,bitset_bindex * next)152 vbitset_list_reverse (bitset src, bitset_bindex *list,
153                       bitset_bindex num, bitset_bindex *next)
154 {
155   bitset_word *srcp = VBITSET_WORDS (src);
156   bitset_bindex n_bits = BITSET_SIZE_ (src);
157 
158   bitset_bindex rbitno = *next;
159 
160   /* If num is 1, we could speed things up with a binary search
161      of the word of interest.  */
162 
163   if (rbitno >= n_bits)
164     return 0;
165 
166   bitset_bindex count = 0;
167 
168   bitset_bindex bitno = n_bits - (rbitno + 1);
169 
170   bitset_windex windex = bitno / BITSET_WORD_BITS;
171   unsigned bitcnt = bitno % BITSET_WORD_BITS;
172   bitset_bindex bitoff = windex * BITSET_WORD_BITS;
173 
174   do
175     {
176       bitset_word word = srcp[windex] << (BITSET_WORD_BITS - 1 - bitcnt);
177       for (; word; bitcnt--)
178         {
179           if (word & BITSET_MSB)
180             {
181               list[count++] = bitoff + bitcnt;
182               if (count >= num)
183                 {
184                   *next = n_bits - (bitoff + bitcnt);
185                   return count;
186                 }
187             }
188           word <<= 1;
189         }
190       bitoff -= BITSET_WORD_BITS;
191       bitcnt = BITSET_WORD_BITS - 1;
192     }
193   while (windex--);
194 
195   *next = n_bits - (bitoff + 1);
196   return count;
197 }
198 
199 
200 /* Find list of up to NUM bits set in BSET starting from and including
201    *NEXT and store in array LIST.  Return with actual number of bits
202    found and with *NEXT indicating where search stopped.  */
203 static bitset_bindex
vbitset_list(bitset src,bitset_bindex * list,bitset_bindex num,bitset_bindex * next)204 vbitset_list (bitset src, bitset_bindex *list,
205               bitset_bindex num, bitset_bindex *next)
206 {
207   bitset_windex size = VBITSET_SIZE (src);
208   bitset_word *srcp = VBITSET_WORDS (src);
209   bitset_bindex bitno = *next;
210   bitset_bindex count = 0;
211 
212   bitset_windex windex;
213   bitset_bindex bitoff;
214   bitset_word word;
215 
216   if (!bitno)
217     {
218       /* Many bitsets are zero, so make this common case fast.  */
219       for (windex = 0; windex < size && !srcp[windex]; windex++)
220         continue;
221       if (windex >= size)
222         return 0;
223 
224       /* If num is 1, we could speed things up with a binary search
225          of the current word.  */
226 
227       bitoff = windex * BITSET_WORD_BITS;
228     }
229   else
230     {
231       if (bitno >= BITSET_SIZE_ (src))
232         return 0;
233 
234       windex = bitno / BITSET_WORD_BITS;
235       bitno = bitno % BITSET_WORD_BITS;
236 
237       if (bitno)
238         {
239           /* Handle the case where we start within a word.
240              Most often, this is executed with large bitsets
241              with many set bits where we filled the array
242              on the previous call to this function.  */
243 
244           bitoff = windex * BITSET_WORD_BITS;
245           word = srcp[windex] >> bitno;
246           for (bitno = bitoff + bitno; word; bitno++)
247             {
248               if (word & 1)
249                 {
250                   list[count++] = bitno;
251                   if (count >= num)
252                     {
253                       *next = bitno + 1;
254                       return count;
255                     }
256                 }
257               word >>= 1;
258             }
259           windex++;
260         }
261       bitoff = windex * BITSET_WORD_BITS;
262     }
263 
264   for (; windex < size; windex++, bitoff += BITSET_WORD_BITS)
265     {
266       if (!(word = srcp[windex]))
267         continue;
268 
269       if ((count + BITSET_WORD_BITS) < num)
270         {
271           for (bitno = bitoff; word; bitno++)
272             {
273               if (word & 1)
274                 list[count++] = bitno;
275               word >>= 1;
276             }
277         }
278       else
279         {
280           for (bitno = bitoff; word; bitno++)
281             {
282               if (word & 1)
283                 {
284                   list[count++] = bitno;
285                   if (count >= num)
286                     {
287                       *next = bitno + 1;
288                       return count;
289                     }
290                 }
291               word >>= 1;
292             }
293         }
294     }
295 
296   *next = bitoff;
297   return count;
298 }
299 
300 
301 /* Ensure that any unused bits within the last word are clear.  */
302 static inline void
vbitset_unused_clear(bitset dst)303 vbitset_unused_clear (bitset dst)
304 {
305   unsigned last_bit = BITSET_SIZE_ (dst) % BITSET_WORD_BITS;
306   if (last_bit)
307     VBITSET_WORDS (dst)[VBITSET_SIZE (dst) - 1] &=
308       ((bitset_word) 1 << last_bit) - 1;
309 }
310 
311 
312 static void
vbitset_ones(bitset dst)313 vbitset_ones (bitset dst)
314 {
315   bitset_word *dstp = VBITSET_WORDS (dst);
316   unsigned bytes = sizeof (bitset_word) * VBITSET_SIZE (dst);
317 
318   memset (dstp, -1, bytes);
319   vbitset_unused_clear (dst);
320 }
321 
322 
323 static void
vbitset_zero(bitset dst)324 vbitset_zero (bitset dst)
325 {
326   bitset_word *dstp = VBITSET_WORDS (dst);
327   unsigned bytes = sizeof (bitset_word) * VBITSET_SIZE (dst);
328 
329   memset (dstp, 0, bytes);
330 }
331 
332 
333 static bool
vbitset_empty_p(bitset dst)334 vbitset_empty_p (bitset dst)
335 {
336   bitset_word *dstp = VBITSET_WORDS (dst);
337 
338   for (unsigned i = 0; i < VBITSET_SIZE (dst); i++)
339     if (dstp[i])
340       return false;
341   return true;
342 }
343 
344 
345 static void
vbitset_copy1(bitset dst,bitset src)346 vbitset_copy1 (bitset dst, bitset src)
347 {
348   if (src == dst)
349     return;
350 
351   vbitset_resize (dst, BITSET_SIZE_ (src));
352 
353   bitset_word *srcp = VBITSET_WORDS (src);
354   bitset_word *dstp = VBITSET_WORDS (dst);
355   bitset_windex ssize = VBITSET_SIZE (src);
356   bitset_windex dsize = VBITSET_SIZE (dst);
357 
358   memcpy (dstp, srcp, sizeof (bitset_word) * ssize);
359 
360   memset (dstp + sizeof (bitset_word) * ssize, 0,
361           sizeof (bitset_word) * (dsize - ssize));
362 }
363 
364 
365 static void
vbitset_not(bitset dst,bitset src)366 vbitset_not (bitset dst, bitset src)
367 {
368   vbitset_resize (dst, BITSET_SIZE_ (src));
369 
370   bitset_word *srcp = VBITSET_WORDS (src);
371   bitset_word *dstp = VBITSET_WORDS (dst);
372   bitset_windex ssize = VBITSET_SIZE (src);
373   bitset_windex dsize = VBITSET_SIZE (dst);
374 
375   for (unsigned i = 0; i < ssize; i++)
376     *dstp++ = ~(*srcp++);
377 
378   vbitset_unused_clear (dst);
379   memset (dstp + sizeof (bitset_word) * ssize, 0,
380           sizeof (bitset_word) * (dsize - ssize));
381 }
382 
383 
384 static bool
vbitset_equal_p(bitset dst,bitset src)385 vbitset_equal_p (bitset dst, bitset src)
386 {
387   bitset_word *srcp = VBITSET_WORDS (src);
388   bitset_word *dstp = VBITSET_WORDS (dst);
389   bitset_windex ssize = VBITSET_SIZE (src);
390   bitset_windex dsize = VBITSET_SIZE (dst);
391 
392   unsigned i;
393   for (i = 0; i < min (ssize, dsize); i++)
394     if (*srcp++ != *dstp++)
395       return false;
396 
397   if (ssize > dsize)
398     {
399       for (; i < ssize; i++)
400         if (*srcp++)
401           return false;
402     }
403   else
404     {
405       for (; i < dsize; i++)
406         if (*dstp++)
407           return false;
408     }
409 
410   return true;
411 }
412 
413 
414 static bool
vbitset_subset_p(bitset dst,bitset src)415 vbitset_subset_p (bitset dst, bitset src)
416 {
417   bitset_word *srcp = VBITSET_WORDS (src);
418   bitset_word *dstp = VBITSET_WORDS (dst);
419   bitset_windex ssize = VBITSET_SIZE (src);
420   bitset_windex dsize = VBITSET_SIZE (dst);
421 
422   unsigned i;
423   for (i = 0; i < min (ssize, dsize); i++, dstp++, srcp++)
424     if (*dstp != (*srcp | *dstp))
425       return false;
426 
427   if (ssize > dsize)
428     for (; i < ssize; i++)
429       if (*srcp++)
430         return false;
431 
432   return true;
433 }
434 
435 
436 static bool
vbitset_disjoint_p(bitset dst,bitset src)437 vbitset_disjoint_p (bitset dst, bitset src)
438 {
439   bitset_word *srcp = VBITSET_WORDS (src);
440   bitset_word *dstp = VBITSET_WORDS (dst);
441   bitset_windex ssize = VBITSET_SIZE (src);
442   bitset_windex dsize = VBITSET_SIZE (dst);
443 
444   for (unsigned i = 0; i < min (ssize, dsize); i++)
445     if (*srcp++ & *dstp++)
446       return false;
447 
448   return true;
449 }
450 
451 
452 static void
vbitset_and(bitset dst,bitset src1,bitset src2)453 vbitset_and (bitset dst, bitset src1, bitset src2)
454 {
455   vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
456 
457   bitset_windex dsize = VBITSET_SIZE (dst);
458   bitset_windex ssize1 = VBITSET_SIZE (src1);
459   bitset_windex ssize2 = VBITSET_SIZE (src2);
460   bitset_word *dstp = VBITSET_WORDS (dst);
461   bitset_word *src1p = VBITSET_WORDS (src1);
462   bitset_word *src2p = VBITSET_WORDS (src2);
463 
464   for (unsigned i = 0; i < min (ssize1, ssize2); i++)
465     *dstp++ = *src1p++ & *src2p++;
466 
467   memset (dstp, 0, sizeof (bitset_word) * (dsize - min (ssize1, ssize2)));
468 }
469 
470 
471 static bool
vbitset_and_cmp(bitset dst,bitset src1,bitset src2)472 vbitset_and_cmp (bitset dst, bitset src1, bitset src2)
473 {
474   vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
475 
476   bitset_windex dsize = VBITSET_SIZE (dst);
477   bitset_windex ssize1 = VBITSET_SIZE (src1);
478   bitset_windex ssize2 = VBITSET_SIZE (src2);
479   bitset_word *dstp = VBITSET_WORDS (dst);
480   bitset_word *src1p = VBITSET_WORDS (src1);
481   bitset_word *src2p = VBITSET_WORDS (src2);
482 
483   bool changed = false;
484   unsigned i;
485   for (i = 0; i < min (ssize1, ssize2); i++, dstp++)
486     {
487       bitset_word tmp = *src1p++ & *src2p++;
488 
489       if (*dstp != tmp)
490         {
491           changed = true;
492           *dstp = tmp;
493         }
494     }
495 
496   if (ssize2 > ssize1)
497     {
498       src1p = src2p;
499       ssize1 = ssize2;
500     }
501 
502   for (; i < ssize1; i++, dstp++)
503     {
504       if (*dstp != 0)
505         {
506           changed = true;
507           *dstp = 0;
508         }
509     }
510 
511   memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
512 
513   return changed;
514 }
515 
516 
517 static void
vbitset_andn(bitset dst,bitset src1,bitset src2)518 vbitset_andn (bitset dst, bitset src1, bitset src2)
519 {
520   vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
521 
522   bitset_windex dsize = VBITSET_SIZE (dst);
523   bitset_windex ssize1 = VBITSET_SIZE (src1);
524   bitset_windex ssize2 = VBITSET_SIZE (src2);
525   bitset_word *dstp = VBITSET_WORDS (dst);
526   bitset_word *src1p = VBITSET_WORDS (src1);
527   bitset_word *src2p = VBITSET_WORDS (src2);
528 
529   unsigned i;
530   for (i = 0; i < min (ssize1, ssize2); i++)
531     *dstp++ = *src1p++ & ~(*src2p++);
532 
533   if (ssize2 > ssize1)
534     {
535       for (; i < ssize2; i++)
536         *dstp++ = 0;
537 
538       memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize2));
539     }
540   else
541     {
542       for (; i < ssize1; i++)
543         *dstp++ = *src1p++;
544 
545       memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
546     }
547 }
548 
549 
550 static bool
vbitset_andn_cmp(bitset dst,bitset src1,bitset src2)551 vbitset_andn_cmp (bitset dst, bitset src1, bitset src2)
552 {
553   vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
554 
555   bitset_windex dsize = VBITSET_SIZE (dst);
556   bitset_windex ssize1 = VBITSET_SIZE (src1);
557   bitset_windex ssize2 = VBITSET_SIZE (src2);
558   bitset_word *dstp = VBITSET_WORDS (dst);
559   bitset_word *src1p = VBITSET_WORDS (src1);
560   bitset_word *src2p = VBITSET_WORDS (src2);
561 
562   bool changed = false;
563   unsigned i;
564   for (i = 0; i < min (ssize1, ssize2); i++, dstp++)
565     {
566       bitset_word tmp = *src1p++ & ~(*src2p++);
567 
568       if (*dstp != tmp)
569         {
570           changed = true;
571           *dstp = tmp;
572         }
573     }
574 
575   if (ssize2 > ssize1)
576     {
577       for (; i < ssize2; i++, dstp++)
578         {
579           if (*dstp != 0)
580             {
581               changed = true;
582               *dstp = 0;
583             }
584         }
585 
586       memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize2));
587     }
588   else
589     {
590       for (; i < ssize1; i++, dstp++)
591         {
592           bitset_word tmp = *src1p++;
593 
594           if (*dstp != tmp)
595             {
596               changed = true;
597               *dstp = tmp;
598             }
599         }
600 
601       memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
602     }
603 
604   return changed;
605 }
606 
607 
608 static void
vbitset_or(bitset dst,bitset src1,bitset src2)609 vbitset_or (bitset dst, bitset src1, bitset src2)
610 {
611   vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
612 
613   bitset_windex dsize = VBITSET_SIZE (dst);
614   bitset_windex ssize1 = VBITSET_SIZE (src1);
615   bitset_windex ssize2 = VBITSET_SIZE (src2);
616   bitset_word *dstp = VBITSET_WORDS (dst);
617   bitset_word *src1p = VBITSET_WORDS (src1);
618   bitset_word *src2p = VBITSET_WORDS (src2);
619 
620   unsigned i;
621   for (i = 0; i < min (ssize1, ssize2); i++)
622     *dstp++ = *src1p++ | *src2p++;
623 
624   if (ssize2 > ssize1)
625     {
626       src1p = src2p;
627       ssize1 = ssize2;
628     }
629 
630   for (; i < ssize1; i++)
631     *dstp++ = *src1p++;
632 
633   memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
634 }
635 
636 
637 static bool
vbitset_or_cmp(bitset dst,bitset src1,bitset src2)638 vbitset_or_cmp (bitset dst, bitset src1, bitset src2)
639 {
640   vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
641 
642   bitset_windex dsize = VBITSET_SIZE (dst);
643   bitset_windex ssize1 = VBITSET_SIZE (src1);
644   bitset_windex ssize2 = VBITSET_SIZE (src2);
645   bitset_word *dstp = VBITSET_WORDS (dst);
646   bitset_word *src1p = VBITSET_WORDS (src1);
647   bitset_word *src2p = VBITSET_WORDS (src2);
648 
649   bool changed = false;
650   unsigned i;
651   for (i = 0; i < min (ssize1, ssize2); i++, dstp++)
652     {
653       bitset_word tmp = *src1p++ | *src2p++;
654 
655       if (*dstp != tmp)
656         {
657           changed = true;
658           *dstp = tmp;
659         }
660     }
661 
662   if (ssize2 > ssize1)
663     {
664       src1p = src2p;
665       ssize1 = ssize2;
666     }
667 
668   for (; i < ssize1; i++, dstp++)
669     {
670       bitset_word tmp = *src1p++;
671 
672       if (*dstp != tmp)
673         {
674           changed = true;
675           *dstp = tmp;
676         }
677     }
678 
679   memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
680 
681   return changed;
682 }
683 
684 
685 static void
vbitset_xor(bitset dst,bitset src1,bitset src2)686 vbitset_xor (bitset dst, bitset src1, bitset src2)
687 {
688   vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
689 
690   bitset_windex dsize = VBITSET_SIZE (dst);
691   bitset_windex ssize1 = VBITSET_SIZE (src1);
692   bitset_windex ssize2 = VBITSET_SIZE (src2);
693   bitset_word *dstp = VBITSET_WORDS (dst);
694   bitset_word *src1p = VBITSET_WORDS (src1);
695   bitset_word *src2p = VBITSET_WORDS (src2);
696 
697   unsigned i;
698   for (i = 0; i < min (ssize1, ssize2); i++)
699     *dstp++ = *src1p++ ^ *src2p++;
700 
701   if (ssize2 > ssize1)
702     {
703       src1p = src2p;
704       ssize1 = ssize2;
705     }
706 
707   for (; i < ssize1; i++)
708     *dstp++ = *src1p++;
709 
710   memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
711 }
712 
713 
714 static bool
vbitset_xor_cmp(bitset dst,bitset src1,bitset src2)715 vbitset_xor_cmp (bitset dst, bitset src1, bitset src2)
716 {
717   vbitset_resize (dst, max (BITSET_SIZE_ (src1), BITSET_SIZE_ (src2)));
718 
719   bitset_windex dsize = VBITSET_SIZE (dst);
720   bitset_windex ssize1 = VBITSET_SIZE (src1);
721   bitset_windex ssize2 = VBITSET_SIZE (src2);
722   bitset_word *dstp = VBITSET_WORDS (dst);
723   bitset_word *src1p = VBITSET_WORDS (src1);
724   bitset_word *src2p = VBITSET_WORDS (src2);
725 
726   bool changed = false;
727   unsigned i;
728   for (i = 0; i < min (ssize1, ssize2); i++, dstp++)
729     {
730       bitset_word tmp = *src1p++ ^ *src2p++;
731 
732       if (*dstp != tmp)
733         {
734           changed = true;
735           *dstp = tmp;
736         }
737     }
738 
739   if (ssize2 > ssize1)
740     {
741       src1p = src2p;
742       ssize1 = ssize2;
743     }
744 
745   for (; i < ssize1; i++, dstp++)
746     {
747       bitset_word tmp = *src1p++;
748 
749       if (*dstp != tmp)
750         {
751           changed = true;
752           *dstp = tmp;
753         }
754     }
755 
756   memset (dstp, 0, sizeof (bitset_word) * (dsize - ssize1));
757 
758   return changed;
759 }
760 
761 
762 /* FIXME, these operations need fixing for different size
763    bitsets.  */
764 
765 static void
vbitset_and_or(bitset dst,bitset src1,bitset src2,bitset src3)766 vbitset_and_or (bitset dst, bitset src1, bitset src2, bitset src3)
767 {
768   if (BITSET_NBITS_ (src1) != BITSET_NBITS_ (src2)
769       || BITSET_NBITS_ (src1) != BITSET_NBITS_ (src3))
770     {
771       bitset_and_or_ (dst, src1, src2, src3);
772       return;
773     }
774 
775   vbitset_resize (dst, BITSET_NBITS_ (src1));
776 
777   bitset_word *src1p = VBITSET_WORDS (src1);
778   bitset_word *src2p = VBITSET_WORDS (src2);
779   bitset_word *src3p = VBITSET_WORDS (src3);
780   bitset_word *dstp = VBITSET_WORDS (dst);
781   bitset_windex size = VBITSET_SIZE (dst);
782 
783   for (unsigned i = 0; i < size; i++)
784     *dstp++ = (*src1p++ & *src2p++) | *src3p++;
785 }
786 
787 
788 static bool
vbitset_and_or_cmp(bitset dst,bitset src1,bitset src2,bitset src3)789 vbitset_and_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
790 {
791   if (BITSET_NBITS_ (src1) != BITSET_NBITS_ (src2)
792       || BITSET_NBITS_ (src1) != BITSET_NBITS_ (src3))
793     return bitset_and_or_cmp_ (dst, src1, src2, src3);
794 
795   vbitset_resize (dst, BITSET_NBITS_ (src1));
796 
797   bitset_word *src1p = VBITSET_WORDS (src1);
798   bitset_word *src2p = VBITSET_WORDS (src2);
799   bitset_word *src3p = VBITSET_WORDS (src3);
800   bitset_word *dstp = VBITSET_WORDS (dst);
801   bitset_windex size = VBITSET_SIZE (dst);
802 
803   bool changed = false;
804   for (unsigned i = 0; i < size; i++, dstp++)
805     {
806       bitset_word tmp = (*src1p++ & *src2p++) | *src3p++;
807 
808       if (*dstp != tmp)
809         {
810           changed = true;
811           *dstp = tmp;
812         }
813     }
814   return changed;
815 }
816 
817 
818 static void
vbitset_andn_or(bitset dst,bitset src1,bitset src2,bitset src3)819 vbitset_andn_or (bitset dst, bitset src1, bitset src2, bitset src3)
820 {
821   if (BITSET_NBITS_ (src1) != BITSET_NBITS_ (src2)
822       || BITSET_NBITS_ (src1) != BITSET_NBITS_ (src3))
823     {
824       bitset_andn_or_ (dst, src1, src2, src3);
825       return;
826     }
827 
828   vbitset_resize (dst, BITSET_NBITS_ (src1));
829 
830   bitset_word *src1p = VBITSET_WORDS (src1);
831   bitset_word *src2p = VBITSET_WORDS (src2);
832   bitset_word *src3p = VBITSET_WORDS (src3);
833   bitset_word *dstp = VBITSET_WORDS (dst);
834   bitset_windex size = VBITSET_SIZE (dst);
835 
836   for (unsigned i = 0; i < size; i++)
837     *dstp++ = (*src1p++ & ~(*src2p++)) | *src3p++;
838 }
839 
840 
841 static bool
vbitset_andn_or_cmp(bitset dst,bitset src1,bitset src2,bitset src3)842 vbitset_andn_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
843 {
844   if (BITSET_NBITS_ (src1) != BITSET_NBITS_ (src2)
845       || BITSET_NBITS_ (src1) != BITSET_NBITS_ (src3))
846     return bitset_andn_or_cmp_ (dst, src1, src2, src3);
847 
848   vbitset_resize (dst, BITSET_NBITS_ (src1));
849 
850   bitset_word *src1p = VBITSET_WORDS (src1);
851   bitset_word *src2p = VBITSET_WORDS (src2);
852   bitset_word *src3p = VBITSET_WORDS (src3);
853   bitset_word *dstp = VBITSET_WORDS (dst);
854   bitset_windex size = VBITSET_SIZE (dst);
855 
856   bool changed = false;
857   for (unsigned i = 0; i < size; i++, dstp++)
858     {
859       bitset_word tmp = (*src1p++ & ~(*src2p++)) | *src3p++;
860 
861       if (*dstp != tmp)
862         {
863           changed = true;
864           *dstp = tmp;
865         }
866     }
867   return changed;
868 }
869 
870 
871 static void
vbitset_or_and(bitset dst,bitset src1,bitset src2,bitset src3)872 vbitset_or_and (bitset dst, bitset src1, bitset src2, bitset src3)
873 {
874   if (BITSET_NBITS_ (src1) != BITSET_NBITS_ (src2)
875       || BITSET_NBITS_ (src1) != BITSET_NBITS_ (src3))
876     {
877       bitset_or_and_ (dst, src1, src2, src3);
878       return;
879     }
880 
881   vbitset_resize (dst, BITSET_NBITS_ (src1));
882 
883   bitset_word *src1p = VBITSET_WORDS (src1);
884   bitset_word *src2p = VBITSET_WORDS (src2);
885   bitset_word *src3p = VBITSET_WORDS (src3);
886   bitset_word *dstp = VBITSET_WORDS (dst);
887   bitset_windex size = VBITSET_SIZE (dst);
888 
889   for (unsigned i = 0; i < size; i++)
890     *dstp++ = (*src1p++ | *src2p++) & *src3p++;
891 }
892 
893 
894 static bool
vbitset_or_and_cmp(bitset dst,bitset src1,bitset src2,bitset src3)895 vbitset_or_and_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
896 {
897   if (BITSET_NBITS_ (src1) != BITSET_NBITS_ (src2)
898       || BITSET_NBITS_ (src1) != BITSET_NBITS_ (src3))
899     return bitset_or_and_cmp_ (dst, src1, src2, src3);
900 
901   vbitset_resize (dst, BITSET_NBITS_ (src1));
902 
903   bitset_word *src1p = VBITSET_WORDS (src1);
904   bitset_word *src2p = VBITSET_WORDS (src2);
905   bitset_word *src3p = VBITSET_WORDS (src3);
906   bitset_word *dstp = VBITSET_WORDS (dst);
907   bitset_windex size = VBITSET_SIZE (dst);
908 
909   bool changed = false;
910   unsigned i;
911   for (i = 0; i < size; i++, dstp++)
912     {
913       bitset_word tmp = (*src1p++ | *src2p++) & *src3p++;
914 
915       if (*dstp != tmp)
916         {
917           changed = true;
918           *dstp = tmp;
919         }
920     }
921   return changed;
922 }
923 
924 
925 static void
vbitset_copy(bitset dst,bitset src)926 vbitset_copy (bitset dst, bitset src)
927 {
928   if (BITSET_COMPATIBLE_ (dst, src))
929     vbitset_copy1 (dst, src);
930   else
931     bitset_copy_ (dst, src);
932 }
933 
934 
935 static void
vbitset_free(bitset bset)936 vbitset_free (bitset bset)
937 {
938   free (VBITSET_WORDS (bset));
939 }
940 
941 
942 /* Vector of operations for multiple word bitsets.  */
943 struct bitset_vtable vbitset_vtable = {
944   vbitset_set,
945   vbitset_reset,
946   bitset_toggle_,
947   vbitset_test,
948   vbitset_resize,
949   bitset_size_,
950   bitset_count_,
951   vbitset_empty_p,
952   vbitset_ones,
953   vbitset_zero,
954   vbitset_copy,
955   vbitset_disjoint_p,
956   vbitset_equal_p,
957   vbitset_not,
958   vbitset_subset_p,
959   vbitset_and,
960   vbitset_and_cmp,
961   vbitset_andn,
962   vbitset_andn_cmp,
963   vbitset_or,
964   vbitset_or_cmp,
965   vbitset_xor,
966   vbitset_xor_cmp,
967   vbitset_and_or,
968   vbitset_and_or_cmp,
969   vbitset_andn_or,
970   vbitset_andn_or_cmp,
971   vbitset_or_and,
972   vbitset_or_and_cmp,
973   vbitset_list,
974   vbitset_list_reverse,
975   vbitset_free,
976   BITSET_VECTOR
977 };
978 
979 
980 size_t
vbitset_bytes(bitset_bindex n_bits MAYBE_UNUSED)981 vbitset_bytes (bitset_bindex n_bits MAYBE_UNUSED)
982 {
983   return sizeof (struct vbitset_struct);
984 }
985 
986 
987 bitset
vbitset_init(bitset bset,bitset_bindex n_bits)988 vbitset_init (bitset bset, bitset_bindex n_bits)
989 {
990   bset->b.vtable = &vbitset_vtable;
991   bset->b.cindex = 0;
992   VBITSET_SIZE (bset) = 0;
993   vbitset_resize (bset, n_bits);
994   return bset;
995 }
996