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 "nodes/bitmapset.h"
43#include "nodes/pg_list.h"
44#include "port/pg_bitutils.h"
45
46
47#define WORDNUM(x) ((x) / BITS_PER_BITMAPWORD)
48#define BITNUM(x) ((x) % BITS_PER_BITMAPWORD)
49
50#define BITMAPSET_SIZE(nwords) \
51 (offsetof(Bitmapset, words) + (nwords) * sizeof(bitmapword))
52
53/*----------
54 * This is a well-known cute trick for isolating the rightmost one-bit
55 * in a word. It assumes two's complement arithmetic. Consider any
56 * nonzero value, and focus attention on the rightmost one. The value is
57 * then something like
58 * xxxxxx10000
59 * where x's are unspecified bits. The two's complement negative is formed
60 * by inverting all the bits and adding one. Inversion gives
61 * yyyyyy01111
62 * where each y is the inverse of the corresponding x. Incrementing gives
63 * yyyyyy10000
64 * and then ANDing with the original value gives
65 * 00000010000
66 * This works for all cases except original value = zero, where of course
67 * we get zero.
68 *----------
69 */
70#define RIGHTMOST_ONE(x) ((signedbitmapword) (x) & -((signedbitmapword) (x)))
71
72#define HAS_MULTIPLE_ONES(x) ((bitmapword) RIGHTMOST_ONE(x) != (x))
73
74#ifdef USE_ASSERT_CHECKING
75/*
76 * bms_is_valid_set - for cassert builds to check for valid sets
77 */
78static bool
80{
81 /* NULL is the correct representation of an empty set */
82 if (a == NULL)
83 return true;
84
85 /* check the node tag is set correctly. pfree'd pointer, maybe? */
86 if (!IsA(a, Bitmapset))
87 return false;
88
89 /* trailing zero words are not allowed */
90 if (a->words[a->nwords - 1] == 0)
91 return false;
92
93 return true;
94}
95#endif
96
97#ifdef REALLOCATE_BITMAPSETS
98/*
99 * bms_copy_and_free
100 * Only required in REALLOCATE_BITMAPSETS builds. Provide a simple way
101 * to return a freshly allocated set and pfree the original.
102 *
103 * Note: callers which accept multiple sets must be careful when calling this
104 * function to clone one parameter as other parameters may point to the same
105 * set. A good option is to call this just before returning the resulting
106 * set.
107 */
108static Bitmapset *
110{
111 Bitmapset *c = bms_copy(a);
112
113 bms_free(a);
114 return c;
115}
116#endif
117
118/*
119 * bms_copy - make a palloc'd copy of a bitmapset
120 */
121Bitmapset *
123{
124 Bitmapset *result;
125 size_t size;
126
128
129 if (a == NULL)
130 return NULL;
131
132 size = BITMAPSET_SIZE(a->nwords);
133 result = (Bitmapset *) palloc(size);
134 memcpy(result, a, size);
135 return result;
136}
137
138/*
139 * bms_equal - are two bitmapsets equal? or both NULL?
140 */
141bool
143{
144 int i;
145
148
149 /* Handle cases where either input is NULL */
150 if (a == NULL)
151 {
152 if (b == NULL)
153 return true;
154 return false;
155 }
156 else if (b == NULL)
157 return false;
158
159 /* can't be equal if the word counts don't match */
160 if (a->nwords != b->nwords)
161 return false;
162
163 /* check each word matches */
164 i = 0;
165 do
166 {
167 if (a->words[i] != b->words[i])
168 return false;
169 } while (++i < a->nwords);
170
171 return true;
172}
173
174/*
175 * bms_compare - qsort-style comparator for bitmapsets
176 *
177 * This guarantees to report values as equal iff bms_equal would say they are
178 * equal. Otherwise, the highest-numbered bit that is set in one value but
179 * not the other determines the result. (This rule means that, for example,
180 * {6} is greater than {5}, which seems plausible.)
181 */
182int
184{
185 int i;
186
189
190 /* Handle cases where either input is NULL */
191 if (a == NULL)
192 return (b == NULL) ? 0 : -1;
193 else if (b == NULL)
194 return +1;
195
196 /* the set with the most words must be greater */
197 if (a->nwords != b->nwords)
198 return (a->nwords > b->nwords) ? +1 : -1;
199
200 i = a->nwords - 1;
201 do
202 {
203 bitmapword aw = a->words[i];
204 bitmapword bw = b->words[i];
205
206 if (aw != bw)
207 return (aw > bw) ? +1 : -1;
208 } while (--i >= 0);
209 return 0;
210}
211
212/*
213 * bms_make_singleton - build a bitmapset containing a single member
214 */
215Bitmapset *
217{
218 Bitmapset *result;
219 int wordnum,
220 bitnum;
221
222 if (x < 0)
223 elog(ERROR, "negative bitmapset member not allowed");
224 wordnum = WORDNUM(x);
225 bitnum = BITNUM(x);
226 result = (Bitmapset *) palloc0(BITMAPSET_SIZE(wordnum + 1));
227 result->type = T_Bitmapset;
228 result->nwords = wordnum + 1;
229 result->words[wordnum] = ((bitmapword) 1 << bitnum);
230 return result;
231}
232
233/*
234 * bms_free - free a bitmapset
235 *
236 * Same as pfree except for allowing NULL input
237 */
238void
240{
241 if (a)
242 pfree(a);
243}
244
245
246/*
247 * bms_union - create and return a new set containing all members from both
248 * input sets. Both inputs are left unmodified.
249 */
250Bitmapset *
252{
253 Bitmapset *result;
254 const Bitmapset *other;
255 int otherlen;
256 int i;
257
260
261 /* Handle cases where either input is NULL */
262 if (a == NULL)
263 return bms_copy(b);
264 if (b == NULL)
265 return bms_copy(a);
266 /* Identify shorter and longer input; copy the longer one */
267 if (a->nwords <= b->nwords)
268 {
269 result = bms_copy(b);
270 other = a;
271 }
272 else
273 {
274 result = bms_copy(a);
275 other = b;
276 }
277 /* And union the shorter input into the result */
278 otherlen = other->nwords;
279 i = 0;
280 do
281 {
282 result->words[i] |= other->words[i];
283 } while (++i < otherlen);
284 return result;
285}
286
287/*
288 * bms_intersect - create and return a new set containing members which both
289 * input sets have in common. Both inputs are left unmodified.
290 */
291Bitmapset *
293{
294 Bitmapset *result;
295 const Bitmapset *other;
296 int lastnonzero;
297 int resultlen;
298 int i;
299
302
303 /* Handle cases where either input is NULL */
304 if (a == NULL || b == NULL)
305 return NULL;
306
307 /* Identify shorter and longer input; copy the shorter one */
308 if (a->nwords <= b->nwords)
309 {
310 result = bms_copy(a);
311 other = b;
312 }
313 else
314 {
315 result = bms_copy(b);
316 other = a;
317 }
318 /* And intersect the longer input with the result */
319 resultlen = result->nwords;
320 lastnonzero = -1;
321 i = 0;
322 do
323 {
324 result->words[i] &= other->words[i];
325
326 if (result->words[i] != 0)
327 lastnonzero = i;
328 } while (++i < resultlen);
329 /* If we computed an empty result, we must return NULL */
330 if (lastnonzero == -1)
331 {
332 pfree(result);
333 return NULL;
334 }
335
336 /* get rid of trailing zero words */
337 result->nwords = lastnonzero + 1;
338 return result;
339}
340
341/*
342 * bms_difference - create and return a new set containing all the members of
343 * 'a' without the members of 'b'.
344 */
345Bitmapset *
347{
348 Bitmapset *result;
349 int i;
350
353
354 /* Handle cases where either input is NULL */
355 if (a == NULL)
356 return NULL;
357 if (b == NULL)
358 return bms_copy(a);
359
360 /*
361 * In Postgres' usage, an empty result is a very common case, so it's
362 * worth optimizing for that by testing bms_nonempty_difference(). This
363 * saves us a palloc/pfree cycle compared to checking after-the-fact.
364 */
366 return NULL;
367
368 /* Copy the left input */
369 result = bms_copy(a);
370
371 /* And remove b's bits from result */
372 if (result->nwords > b->nwords)
373 {
374 /*
375 * We'll never need to remove trailing zero words when 'a' has more
376 * words than 'b' as the additional words must be non-zero.
377 */
378 i = 0;
379 do
380 {
381 result->words[i] &= ~b->words[i];
382 } while (++i < b->nwords);
383 }
384 else
385 {
386 int lastnonzero = -1;
387
388 /* we may need to remove trailing zero words from the result. */
389 i = 0;
390 do
391 {
392 result->words[i] &= ~b->words[i];
393
394 /* remember the last non-zero word */
395 if (result->words[i] != 0)
396 lastnonzero = i;
397 } while (++i < result->nwords);
398
399 /* trim off trailing zero words */
400 result->nwords = lastnonzero + 1;
401 }
402 Assert(result->nwords != 0);
403
404 /* Need not check for empty result, since we handled that case above */
405 return result;
406}
407
408/*
409 * bms_is_subset - is A a subset of B?
410 */
411bool
413{
414 int i;
415
418
419 /* Handle cases where either input is NULL */
420 if (a == NULL)
421 return true; /* empty set is a subset of anything */
422 if (b == NULL)
423 return false;
424
425 /* 'a' can't be a subset of 'b' if it contains more words */
426 if (a->nwords > b->nwords)
427 return false;
428
429 /* Check all 'a' members are set in 'b' */
430 i = 0;
431 do
432 {
433 if ((a->words[i] & ~b->words[i]) != 0)
434 return false;
435 } while (++i < a->nwords);
436 return true;
437}
438
439/*
440 * bms_subset_compare - compare A and B for equality/subset relationships
441 *
442 * This is more efficient than testing bms_is_subset in both directions.
443 */
446{
447 BMS_Comparison result;
448 int shortlen;
449 int i;
450
453
454 /* Handle cases where either input is NULL */
455 if (a == NULL)
456 {
457 if (b == NULL)
458 return BMS_EQUAL;
459 return BMS_SUBSET1;
460 }
461 if (b == NULL)
462 return BMS_SUBSET2;
463
464 /* Check common words */
465 result = BMS_EQUAL; /* status so far */
466 shortlen = Min(a->nwords, b->nwords);
467 i = 0;
468 do
469 {
470 bitmapword aword = a->words[i];
471 bitmapword bword = b->words[i];
472
473 if ((aword & ~bword) != 0)
474 {
475 /* a is not a subset of b */
476 if (result == BMS_SUBSET1)
477 return BMS_DIFFERENT;
478 result = BMS_SUBSET2;
479 }
480 if ((bword & ~aword) != 0)
481 {
482 /* b is not a subset of a */
483 if (result == BMS_SUBSET2)
484 return BMS_DIFFERENT;
485 result = BMS_SUBSET1;
486 }
487 } while (++i < shortlen);
488 /* Check extra words */
489 if (a->nwords > b->nwords)
490 {
491 /* if a has more words then a is not a subset of b */
492 if (result == BMS_SUBSET1)
493 return BMS_DIFFERENT;
494 return BMS_SUBSET2;
495 }
496 else if (a->nwords < b->nwords)
497 {
498 /* if b has more words then b is not a subset of a */
499 if (result == BMS_SUBSET2)
500 return BMS_DIFFERENT;
501 return BMS_SUBSET1;
502 }
503 return result;
504}
505
506/*
507 * bms_is_member - is X a member of A?
508 */
509bool
511{
512 int wordnum,
513 bitnum;
514
516
517 /* XXX better to just return false for x<0 ? */
518 if (x < 0)
519 elog(ERROR, "negative bitmapset member not allowed");
520 if (a == NULL)
521 return false;
522
523 wordnum = WORDNUM(x);
524 bitnum = BITNUM(x);
525 if (wordnum >= a->nwords)
526 return false;
527 if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
528 return true;
529 return false;
530}
531
532/*
533 * bms_member_index
534 * determine 0-based index of member x in the bitmap
535 *
536 * Returns (-1) when x is not a member.
537 */
538int
540{
541 int bitnum;
542 int wordnum;
543 int result = 0;
544 bitmapword mask;
545
547
548 /* return -1 if not a member of the bitmap */
549 if (!bms_is_member(x, a))
550 return -1;
551
552 wordnum = WORDNUM(x);
553 bitnum = BITNUM(x);
554
555 /* count bits in preceding words */
556 result += pg_popcount((const char *) a->words,
557 wordnum * sizeof(bitmapword));
558
559 /*
560 * Now add bits of the last word, but only those before the item. We can
561 * do that by applying a mask and then using popcount again. To get
562 * 0-based index, we want to count only preceding bits, not the item
563 * itself, so we subtract 1.
564 */
565 mask = ((bitmapword) 1 << bitnum) - 1;
566 result += bmw_popcount(a->words[wordnum] & mask);
567
568 return result;
569}
570
571/*
572 * bms_overlap - do sets overlap (ie, have a nonempty intersection)?
573 */
574bool
576{
577 int shortlen;
578 int i;
579
582
583 /* Handle cases where either input is NULL */
584 if (a == NULL || b == NULL)
585 return false;
586 /* Check words in common */
587 shortlen = Min(a->nwords, b->nwords);
588 i = 0;
589 do
590 {
591 if ((a->words[i] & b->words[i]) != 0)
592 return true;
593 } while (++i < shortlen);
594 return false;
595}
596
597/*
598 * bms_overlap_list - does a set overlap an integer list?
599 */
600bool
602{
603 ListCell *lc;
604 int wordnum,
605 bitnum;
606
608
609 if (a == NULL || b == NIL)
610 return false;
611
612 foreach(lc, b)
613 {
614 int x = lfirst_int(lc);
615
616 if (x < 0)
617 elog(ERROR, "negative bitmapset member not allowed");
618 wordnum = WORDNUM(x);
619 bitnum = BITNUM(x);
620 if (wordnum < a->nwords)
621 if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
622 return true;
623 }
624
625 return false;
626}
627
628/*
629 * bms_nonempty_difference - do sets have a nonempty difference?
630 *
631 * i.e., are any members set in 'a' that are not also set in 'b'.
632 */
633bool
635{
636 int i;
637
640
641 /* Handle cases where either input is NULL */
642 if (a == NULL)
643 return false;
644 if (b == NULL)
645 return true;
646 /* if 'a' has more words then it must contain additional members */
647 if (a->nwords > b->nwords)
648 return true;
649 /* Check all 'a' members are set in 'b' */
650 i = 0;
651 do
652 {
653 if ((a->words[i] & ~b->words[i]) != 0)
654 return true;
655 } while (++i < a->nwords);
656 return false;
657}
658
659/*
660 * bms_singleton_member - return the sole integer member of set
661 *
662 * Raises error if |a| is not 1.
663 */
664int
666{
667 int result = -1;
668 int nwords;
669 int wordnum;
670
672
673 if (a == NULL)
674 elog(ERROR, "bitmapset is empty");
675
676 nwords = a->nwords;
677 wordnum = 0;
678 do
679 {
680 bitmapword w = a->words[wordnum];
681
682 if (w != 0)
683 {
684 if (result >= 0 || HAS_MULTIPLE_ONES(w))
685 elog(ERROR, "bitmapset has multiple members");
686 result = wordnum * BITS_PER_BITMAPWORD;
687 result += bmw_rightmost_one_pos(w);
688 }
689 } while (++wordnum < nwords);
690
691 /* we don't expect non-NULL sets to be empty */
692 Assert(result >= 0);
693 return result;
694}
695
696/*
697 * bms_get_singleton_member
698 *
699 * Test whether the given set is a singleton.
700 * If so, set *member to the value of its sole member, and return true.
701 * If not, return false, without changing *member.
702 *
703 * This is more convenient and faster than calling bms_membership() and then
704 * bms_singleton_member(), if we don't care about distinguishing empty sets
705 * from multiple-member sets.
706 */
707bool
709{
710 int result = -1;
711 int nwords;
712 int wordnum;
713
715
716 if (a == NULL)
717 return false;
718
719 nwords = a->nwords;
720 wordnum = 0;
721 do
722 {
723 bitmapword w = a->words[wordnum];
724
725 if (w != 0)
726 {
727 if (result >= 0 || HAS_MULTIPLE_ONES(w))
728 return false;
729 result = wordnum * BITS_PER_BITMAPWORD;
730 result += bmw_rightmost_one_pos(w);
731 }
732 } while (++wordnum < nwords);
733
734 /* we don't expect non-NULL sets to be empty */
735 Assert(result >= 0);
736 *member = result;
737 return true;
738}
739
740/*
741 * bms_num_members - count members of set
742 */
743int
745{
747
748 if (a == NULL)
749 return 0;
750
751 /* fast-path for common case */
752 if (a->nwords == 1)
753 return bmw_popcount(a->words[0]);
754
755 return pg_popcount((const char *) a->words,
756 a->nwords * sizeof(bitmapword));
757}
758
759/*
760 * bms_membership - does a set have zero, one, or multiple members?
761 *
762 * This is faster than making an exact count with bms_num_members().
763 */
766{
768 int nwords;
769 int wordnum;
770
772
773 if (a == NULL)
774 return BMS_EMPTY_SET;
775
776 nwords = a->nwords;
777 wordnum = 0;
778 do
779 {
780 bitmapword w = a->words[wordnum];
781
782 if (w != 0)
783 {
784 if (result != BMS_EMPTY_SET || HAS_MULTIPLE_ONES(w))
785 return BMS_MULTIPLE;
786 result = BMS_SINGLETON;
787 }
788 } while (++wordnum < nwords);
789 return result;
790}
791
792
793/*
794 * bms_add_member - add a specified member to set
795 *
796 * 'a' is recycled when possible.
797 */
798Bitmapset *
800{
801 int wordnum,
802 bitnum;
803
805
806 if (x < 0)
807 elog(ERROR, "negative bitmapset member not allowed");
808 if (a == NULL)
809 return bms_make_singleton(x);
810
811 wordnum = WORDNUM(x);
812 bitnum = BITNUM(x);
813
814 /* enlarge the set if necessary */
815 if (wordnum >= a->nwords)
816 {
817 int oldnwords = a->nwords;
818 int i;
819
821 a->nwords = wordnum + 1;
822 /* zero out the enlarged portion */
823 i = oldnwords;
824 do
825 {
826 a->words[i] = 0;
827 } while (++i < a->nwords);
828 }
829
830 a->words[wordnum] |= ((bitmapword) 1 << bitnum);
831
832#ifdef REALLOCATE_BITMAPSETS
833
834 /*
835 * There's no guarantee that the repalloc returned a new pointer, so copy
836 * and free unconditionally here.
837 */
839#endif
840
841 return a;
842}
843
844/*
845 * bms_del_member - remove a specified member from set
846 *
847 * No error if x is not currently a member of set
848 *
849 * 'a' is recycled when possible.
850 */
851Bitmapset *
853{
854 int wordnum,
855 bitnum;
856
858
859 if (x < 0)
860 elog(ERROR, "negative bitmapset member not allowed");
861 if (a == NULL)
862 return NULL;
863
864 wordnum = WORDNUM(x);
865 bitnum = BITNUM(x);
866
867#ifdef REALLOCATE_BITMAPSETS
869#endif
870
871 /* member can't exist. Return 'a' unmodified */
872 if (unlikely(wordnum >= a->nwords))
873 return a;
874
875 a->words[wordnum] &= ~((bitmapword) 1 << bitnum);
876
877 /* when last word becomes empty, trim off all trailing empty words */
878 if (a->words[wordnum] == 0 && wordnum == a->nwords - 1)
879 {
880 /* find the last non-empty word and make that the new final word */
881 for (int i = wordnum - 1; i >= 0; i--)
882 {
883 if (a->words[i] != 0)
884 {
885 a->nwords = i + 1;
886 return a;
887 }
888 }
889
890 /* the set is now empty */
891 pfree(a);
892 return NULL;
893 }
894 return a;
895}
896
897/*
898 * bms_add_members - like bms_union, but left input is recycled when possible
899 */
900Bitmapset *
902{
903 Bitmapset *result;
904 const Bitmapset *other;
905 int otherlen;
906 int i;
907
910
911 /* Handle cases where either input is NULL */
912 if (a == NULL)
913 return bms_copy(b);
914 if (b == NULL)
915 {
916#ifdef REALLOCATE_BITMAPSETS
918#endif
919
920 return a;
921 }
922 /* Identify shorter and longer input; copy the longer one if needed */
923 if (a->nwords < b->nwords)
924 {
925 result = bms_copy(b);
926 other = a;
927 }
928 else
929 {
930 result = a;
931 other = b;
932 }
933 /* And union the shorter input into the result */
935 i = 0;
936 do
937 {
938 result->words[i] |= other->words[i];
939 } while (++i < otherlen);
940 if (result != a)
941 pfree(a);
942#ifdef REALLOCATE_BITMAPSETS
943 else
944 result = bms_copy_and_free(result);
945#endif
946
947 return result;
948}
949
950/*
951 * bms_replace_members
952 * Remove all existing members from 'a' and repopulate the set with members
953 * from 'b', recycling 'a', when possible.
954 */
955Bitmapset *
957{
958 int i;
959
962
963 if (a == NULL)
964 return bms_copy(b);
965 if (b == NULL)
966 {
967 pfree(a);
968 return NULL;
969 }
970
971 if (a->nwords < b->nwords)
972 a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(b->nwords));
973
974 i = 0;
975 do
976 {
977 a->words[i] = b->words[i];
978 } while (++i < b->nwords);
979
980 a->nwords = b->nwords;
981
982#ifdef REALLOCATE_BITMAPSETS
983
984 /*
985 * There's no guarantee that the repalloc returned a new pointer, so copy
986 * and free unconditionally here.
987 */
989#endif
990
991 return a;
992}
993
994/*
995 * bms_add_range
996 * Add members in the range of 'lower' to 'upper' to the set.
997 *
998 * Note this could also be done by calling bms_add_member in a loop, however,
999 * using this function will be faster when the range is large as we work at
1000 * the bitmapword level rather than at bit level.
1001 */
1002Bitmapset *
1004{
1005 int lwordnum,
1006 lbitnum,
1007 uwordnum,
1008 ushiftbits,
1009 wordnum;
1010
1012
1013 /* do nothing if nothing is called for, without further checking */
1014 if (upper < lower)
1015 {
1016#ifdef REALLOCATE_BITMAPSETS
1018#endif
1019
1020 return a;
1021 }
1022
1023 if (lower < 0)
1024 elog(ERROR, "negative bitmapset member not allowed");
1026
1027 if (a == NULL)
1028 {
1030 a->type = T_Bitmapset;
1031 a->nwords = uwordnum + 1;
1032 }
1033 else if (uwordnum >= a->nwords)
1034 {
1035 int oldnwords = a->nwords;
1036 int i;
1037
1038 /* ensure we have enough words to store the upper bit */
1040 a->nwords = uwordnum + 1;
1041 /* zero out the enlarged portion */
1042 i = oldnwords;
1043 do
1044 {
1045 a->words[i] = 0;
1046 } while (++i < a->nwords);
1047 }
1048
1050
1051 lbitnum = BITNUM(lower);
1053
1054 /*
1055 * Special case when lwordnum is the same as uwordnum we must perform the
1056 * upper and lower masking on the word.
1057 */
1058 if (lwordnum == uwordnum)
1059 {
1060 a->words[lwordnum] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1)
1061 & (~(bitmapword) 0) >> ushiftbits;
1062 }
1063 else
1064 {
1065 /* turn on lbitnum and all bits left of it */
1066 a->words[wordnum++] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1);
1067
1068 /* turn on all bits for any intermediate words */
1069 while (wordnum < uwordnum)
1070 a->words[wordnum++] = ~(bitmapword) 0;
1071
1072 /* turn on upper's bit and all bits right of it. */
1073 a->words[uwordnum] |= (~(bitmapword) 0) >> ushiftbits;
1074 }
1075
1076#ifdef REALLOCATE_BITMAPSETS
1077
1078 /*
1079 * There's no guarantee that the repalloc returned a new pointer, so copy
1080 * and free unconditionally here.
1081 */
1083#endif
1084
1085 return a;
1086}
1087
1088/*
1089 * bms_int_members - like bms_intersect, but left input is recycled when
1090 * possible
1091 */
1092Bitmapset *
1094{
1095 int lastnonzero;
1096 int shortlen;
1097 int i;
1098
1101
1102 /* Handle cases where either input is NULL */
1103 if (a == NULL)
1104 return NULL;
1105 if (b == NULL)
1106 {
1107 pfree(a);
1108 return NULL;
1109 }
1110
1111 /* Intersect b into a; we need never copy */
1112 shortlen = Min(a->nwords, b->nwords);
1113 lastnonzero = -1;
1114 i = 0;
1115 do
1116 {
1117 a->words[i] &= b->words[i];
1118
1119 if (a->words[i] != 0)
1120 lastnonzero = i;
1121 } while (++i < shortlen);
1122
1123 /* If we computed an empty result, we must return NULL */
1124 if (lastnonzero == -1)
1125 {
1126 pfree(a);
1127 return NULL;
1128 }
1129
1130 /* get rid of trailing zero words */
1131 a->nwords = lastnonzero + 1;
1132
1133#ifdef REALLOCATE_BITMAPSETS
1135#endif
1136
1137 return a;
1138}
1139
1140/*
1141 * bms_del_members - delete members in 'a' that are set in 'b'. 'a' is
1142 * recycled when possible.
1143 */
1144Bitmapset *
1146{
1147 int i;
1148
1151
1152 /* Handle cases where either input is NULL */
1153 if (a == NULL)
1154 return NULL;
1155 if (b == NULL)
1156 {
1157#ifdef REALLOCATE_BITMAPSETS
1159#endif
1160
1161 return a;
1162 }
1163
1164 /* Remove b's bits from a; we need never copy */
1165 if (a->nwords > b->nwords)
1166 {
1167 /*
1168 * We'll never need to remove trailing zero words when 'a' has more
1169 * words than 'b'.
1170 */
1171 i = 0;
1172 do
1173 {
1174 a->words[i] &= ~b->words[i];
1175 } while (++i < b->nwords);
1176 }
1177 else
1178 {
1179 int lastnonzero = -1;
1180
1181 /* we may need to remove trailing zero words from the result. */
1182 i = 0;
1183 do
1184 {
1185 a->words[i] &= ~b->words[i];
1186
1187 /* remember the last non-zero word */
1188 if (a->words[i] != 0)
1189 lastnonzero = i;
1190 } while (++i < a->nwords);
1191
1192 /* check if 'a' has become empty */
1193 if (lastnonzero == -1)
1194 {
1195 pfree(a);
1196 return NULL;
1197 }
1198
1199 /* trim off any trailing zero words */
1200 a->nwords = lastnonzero + 1;
1201 }
1202
1203#ifdef REALLOCATE_BITMAPSETS
1205#endif
1206
1207 return a;
1208}
1209
1210/*
1211 * bms_join - like bms_union, but *either* input *may* be recycled
1212 */
1213Bitmapset *
1215{
1216 Bitmapset *result;
1218 int otherlen;
1219 int i;
1220
1223
1224 /* Handle cases where either input is NULL */
1225 if (a == NULL)
1226 {
1227#ifdef REALLOCATE_BITMAPSETS
1229#endif
1230
1231 return b;
1232 }
1233 if (b == NULL)
1234 {
1235#ifdef REALLOCATE_BITMAPSETS
1237#endif
1238
1239 return a;
1240 }
1241
1242 /* Identify shorter and longer input; use longer one as result */
1243 if (a->nwords < b->nwords)
1244 {
1245 result = b;
1246 other = a;
1247 }
1248 else
1249 {
1250 result = a;
1251 other = b;
1252 }
1253 /* And union the shorter input into the result */
1255 i = 0;
1256 do
1257 {
1258 result->words[i] |= other->words[i];
1259 } while (++i < otherlen);
1260 if (other != result) /* pure paranoia */
1261 pfree(other);
1262
1263#ifdef REALLOCATE_BITMAPSETS
1264 result = bms_copy_and_free(result);
1265#endif
1266
1267 return result;
1268}
1269
1270/*
1271 * bms_next_member - find next member of a set
1272 *
1273 * Returns smallest member greater than "prevbit", or -2 if there is none.
1274 * "prevbit" must NOT be less than -1, or the behavior is unpredictable.
1275 *
1276 * This is intended as support for iterating through the members of a set.
1277 * The typical pattern is
1278 *
1279 * x = -1;
1280 * while ((x = bms_next_member(inputset, x)) >= 0)
1281 * process member x;
1282 *
1283 * Notice that when there are no more members, we return -2, not -1 as you
1284 * might expect. The rationale for that is to allow distinguishing the
1285 * loop-not-started state (x == -1) from the loop-completed state (x == -2).
1286 * It makes no difference in simple loop usage, but complex iteration logic
1287 * might need such an ability.
1288 */
1289int
1291{
1292 int nwords;
1293 bitmapword mask;
1294
1296
1297 if (a == NULL)
1298 return -2;
1299 nwords = a->nwords;
1300 prevbit++;
1301 mask = (~(bitmapword) 0) << BITNUM(prevbit);
1302 for (int wordnum = WORDNUM(prevbit); wordnum < nwords; wordnum++)
1303 {
1304 bitmapword w = a->words[wordnum];
1305
1306 /* ignore bits before prevbit */
1307 w &= mask;
1308
1309 if (w != 0)
1310 {
1311 int result;
1312
1313 result = wordnum * BITS_PER_BITMAPWORD;
1314 result += bmw_rightmost_one_pos(w);
1315 return result;
1316 }
1317
1318 /* in subsequent words, consider all bits */
1319 mask = (~(bitmapword) 0);
1320 }
1321 return -2;
1322}
1323
1324/*
1325 * bms_prev_member - find prev member of a set
1326 *
1327 * Returns largest member less than "prevbit", or -2 if there is none.
1328 * "prevbit" must NOT be more than one above the highest possible bit that can
1329 * be set in the Bitmapset at its current size.
1330 *
1331 * To ease finding the highest set bit for the initial loop, the special
1332 * prevbit value of -1 can be passed to have the function find the highest
1333 * valued member in the set.
1334 *
1335 * This is intended as support for iterating through the members of a set in
1336 * reverse. The typical pattern is
1337 *
1338 * x = -1;
1339 * while ((x = bms_prev_member(inputset, x)) >= 0)
1340 * process member x;
1341 *
1342 * Notice that when there are no more members, we return -2, not -1 as you
1343 * might expect. The rationale for that is to allow distinguishing the
1344 * loop-not-started state (x == -1) from the loop-completed state (x == -2).
1345 * It makes no difference in simple loop usage, but complex iteration logic
1346 * might need such an ability.
1347 */
1348
1349int
1351{
1352 int ushiftbits;
1353 bitmapword mask;
1354
1356
1357 /*
1358 * If set is NULL or if there are no more bits to the right then we've
1359 * nothing to do.
1360 */
1361 if (a == NULL || prevbit == 0)
1362 return -2;
1363
1364 /* Validate callers didn't give us something out of range */
1366 Assert(prevbit >= -1);
1367
1368 /* transform -1 to the highest possible bit we could have set */
1369 if (prevbit == -1)
1370 prevbit = a->nwords * BITS_PER_BITMAPWORD - 1;
1371 else
1372 prevbit--;
1373
1375 mask = (~(bitmapword) 0) >> ushiftbits;
1376 for (int wordnum = WORDNUM(prevbit); wordnum >= 0; wordnum--)
1377 {
1378 bitmapword w = a->words[wordnum];
1379
1380 /* mask out bits left of prevbit */
1381 w &= mask;
1382
1383 if (w != 0)
1384 {
1385 int result;
1386
1387 result = wordnum * BITS_PER_BITMAPWORD;
1388 result += bmw_leftmost_one_pos(w);
1389 return result;
1390 }
1391
1392 /* in subsequent words, consider all bits */
1393 mask = (~(bitmapword) 0);
1394 }
1395 return -2;
1396}
1397
1398/*
1399 * bms_hash_value - compute a hash key for a Bitmapset
1400 */
1401uint32
1403{
1405
1406 if (a == NULL)
1407 return 0; /* All empty sets hash to 0 */
1408 return DatumGetUInt32(hash_any((const unsigned char *) a->words,
1409 a->nwords * sizeof(bitmapword)));
1410}
1411
1412/*
1413 * bitmap_hash - hash function for keys that are (pointers to) Bitmapsets
1414 *
1415 * Note: don't forget to specify bitmap_match as the match function!
1416 */
1417uint32
1418bitmap_hash(const void *key, Size keysize)
1419{
1420 Assert(keysize == sizeof(Bitmapset *));
1421 return bms_hash_value(*((const Bitmapset *const *) key));
1422}
1423
1424/*
1425 * bitmap_match - match function to use with bitmap_hash
1426 */
1427int
1428bitmap_match(const void *key1, const void *key2, Size keysize)
1429{
1430 Assert(keysize == sizeof(Bitmapset *));
1431 return !bms_equal(*((const Bitmapset *const *) key1),
1432 *((const Bitmapset *const *) key2));
1433}
#define BITMAPSET_SIZE(nwords)
Definition bitmapset.c:50
Bitmapset * bms_replace_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:956
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:346
int bms_prev_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1350
Bitmapset * bms_make_singleton(int x)
Definition bitmapset.c:216
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1093
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:292
uint32 bitmap_hash(const void *key, Size keysize)
Definition bitmapset.c:1418
#define WORDNUM(x)
Definition bitmapset.c:47
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:142
BMS_Comparison bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:445
int bms_next_member(const Bitmapset *a, int prevbit)
Definition bitmapset.c:1290
uint32 bms_hash_value(const Bitmapset *a)
Definition bitmapset.c:1402
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:1145
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
Definition bitmapset.c:1003
Bitmapset * bms_del_member(Bitmapset *a, int x)
Definition bitmapset.c:852
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:412
int bms_singleton_member(const Bitmapset *a)
Definition bitmapset.c:665
void bms_free(Bitmapset *a)
Definition bitmapset.c:239
int bms_num_members(const Bitmapset *a)
Definition bitmapset.c:744
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:901
#define BITNUM(x)
Definition bitmapset.c:48
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:251
#define HAS_MULTIPLE_ONES(x)
Definition bitmapset.c:72
int bitmap_match(const void *key1, const void *key2, Size keysize)
Definition bitmapset.c:1428
BMS_Membership bms_membership(const Bitmapset *a)
Definition bitmapset.c:765
int bms_member_index(Bitmapset *a, int x)
Definition bitmapset.c:539
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:575
int bms_compare(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:183
bool bms_get_singleton_member(const Bitmapset *a, int *member)
Definition bitmapset.c:708
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition bitmapset.c:1214
bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:634
Bitmapset * bms_copy(const Bitmapset *a)
Definition bitmapset.c:122
bool bms_overlap_list(const Bitmapset *a, const List *b)
Definition bitmapset.c:601
#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:1019
#define Assert(condition)
Definition c.h:885
#define unlikely(x)
Definition c.h:424
uint32_t uint32
Definition c.h:558
size_t Size
Definition c.h:631
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
static Datum hash_any(const unsigned char *k, int keylen)
Definition hashfn.h:31
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:1632
void pfree(void *pointer)
Definition mcxt.c:1616
void * palloc0(Size size)
Definition mcxt.c:1417
void * palloc(Size size)
Definition mcxt.c:1387
#define IsA(nodeptr, _type_)
Definition nodes.h:164
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:232
char * c
static int fb(int x)
int nwords
Definition bitmapset.h:54
bitmapword words[FLEXIBLE_ARRAY_MEMBER]
Definition bitmapset.h:55
Definition pg_list.h:54