PostgreSQL Source Code git master
Loading...
Searching...
No Matches
bitmapset.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * bitmapset.c
4 * PostgreSQL generic bitmap set package
5 *
6 * A bitmap set can represent any set of nonnegative integers, although
7 * it is mainly intended for sets where the maximum value is not large,
8 * say at most a few hundred. By convention, we always represent a set with
9 * the minimum possible number of words, i.e, there are never any trailing
10 * zero words. Enforcing this requires that an empty set is represented as
11 * NULL. Because an empty Bitmapset is represented as NULL, a non-NULL
12 * Bitmapset always has at least 1 Bitmapword. We can exploit this fact to
13 * speed up various loops over the Bitmapset's words array by using "do while"
14 * loops instead of "for" loops. This means the code does not waste time
15 * checking the loop condition before the first iteration. For Bitmapsets
16 * containing only a single word (likely the majority of them) this halves the
17 * number of loop condition checks.
18 *
19 * Callers must ensure that the set returned by functions in this file which
20 * adjust the members of an existing set is assigned to all pointers pointing
21 * to that existing set. No guarantees are made that we'll ever modify the
22 * existing set in-place and return it.
23 *
24 * To help find bugs caused by callers failing to record the return value of
25 * the function which manipulates an existing set, we support building with
26 * REALLOCATE_BITMAPSETS. This results in the set being reallocated each time
27 * the set is altered and the existing being pfreed. This is useful as if any
28 * references still exist to the old set, we're more likely to notice as
29 * any users of the old set will be accessing pfree'd memory. This option is
30 * only intended to be used for debugging.
31 *
32 * Copyright (c) 2003-2026, PostgreSQL Global Development Group
33 *
34 * IDENTIFICATION
35 * src/backend/nodes/bitmapset.c
36 *
37 *-------------------------------------------------------------------------
38 */
39#include "postgres.h"
40
41#include "common/hashfn.h"
42#include "common/int.h"
43#include "nodes/bitmapset.h"
44#include "nodes/pg_list.h"
45#include "port/pg_bitutils.h"
46
47
48#define WORDNUM(x) ((x) / BITS_PER_BITMAPWORD)
49#define BITNUM(x) ((x) % BITS_PER_BITMAPWORD)
50
51#define BITMAPSET_SIZE(nwords) \
52 (offsetof(Bitmapset, words) + (nwords) * sizeof(bitmapword))
53
54/*----------
55 * This is a well-known cute trick for isolating the rightmost one-bit
56 * in a word. It assumes two's complement arithmetic. Consider any
57 * nonzero value, and focus attention on the rightmost one. The value is
58 * then something like
59 * xxxxxx10000
60 * where x's are unspecified bits. The two's complement negative is formed
61 * by inverting all the bits and adding one. Inversion gives
62 * yyyyyy01111
63 * where each y is the inverse of the corresponding x. Incrementing gives
64 * yyyyyy10000
65 * and then ANDing with the original value gives
66 * 00000010000
67 * This works for all cases except original value = zero, where of course
68 * we get zero.
69 *----------
70 */
71#define RIGHTMOST_ONE(x) ((signedbitmapword) (x) & -((signedbitmapword) (x)))
72
73#define HAS_MULTIPLE_ONES(x) ((bitmapword) RIGHTMOST_ONE(x) != (x))
74
75#ifdef USE_ASSERT_CHECKING
76/*
77 * bms_is_valid_set - for cassert builds to check for valid sets
78 */
79static bool
81{
82 /* NULL is the correct representation of an empty set */
83 if (a == NULL)
84 return true;
85
86 /* check the node tag is set correctly. pfree'd pointer, maybe? */
87 if (!IsA(a, Bitmapset))
88 return false;
89
90 /* trailing zero words are not allowed */
91 if (a->words[a->nwords - 1] == 0)
92 return false;
93
94 return true;
95}
96#endif
97
98#ifdef REALLOCATE_BITMAPSETS
99/*
100 * bms_copy_and_free
101 * Only required in REALLOCATE_BITMAPSETS builds. Provide a simple way
102 * to return a freshly allocated set and pfree the original.
103 *
104 * Note: callers which accept multiple sets must be careful when calling this
105 * function to clone one parameter as other parameters may point to the same
106 * set. A good option is to call this just before returning the resulting
107 * set.
108 */
109static Bitmapset *
111{
112 Bitmapset *c = bms_copy(a);
113
114 bms_free(a);
115 return c;
116}
117#endif
118
119/*
120 * bms_copy - make a palloc'd copy of a bitmapset
121 */
122Bitmapset *
124{
126 size_t size;
127
129
130 if (a == NULL)
131 return NULL;
132
133 size = BITMAPSET_SIZE(a->nwords);
134 result = (Bitmapset *) palloc(size);
135 memcpy(result, a, size);
136 return result;
137}
138
139/*
140 * bms_equal - are two bitmapsets equal? or both NULL?
141 */
142bool
144{
145 int i;
146
149
150 /* Handle cases where either input is NULL */
151 if (a == NULL)
152 {
153 if (b == NULL)
154 return true;
155 return false;
156 }
157 else if (b == NULL)
158 return false;
159
160 /* can't be equal if the word counts don't match */
161 if (a->nwords != b->nwords)
162 return false;
163
164 /* check each word matches */
165 i = 0;
166 do
167 {
168 if (a->words[i] != b->words[i])
169 return false;
170 } while (++i < a->nwords);
171
172 return true;
173}
174
175/*
176 * bms_compare - qsort-style comparator for bitmapsets
177 *
178 * This guarantees to report values as equal iff bms_equal would say they are
179 * equal. Otherwise, the highest-numbered bit that is set in one value but
180 * not the other determines the result. (This rule means that, for example,
181 * {6} is greater than {5}, which seems plausible.)
182 */
183int
185{
186 int i;
187
190
191 /* Handle cases where either input is NULL */
192 if (a == NULL)
193 return (b == NULL) ? 0 : -1;
194 else if (b == NULL)
195 return +1;
196
197 /* the set with the most words must be greater */
198 if (a->nwords != b->nwords)
199 return (a->nwords > b->nwords) ? +1 : -1;
200
201 i = a->nwords - 1;
202 do
203 {
204 bitmapword aw = a->words[i];
205 bitmapword bw = b->words[i];
206
207 if (aw != bw)
208 return (aw > bw) ? +1 : -1;
209 } while (--i >= 0);
210 return 0;
211}
212
213/*
214 * bms_make_singleton - build a bitmapset containing a single member
215 */
216Bitmapset *
218{
220 int wordnum,
221 bitnum;
222
223 if (x < 0)
224 elog(ERROR, "negative bitmapset member not allowed");
225 wordnum = WORDNUM(x);
226 bitnum = BITNUM(x);
228 result->type = T_Bitmapset;
229 result->nwords = wordnum + 1;
230 result->words[wordnum] = ((bitmapword) 1 << bitnum);
231 return result;
232}
233
234/*
235 * bms_free - free a bitmapset
236 *
237 * Same as pfree except for allowing NULL input
238 */
239void
241{
242 if (a)
243 pfree(a);
244}
245
246
247/*
248 * bms_union - create and return a new set containing all members from both
249 * input sets. Both inputs are left unmodified.
250 */
251Bitmapset *
253{
255 const Bitmapset *other;
256 int otherlen;
257 int i;
258
261
262 /* Handle cases where either input is NULL */
263 if (a == NULL)
264 return bms_copy(b);
265 if (b == NULL)
266 return bms_copy(a);
267 /* Identify shorter and longer input; copy the longer one */
268 if (a->nwords <= b->nwords)
269 {
270 result = bms_copy(b);
271 other = a;
272 }
273 else
274 {
275 result = bms_copy(a);
276 other = b;
277 }
278 /* And union the shorter input into the result */
279 otherlen = other->nwords;
280 i = 0;
281 do
282 {
283 result->words[i] |= other->words[i];
284 } while (++i < otherlen);
285 return result;
286}
287
288/*
289 * bms_intersect - create and return a new set containing members which both
290 * input sets have in common. Both inputs are left unmodified.
291 */
292Bitmapset *
294{
296 const Bitmapset *other;
297 int lastnonzero;
298 int resultlen;
299 int i;
300
303
304 /* Handle cases where either input is NULL */
305 if (a == NULL || b == NULL)
306 return NULL;
307
308 /* Identify shorter and longer input; copy the shorter one */
309 if (a->nwords <= b->nwords)
310 {
311 result = bms_copy(a);
312 other = b;
313 }
314 else
315 {
316 result = bms_copy(b);
317 other = a;
318 }
319 /* And intersect the longer input with the result */
320 resultlen = result->nwords;
321 lastnonzero = -1;
322 i = 0;
323 do
324 {
325 result->words[i] &= other->words[i];
326
327 if (result->words[i] != 0)
328 lastnonzero = i;
329 } while (++i < resultlen);
330 /* If we computed an empty result, we must return NULL */
331 if (lastnonzero == -1)
332 {
333 pfree(result);
334 return NULL;
335 }
336
337 /* get rid of trailing zero words */
338 result->nwords = lastnonzero + 1;
339 return result;
340}
341
342/*
343 * bms_difference - create and return a new set containing all the members of
344 * 'a' without the members of 'b'.
345 */
346Bitmapset *
348{
350 int i;
351
354
355 /* Handle cases where either input is NULL */
356 if (a == NULL)
357 return NULL;
358 if (b == NULL)
359 return bms_copy(a);
360
361 /*
362 * In Postgres' usage, an empty result is a very common case, so it's
363 * worth optimizing for that by testing bms_nonempty_difference(). This
364 * saves us a palloc/pfree cycle compared to checking after-the-fact.
365 */
367 return NULL;
368
369 /* Copy the left input */
370 result = bms_copy(a);
371
372 /* And remove b's bits from result */
373 if (result->nwords > b->nwords)
374 {
375 /*
376 * We'll never need to remove trailing zero words when 'a' has more
377 * words than 'b' as the additional words must be non-zero.
378 */
379 i = 0;
380 do
381 {
382 result->words[i] &= ~b->words[i];
383 } while (++i < b->nwords);
384 }
385 else
386 {
387 int lastnonzero = -1;
388
389 /* we may need to remove trailing zero words from the result. */
390 i = 0;
391 do
392 {
393 result->words[i] &= ~b->words[i];
394
395 /* remember the last non-zero word */
396 if (result->words[i] != 0)
397 lastnonzero = i;
398 } while (++i < result->nwords);
399
400 /* trim off trailing zero words */
401 result->nwords = lastnonzero + 1;
402 }
403 Assert(result->nwords != 0);
404
405 /* Need not check for empty result, since we handled that case above */
406 return result;
407}
408
409/*
410 * bms_offset_members
411 * Creates a new Bitmapset with all members of 'a' adjusted to add the
412 * value of 'offset' to each member.
413 *
414 * Members that would become negative as a result of a negative offset will
415 * be removed from the set, whereas too large an offset, which would result in
416 * a member going > INT_MAX, will result in an ERROR.
417 */
418Bitmapset *
419bms_offset_members(const Bitmapset *a, int offset)
420{
422 int offset_words;
423 int offset_bits;
424 int new_nwords;
425 int old_nwords;
427 int old_highest;
428 int new_highest;
429
431
432 /* nothing to do for empty sets */
433 if (a == NULL)
434 return NULL;
435
436 old_nwords = a->nwords;
437 offset_words = WORDNUM(offset);
438 offset_bits = BITNUM(offset);
439 high_bit = bmw_leftmost_one_pos(a->words[a->nwords - 1]);
441
442 /* don't create a set with a member that doesn't fit into an int32 */
444 elog(ERROR, "bitmapset overflow");
445 /* return NULL if the new set would be empty */
446 else if (new_highest < 0)
447 return NULL;
448
451 result->type = T_Bitmapset;
452 result->nwords = new_nwords;
453
454 /* handle zero and positive offsets (bitshift left) */
455 if (offset >= 0)
456 {
457 /*
458 * We special-case offsetting only by whole words, so we don't have to
459 * special-case bitshifting by BITS_PER_BITMAPWORD places, which has
460 * an undefined behavior.
461 */
462 if (offset_bits == 0)
463 {
464 int i = 0;
465
466 /*
467 * The old set is guaranteed to have at least 1 word, so use
468 * do/while to save the redundant initial loop bounds check.
469 */
470 do
471 {
473 result->words[i + offset_words] = a->words[i];
474 } while (++i < old_nwords);
475 }
476 else
477 {
480 int i = 0;
481
482 do
483 {
484 bitmapword carry = (a->words[i] >> carry_bits);
485
487 /* shift bits up and carry bits from the previous word */
488 result->words[i + offset_words] = (a->words[i] << offset_bits) | prev_carry;
490 } while (++i < old_nwords);
491 result->words[new_nwords - 1] |= prev_carry;
492 }
493 }
494
495 /* handle negative offset (bitshift right) */
496 else
497 {
498 /* make the negative offset_words and offset_bits positive */
501
502 /* as above, special case shifting only by whole words */
503 if (offset_bits == 0)
504 {
505 int i = 0;
506
507 do
508 {
510 result->words[i] = a->words[i + offset_words];
511 } while (++i < new_nwords);
512 }
513 else
514 {
517 int i = new_nwords - 1;
518
519 /* carry bits from any word just above where the loop starts */
522
523 /*
524 * We loop backward over the array so we correctly carry bits from
525 * higher words.
526 */
527 do
528 {
529 bitmapword carry = (a->words[i + offset_words] << carry_bits);
530
532
533 /* shift bits down and carry bits from the previous word */
534 result->words[i] = (a->words[i + offset_words] >> offset_bits) | prev_carry;
536 } while (--i >= 0);
537 }
538 }
539
540 return result;
541}
542
543/*
544 * bms_is_subset - is A a subset of B?
545 */
546bool
548{
549 int i;
550
553
554 /* Handle cases where either input is NULL */
555 if (a == NULL)
556 return true; /* empty set is a subset of anything */
557 if (b == NULL)
558 return false;
559
560 /* 'a' can't be a subset of 'b' if it contains more words */
561 if (a->nwords > b->nwords)
562 return false;
563
564 /* Check all 'a' members are set in 'b' */
565 i = 0;
566 do
567 {
568 if ((a->words[i] & ~b->words[i]) != 0)
569 return false;
570 } while (++i < a->nwords);
571 return true;
572}
573
574/*
575 * bms_subset_compare - compare A and B for equality/subset relationships
576 *
577 * This is more efficient than testing bms_is_subset in both directions.
578 */
581{
583 int shortlen;
584 int i;
585
588
589 /* Handle cases where either input is NULL */
590 if (a == NULL)
591 {
592 if (b == NULL)
593 return BMS_EQUAL;
594 return BMS_SUBSET1;
595 }
596 if (b == NULL)
597 return BMS_SUBSET2;
598
599 /* Check common words */
600 result = BMS_EQUAL; /* status so far */
601 shortlen = Min(a->nwords, b->nwords);
602 i = 0;
603 do
604 {
605 bitmapword aword = a->words[i];
606 bitmapword bword = b->words[i];
607
608 if ((aword & ~bword) != 0)
609 {
610 /* a is not a subset of b */
611 if (result == BMS_SUBSET1)
612 return BMS_DIFFERENT;
614 }
615 if ((bword & ~aword) != 0)
616 {
617 /* b is not a subset of a */
618 if (result == BMS_SUBSET2)
619 return BMS_DIFFERENT;
621 }
622 } while (++i < shortlen);
623 /* Check extra words */
624 if (a->nwords > b->nwords)
625 {
626 /* if a has more words then a is not a subset of b */
627 if (result == BMS_SUBSET1)
628 return BMS_DIFFERENT;
629 return BMS_SUBSET2;
630 }
631 else if (a->nwords < b->nwords)
632 {
633 /* if b has more words then b is not a subset of a */
634 if (result == BMS_SUBSET2)
635 return BMS_DIFFERENT;
636 return BMS_SUBSET1;
637 }
638 return result;
639}
640
641/*
642 * bms_is_member - is X a member of A?
643 */
644bool
646{
647 int wordnum,
648 bitnum;
649
651
652 /* XXX better to just return false for x<0 ? */
653 if (x < 0)
654 elog(ERROR, "negative bitmapset member not allowed");
655 if (a == NULL)
656 return false;
657
658 wordnum = WORDNUM(x);
659 bitnum = BITNUM(x);
660 if (wordnum >= a->nwords)
661 return false;
662 if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
663 return true;
664 return false;
665}
666
667/*
668 * bms_member_index
669 * determine 0-based index of member x in the bitmap
670 *
671 * Returns (-1) when x is not a member.
672 */
673int
675{
676 int bitnum;
677 int wordnum;
678 int result = 0;
679 bitmapword mask;
680
682
683 /* return -1 if not a member of the bitmap */
684 if (!bms_is_member(x, a))
685 return -1;
686
687 wordnum = WORDNUM(x);
688 bitnum = BITNUM(x);
689
690 /* count bits in preceding words */
691 result += pg_popcount((const char *) a->words,
692 wordnum * sizeof(bitmapword));
693
694 /*
695 * Now add bits of the last word, but only those before the item. We can
696 * do that by applying a mask and then using popcount again. To get
697 * 0-based index, we want to count only preceding bits, not the item
698 * itself, so we subtract 1.
699 */
700 mask = ((bitmapword) 1 << bitnum) - 1;
701 result += bmw_popcount(a->words[wordnum] & mask);
702
703 return result;
704}
705
706/*
707 * bms_overlap - do sets overlap (ie, have a nonempty intersection)?
708 */
709bool
711{
712 int shortlen;
713 int i;
714
717
718 /* Handle cases where either input is NULL */
719 if (a == NULL || b == NULL)
720 return false;
721 /* Check words in common */
722 shortlen = Min(a->nwords, b->nwords);
723 i = 0;
724 do
725 {
726 if ((a->words[i] & b->words[i]) != 0)
727 return true;
728 } while (++i < shortlen);
729 return false;
730}
731
732/*
733 * bms_overlap_list - does a set overlap an integer list?
734 */
735bool
737{
738 ListCell *lc;
739 int wordnum,
740 bitnum;
741
743
744 if (a == NULL || b == NIL)
745 return false;
746
747 foreach(lc, b)
748 {
749 int x = lfirst_int(lc);
750
751 if (x < 0)
752 elog(ERROR, "negative bitmapset member not allowed");
753 wordnum = WORDNUM(x);
754 bitnum = BITNUM(x);
755 if (wordnum < a->nwords)
756 if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
757 return true;
758 }
759
760 return false;
761}
762
763/*
764 * bms_nonempty_difference - do sets have a nonempty difference?
765 *
766 * i.e., are any members set in 'a' that are not also set in 'b'.
767 */
768bool
770{
771 int i;
772
775
776 /* Handle cases where either input is NULL */
777 if (a == NULL)
778 return false;
779 if (b == NULL)
780 return true;
781 /* if 'a' has more words then it must contain additional members */
782 if (a->nwords > b->nwords)
783 return true;
784 /* Check all 'a' members are set in 'b' */
785 i = 0;
786 do
787 {
788 if ((a->words[i] & ~b->words[i]) != 0)
789 return true;
790 } while (++i < a->nwords);
791 return false;
792}
793
794/*
795 * bms_singleton_member - return the sole integer member of set
796 *
797 * Raises error if |a| is not 1.
798 */
799int
801{
802 int result = -1;
803 int nwords;
804 int wordnum;
805
807
808 if (a == NULL)
809 elog(ERROR, "bitmapset is empty");
810
811 nwords = a->nwords;
812 wordnum = 0;
813 do
814 {
815 bitmapword w = a->words[wordnum];
816
817 if (w != 0)
818 {
819 if (result >= 0 || HAS_MULTIPLE_ONES(w))
820 elog(ERROR, "bitmapset has multiple members");
823 }
824 } while (++wordnum < nwords);
825
826 /* we don't expect non-NULL sets to be empty */
827 Assert(result >= 0);
828 return result;
829}
830
831/*
832 * bms_get_singleton_member
833 *
834 * Test whether the given set is a singleton.
835 * If so, set *member to the value of its sole member, and return true.
836 * If not, return false, without changing *member.
837 *
838 * This is more convenient and faster than calling bms_membership() and then
839 * bms_singleton_member(), if we don't care about distinguishing empty sets
840 * from multiple-member sets.
841 */
842bool
844{
845 int result = -1;
846 int nwords;
847 int wordnum;
848
850
851 if (a == NULL)
852 return false;
853
854 nwords = a->nwords;
855 wordnum = 0;
856 do
857 {
858 bitmapword w = a->words[wordnum];
859
860 if (w != 0)
861 {
862 if (result >= 0 || HAS_MULTIPLE_ONES(w))
863 return false;
866 }
867 } while (++wordnum < nwords);
868
869 /* we don't expect non-NULL sets to be empty */
870 Assert(result >= 0);
871 *member = result;
872 return true;
873}
874
875/*
876 * bms_num_members - count members of set
877 */
878int
880{
882
883 if (a == NULL)
884 return 0;
885
886 /* fast-path for common case */
887 if (a->nwords == 1)
888 return bmw_popcount(a->words[0]);
889
890 return pg_popcount((const char *) a->words,
891 a->nwords * sizeof(bitmapword));
892}
893
894/*
895 * bms_membership - does a set have zero, one, or multiple members?
896 *
897 * This is faster than making an exact count with bms_num_members().
898 */
901{
903 int nwords;
904 int wordnum;
905
907
908 if (a == NULL)
909 return BMS_EMPTY_SET;
910
911 nwords = a->nwords;
912 wordnum = 0;
913 do
914 {
915 bitmapword w = a->words[wordnum];
916
917 if (w != 0)
918 {
920 return BMS_MULTIPLE;
922 }
923 } while (++wordnum < nwords);
924 return result;
925}
926
927
928/*
929 * bms_add_member - add a specified member to set
930 *
931 * 'a' is recycled when possible.
932 */
933Bitmapset *
935{
936 int wordnum,
937 bitnum;
938
940
941 if (x < 0)
942 elog(ERROR, "negative bitmapset member not allowed");
943 if (a == NULL)
944 return bms_make_singleton(x);
945
946 wordnum = WORDNUM(x);
947 bitnum = BITNUM(x);
948
949 /* enlarge the set if necessary */
950 if (wordnum >= a->nwords)
951 {
952 int oldnwords = a->nwords;
953 int i;
954
956 a->nwords = wordnum + 1;
957 /* zero out the enlarged portion */
958 i = oldnwords;
959 do
960 {
961 a->words[i] = 0;
962 } while (++i < a->nwords);
963 }
964
965 a->words[wordnum] |= ((bitmapword) 1 << bitnum);
966
967#ifdef REALLOCATE_BITMAPSETS
968
969 /*
970 * There's no guarantee that the repalloc returned a new pointer, so copy
971 * and free unconditionally here.
972 */
974#endif
975
976 return a;
977}
978
979/*
980 * bms_del_member - remove a specified member from set
981 *
982 * No error if x is not currently a member of set
983 *
984 * 'a' is recycled when possible.
985 */
986Bitmapset *
988{
989 int wordnum,
990 bitnum;
991
993
994 if (x < 0)
995 elog(ERROR, "negative bitmapset member not allowed");
996 if (a == NULL)
997 return NULL;
998
999 wordnum = WORDNUM(x);
1000 bitnum = BITNUM(x);
1001
1002#ifdef REALLOCATE_BITMAPSETS
1004#endif
1005
1006 /* member can't exist. Return 'a' unmodified */
1007 if (unlikely(wordnum >= a->nwords))
1008 return a;
1009
1010 a->words[wordnum] &= ~((bitmapword) 1 << bitnum);
1011
1012 /* when last word becomes empty, trim off all trailing empty words */
1013 if (a->words[wordnum] == 0 && wordnum == a->nwords - 1)
1014 {
1015 /* find the last non-empty word and make that the new final word */
1016 for (int i = wordnum - 1; i >= 0; i--)
1017 {
1018 if (a->words[i] != 0)
1019 {
1020 a->nwords = i + 1;
1021 return a;
1022 }
1023 }
1024
1025 /* the set is now empty */
1026 pfree(a);
1027 return NULL;
1028 }
1029 return a;
1030}
1031
1032/*
1033 * bms_add_members - like bms_union, but left input is recycled when possible
1034 */
1035Bitmapset *
1037{
1039 const Bitmapset *other;
1040 int otherlen;
1041 int i;
1042
1045
1046 /* Handle cases where either input is NULL */
1047 if (a == NULL)
1048 return bms_copy(b);
1049 if (b == NULL)
1050 {
1051#ifdef REALLOCATE_BITMAPSETS
1053#endif
1054
1055 return a;
1056 }
1057 /* Identify shorter and longer input; copy the longer one if needed */
1058 if (a->nwords < b->nwords)
1059 {
1060 result = bms_copy(b);
1061 other = a;
1062 }
1063 else
1064 {
1065 result = a;
1066 other = b;
1067 }
1068 /* And union the shorter input into the result */
1069 otherlen = other->nwords;
1070 i = 0;
1071 do
1072 {
1073 result->words[i] |= other->words[i];
1074 } while (++i < otherlen);
1075 if (result != a)
1076 pfree(a);
1077#ifdef REALLOCATE_BITMAPSETS
1078 else
1080#endif
1081
1082 return result;
1083}
1084
1085/*
1086 * bms_replace_members
1087 * Remove all existing members from 'a' and repopulate the set with members
1088 * from 'b', recycling 'a', when possible.
1089 */
1090Bitmapset *
1092{
1093 int i;
1094
1097
1098 if (a == NULL)
1099 return bms_copy(b);
1100 if (b == NULL)
1101 {
1102 pfree(a);
1103 return NULL;
1104 }
1105
1106 if (a->nwords < b->nwords)
1107 a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(b->nwords));
1108
1109 i = 0;
1110 do
1111 {
1112 a->words[i] = b->words[i];
1113 } while (++i < b->nwords);
1114
1115 a->nwords = b->nwords;
1116
1117#ifdef REALLOCATE_BITMAPSETS
1118
1119 /*
1120 * There's no guarantee that the repalloc returned a new pointer, so copy
1121 * and free unconditionally here.
1122 */
1124#endif
1125
1126 return a;
1127}
1128
1129/*
1130 * bms_add_range
1131 * Add members in the range of 'lower' to 'upper' to the set.
1132 *
1133 * Note this could also be done by calling bms_add_member in a loop, however,
1134 * using this function will be faster when the range is large as we work at
1135 * the bitmapword level rather than at bit level.
1136 */
1137Bitmapset *
1139{
1140 int lwordnum,
1141 lbitnum,
1142 uwordnum,
1143 ushiftbits,
1144 wordnum;
1145
1147
1148 /* do nothing if nothing is called for, without further checking */
1149 if (upper < lower)
1150 {
1151#ifdef REALLOCATE_BITMAPSETS
1153#endif
1154
1155 return a;
1156 }
1157
1158 if (lower < 0)
1159 elog(ERROR, "negative bitmapset member not allowed");
1161
1162 if (a == NULL)
1163 {
1165 a->type = T_Bitmapset;
1166 a->nwords = uwordnum + 1;
1167 }
1168 else if (uwordnum >= a->nwords)
1169 {
1170 int oldnwords = a->nwords;
1171 int i;
1172
1173 /* ensure we have enough words to store the upper bit */
1175 a->nwords = uwordnum + 1;
1176 /* zero out the enlarged portion */
1177 i = oldnwords;
1178 do
1179 {
1180 a->words[i] = 0;
1181 } while (++i < a->nwords);
1182 }
1183
1185
1186 lbitnum = BITNUM(lower);
1188
1189 /*
1190 * Special case when lwordnum is the same as uwordnum we must perform the
1191 * upper and lower masking on the word.
1192 */
1193 if (lwordnum == uwordnum)
1194 {
1195 a->words[lwordnum] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1)
1196 & (~(bitmapword) 0) >> ushiftbits;
1197 }
1198 else
1199 {
1200 /* turn on lbitnum and all bits left of it */
1201 a->words[wordnum++] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1);
1202
1203 /* turn on all bits for any intermediate words */
1204 while (wordnum < uwordnum)
1205 a->words[wordnum++] = ~(bitmapword) 0;
1206
1207 /* turn on upper's bit and all bits right of it. */
1208 a->words[uwordnum] |= (~(bitmapword) 0) >> ushiftbits;
1209 }
1210
1211#ifdef REALLOCATE_BITMAPSETS
1212
1213 /*
1214 * There's no guarantee that the repalloc returned a new pointer, so copy
1215 * and free unconditionally here.
1216 */
1218#endif
1219
1220 return a;
1221}
1222
1223/*
1224 * bms_int_members - like bms_intersect, but left input is recycled when
1225 * possible
1226 */
1227Bitmapset *
1229{
1230 int lastnonzero;
1231 int shortlen;
1232 int i;
1233
1236
1237 /* Handle cases where either input is NULL */
1238 if (a == NULL)
1239 return NULL;
1240 if (b == NULL)
1241 {
1242 pfree(a);
1243 return NULL;
1244 }
1245
1246 /* Intersect b into a; we need never copy */
1247 shortlen = Min(a->nwords, b->nwords);
1248 lastnonzero = -1;
1249 i = 0;
1250 do
1251 {
1252 a->words[i] &= b->words[i];
1253
1254 if (a->words[i] != 0)
1255 lastnonzero = i;
1256 } while (++i < shortlen);
1257
1258 /* If we computed an empty result, we must return NULL */
1259 if (lastnonzero == -1)
1260 {
1261 pfree(a);
1262 return NULL;
1263 }
1264
1265 /* get rid of trailing zero words */
1266 a->nwords = lastnonzero + 1;
1267
1268#ifdef REALLOCATE_BITMAPSETS
1270#endif
1271
1272 return a;
1273}
1274
1275/*
1276 * bms_del_members - delete members in 'a' that are set in 'b'. 'a' is
1277 * recycled when possible.
1278 */
1279Bitmapset *
1281{
1282 int i;
1283
1286
1287 /* Handle cases where either input is NULL */
1288 if (a == NULL)
1289 return NULL;
1290 if (b == NULL)
1291 {
1292#ifdef REALLOCATE_BITMAPSETS
1294#endif
1295
1296 return a;
1297 }
1298
1299 /* Remove b's bits from a; we need never copy */
1300 if (a->nwords > b->nwords)
1301 {
1302 /*
1303 * We'll never need to remove trailing zero words when 'a' has more
1304 * words than 'b'.
1305 */
1306 i = 0;
1307 do
1308 {
1309 a->words[i] &= ~b->words[i];
1310 } while (++i < b->nwords);
1311 }
1312 else
1313 {
1314 int lastnonzero = -1;
1315
1316 /* we may need to remove trailing zero words from the result. */
1317 i = 0;
1318 do
1319 {
1320 a->words[i] &= ~b->words[i];
1321
1322 /* remember the last non-zero word */
1323 if (a->words[i] != 0)
1324 lastnonzero = i;
1325 } while (++i < a->nwords);
1326
1327 /* check if 'a' has become empty */
1328 if (lastnonzero == -1)
1329 {
1330 pfree(a);
1331 return NULL;
1332 }
1333
1334 /* trim off any trailing zero words */
1335 a->nwords = lastnonzero + 1;
1336 }
1337
1338#ifdef REALLOCATE_BITMAPSETS
1340#endif
1341
1342 return a;
1343}
1344
1345/*
1346 * bms_join - like bms_union, but *either* input *may* be recycled
1347 */
1348Bitmapset *
1350{
1353 int otherlen;
1354 int i;
1355
1358
1359 /* Handle cases where either input is NULL */
1360 if (a == NULL)
1361 {
1362#ifdef REALLOCATE_BITMAPSETS
1364#endif
1365
1366 return b;
1367 }
1368 if (b == NULL)
1369 {
1370#ifdef REALLOCATE_BITMAPSETS
1372#endif
1373
1374 return a;
1375 }
1376
1377 /* Identify shorter and longer input; use longer one as result */
1378 if (a->nwords < b->nwords)
1379 {
1380 result = b;
1381 other = a;
1382 }
1383 else
1384 {
1385 result = a;
1386 other = b;
1387 }
1388 /* And union the shorter input into the result */
1389 otherlen = other->nwords;
1390 i = 0;
1391 do
1392 {
1393 result->words[i] |= other->words[i];
1394 } while (++i < otherlen);
1395 if (other != result) /* pure paranoia */
1396 pfree(other);
1397
1398#ifdef REALLOCATE_BITMAPSETS
1400#endif
1401
1402 return result;
1403}
1404
1405/*
1406 * bms_next_member - find next member of a set
1407 *
1408 * Returns smallest member greater than "prevbit", or -2 if there is none.
1409 * "prevbit" must NOT be less than -1, or the behavior is unpredictable.
1410 *
1411 * This is intended as support for iterating through the members of a set.
1412 * The typical pattern is
1413 *
1414 * x = -1;
1415 * while ((x = bms_next_member(inputset, x)) >= 0)
1416 * process member x;
1417 *
1418 * Notice that when there are no more members, we return -2, not -1 as you
1419 * might expect. The rationale for that is to allow distinguishing the
1420 * loop-not-started state (x == -1) from the loop-completed state (x == -2).
1421 * It makes no difference in simple loop usage, but complex iteration logic
1422 * might need such an ability.
1423 */
1424int
1426{
1427 unsigned int currbit = prevbit;
1428 int nwords;
1429 bitmapword mask;
1430
1432
1433 if (a == NULL)
1434 return -2;
1435 nwords = a->nwords;
1436
1437 /* use an unsigned int to avoid the risk that int overflows */
1438 currbit++;
1439 mask = (~(bitmapword) 0) << BITNUM(currbit);
1440 for (int wordnum = WORDNUM(currbit); wordnum < nwords; wordnum++)
1441 {
1442 bitmapword w = a->words[wordnum];
1443
1444 /* ignore bits before currbit */
1445 w &= mask;
1446
1447 if (w != 0)
1448 {
1449 int result;
1450
1453 return result;
1454 }
1455
1456 /* in subsequent words, consider all bits */
1457 mask = (~(bitmapword) 0);
1458 }
1459 return -2;
1460}
1461
1462/*
1463 * bms_prev_member - find prev member of a set
1464 *
1465 * Returns largest member less than "prevbit", or -2 if there is none.
1466 * "prevbit" must NOT be more than one above the highest possible bit that can
1467 * be set in the Bitmapset at its current size.
1468 *
1469 * To ease finding the highest set bit for the initial loop, the special
1470 * prevbit value of -1 can be passed to have the function find the highest
1471 * valued member in the set.
1472 *
1473 * This is intended as support for iterating through the members of a set in
1474 * reverse. The typical pattern is
1475 *
1476 * x = -1;
1477 * while ((x = bms_prev_member(inputset, x)) >= 0)
1478 * process member x;
1479 *
1480 * Notice that when there are no more members, we return -2, not -1 as you
1481 * might expect. The rationale for that is to allow distinguishing the
1482 * loop-not-started state (x == -1) from the loop-completed state (x == -2).
1483 * It makes no difference in simple loop usage, but complex iteration logic
1484 * might need such an ability.
1485 */
1486int
1488{
1489 unsigned int currbit;
1490 int ushiftbits;
1491 bitmapword mask;
1492
1494
1495 /*
1496 * If set is NULL or if there are no more bits to the right then we've
1497 * nothing to do.
1498 */
1499 if (a == NULL || prevbit == 0)
1500 return -2;
1501
1502 /* Validate callers didn't give us something out of range */
1503 Assert(prevbit < 0 || prevbit <= (unsigned int) (a->nwords * BITS_PER_BITMAPWORD));
1504
1505 /*
1506 * Transform -1 (or any negative number) to the highest possible bit we
1507 * could have set. We do this in unsigned math to avoid the risk of
1508 * overflowing a signed int.
1509 */
1510 if (prevbit < 0)
1511 currbit = (unsigned int) a->nwords * BITS_PER_BITMAPWORD - 1;
1512 else
1513 currbit = prevbit - 1;
1514
1516 mask = (~(bitmapword) 0) >> ushiftbits;
1517 for (int wordnum = WORDNUM(currbit); wordnum >= 0; wordnum--)
1518 {
1519 bitmapword w = a->words[wordnum];
1520
1521 /* mask out bits left of currbit */
1522 w &= mask;
1523
1524 if (w != 0)
1525 {
1526 int result;
1527
1530 return result;
1531 }
1532
1533 /* in subsequent words, consider all bits */
1534 mask = (~(bitmapword) 0);
1535 }
1536 return -2;
1537}
1538
1539/*
1540 * bms_hash_value - compute a hash key for a Bitmapset
1541 */
1542uint32
1544{
1546
1547 if (a == NULL)
1548 return 0; /* All empty sets hash to 0 */
1549 return DatumGetUInt32(hash_any((const unsigned char *) a->words,
1550 a->nwords * sizeof(bitmapword)));
1551}
1552
1553/*
1554 * bitmap_hash - hash function for keys that are (pointers to) Bitmapsets
1555 *
1556 * Note: don't forget to specify bitmap_match as the match function!
1557 */
1558uint32
1559bitmap_hash(const void *key, Size keysize)
1560{
1561 Assert(keysize == sizeof(Bitmapset *));
1562 return bms_hash_value(*((const Bitmapset *const *) key));
1563}
1564
1565/*
1566 * bitmap_match - match function to use with bitmap_hash
1567 */
1568int
1569bitmap_match(const void *key1, const void *key2, Size keysize)
1570{
1571 Assert(keysize == sizeof(Bitmapset *));
1572 return !bms_equal(*((const Bitmapset *const *) key1),
1573 *((const Bitmapset *const *) key2));
1574}
#define BITMAPSET_SIZE(nwords)
Definition bitmapset.c:51
Bitmapset * bms_replace_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1091
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:347
int bms_prev_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1487
Bitmapset * bms_make_singleton(int x)
Definition bitmapset.c:217
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1228
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:293
uint32 bitmap_hash(const void *key, Size keysize)
Definition bitmapset.c:1559
#define WORDNUM(x)
Definition bitmapset.c:48
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:143
BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:580
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1425
uint32 bms_hash_value(const Bitmapset *a)
Definition bitmapset.c:1543
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1280
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition bitmapset.c:1138
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition bitmapset.c:987
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:547
int bms_singleton_member(const Bitmapset *a)
Definition bitmapset.c:800
void bms_free(Bitmapset *a)
Definition bitmapset.c:240
int bms_num_members(const Bitmapset *a)
Definition bitmapset.c:879
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:645
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:934
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1036
#define BITNUM(x)
Definition bitmapset.c:49
Bitmapset * bms_offset_members(const Bitmapset *a, int offset)
Definition bitmapset.c:419
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:252
#define HAS_MULTIPLE_ONES(x)
Definition bitmapset.c:73
int bitmap_match(const void *key1, const void *key2, Size keysize)
Definition bitmapset.c:1569
BMS_Membership bms_membership(const Bitmapset *a)
Definition bitmapset.c:900
int bms_member_index(Bitmapset *a, int x)
Definition bitmapset.c:674
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:710
int bms_compare(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:184
bool bms_get_singleton_member(const Bitmapset *a, int *member)
Definition bitmapset.c:843
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition bitmapset.c:1349
bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:769
Bitmapset * bms_copy(const Bitmapset *a)
Definition bitmapset.c:123
bool bms_overlap_list(const Bitmapset *a, const List *b)
Definition bitmapset.c:736
#define bmw_rightmost_one_pos(w)
Definition bitmapset.h:79
#define bmw_leftmost_one_pos(w)
Definition bitmapset.h:78
BMS_Comparison
Definition bitmapset.h:61
@ BMS_DIFFERENT
Definition bitmapset.h:65
@ BMS_SUBSET1
Definition bitmapset.h:63
@ BMS_EQUAL
Definition bitmapset.h:62
@ BMS_SUBSET2
Definition bitmapset.h:64
BMS_Membership
Definition bitmapset.h:70
@ BMS_SINGLETON
Definition bitmapset.h:72
@ BMS_EMPTY_SET
Definition bitmapset.h:71
@ BMS_MULTIPLE
Definition bitmapset.h:73
uint32 bitmapword
Definition bitmapset.h:44
#define BITS_PER_BITMAPWORD
Definition bitmapset.h:43
#define bmw_popcount(w)
Definition bitmapset.h:80
#define Min(x, y)
Definition c.h:1131
#define Assert(condition)
Definition c.h:1002
int32_t int32
Definition c.h:679
#define unlikely(x)
Definition c.h:497
uint32_t uint32
Definition c.h:683
size_t Size
Definition c.h:748
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
static Datum hash_any(const unsigned char *k, int keylen)
Definition hashfn.h:31
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)
Definition int.h:151
int b
Definition isn.c:74
int x
Definition isn.c:75
int a
Definition isn.c:73
int i
Definition isn.c:77
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1635
void pfree(void *pointer)
Definition mcxt.c:1619
void * palloc0(Size size)
Definition mcxt.c:1420
void * palloc(Size size)
Definition mcxt.c:1390
#define IsA(nodeptr, _type_)
Definition nodes.h:162
Datum lower(PG_FUNCTION_ARGS)
Datum upper(PG_FUNCTION_ARGS)
static uint64 pg_popcount(const char *buf, int bytes)
#define NIL
Definition pg_list.h:68
#define lfirst_int(lc)
Definition pg_list.h:173
static uint32 DatumGetUInt32(Datum X)
Definition postgres.h:222
char * c
static int fb(int x)
Definition pg_list.h:54