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