LCOV - code coverage report
Current view: top level - src/backend/nodes - bitmapset.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 445 446 99.8 %
Date: 2025-12-25 04:18:33 Functions: 32 32 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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-2025, 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             :  */
      78             : static bool
      79             : bms_is_valid_set(const Bitmapset *a)
      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             :  */
     108             : static Bitmapset *
     109             : bms_copy_and_free(Bitmapset *a)
     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             :  */
     121             : Bitmapset *
     122    56411908 : bms_copy(const Bitmapset *a)
     123             : {
     124             :     Bitmapset  *result;
     125             :     size_t      size;
     126             : 
     127             :     Assert(bms_is_valid_set(a));
     128             : 
     129    56411908 :     if (a == NULL)
     130    36873002 :         return NULL;
     131             : 
     132    19538906 :     size = BITMAPSET_SIZE(a->nwords);
     133    19538906 :     result = (Bitmapset *) palloc(size);
     134    19538906 :     memcpy(result, a, size);
     135    19538906 :     return result;
     136             : }
     137             : 
     138             : /*
     139             :  * bms_equal - are two bitmapsets equal? or both NULL?
     140             :  */
     141             : bool
     142    18926578 : bms_equal(const Bitmapset *a, const Bitmapset *b)
     143             : {
     144             :     int         i;
     145             : 
     146             :     Assert(bms_is_valid_set(a));
     147             :     Assert(bms_is_valid_set(b));
     148             : 
     149             :     /* Handle cases where either input is NULL */
     150    18926578 :     if (a == NULL)
     151             :     {
     152    12907248 :         if (b == NULL)
     153    12837616 :             return true;
     154       69632 :         return false;
     155             :     }
     156     6019330 :     else if (b == NULL)
     157       22228 :         return false;
     158             : 
     159             :     /* can't be equal if the word counts don't match */
     160     5997102 :     if (a->nwords != b->nwords)
     161           4 :         return false;
     162             : 
     163             :     /* check each word matches */
     164     5997098 :     i = 0;
     165             :     do
     166             :     {
     167     5997302 :         if (a->words[i] != b->words[i])
     168     2979706 :             return false;
     169     3017596 :     } while (++i < a->nwords);
     170             : 
     171     3017392 :     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             :  */
     182             : int
     183       26226 : bms_compare(const Bitmapset *a, const Bitmapset *b)
     184             : {
     185             :     int         i;
     186             : 
     187             :     Assert(bms_is_valid_set(a));
     188             :     Assert(bms_is_valid_set(b));
     189             : 
     190             :     /* Handle cases where either input is NULL */
     191       26226 :     if (a == NULL)
     192           8 :         return (b == NULL) ? 0 : -1;
     193       26218 :     else if (b == NULL)
     194           4 :         return +1;
     195             : 
     196             :     /* the set with the most words must be greater */
     197       26214 :     if (a->nwords != b->nwords)
     198           2 :         return (a->nwords > b->nwords) ? +1 : -1;
     199             : 
     200       26212 :     i = a->nwords - 1;
     201             :     do
     202             :     {
     203       26212 :         bitmapword  aw = a->words[i];
     204       26212 :         bitmapword  bw = b->words[i];
     205             : 
     206       26212 :         if (aw != bw)
     207       26210 :             return (aw > bw) ? +1 : -1;
     208           2 :     } while (--i >= 0);
     209           2 :     return 0;
     210             : }
     211             : 
     212             : /*
     213             :  * bms_make_singleton - build a bitmapset containing a single member
     214             :  */
     215             : Bitmapset *
     216    16111338 : bms_make_singleton(int x)
     217             : {
     218             :     Bitmapset  *result;
     219             :     int         wordnum,
     220             :                 bitnum;
     221             : 
     222    16111338 :     if (x < 0)
     223           2 :         elog(ERROR, "negative bitmapset member not allowed");
     224    16111336 :     wordnum = WORDNUM(x);
     225    16111336 :     bitnum = BITNUM(x);
     226    16111336 :     result = (Bitmapset *) palloc0(BITMAPSET_SIZE(wordnum + 1));
     227    16111336 :     result->type = T_Bitmapset;
     228    16111336 :     result->nwords = wordnum + 1;
     229    16111336 :     result->words[wordnum] = ((bitmapword) 1 << bitnum);
     230    16111336 :     return result;
     231             : }
     232             : 
     233             : /*
     234             :  * bms_free - free a bitmapset
     235             :  *
     236             :  * Same as pfree except for allowing NULL input
     237             :  */
     238             : void
     239    22066166 : bms_free(Bitmapset *a)
     240             : {
     241    22066166 :     if (a)
     242     9660846 :         pfree(a);
     243    22066166 : }
     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             :  */
     250             : Bitmapset *
     251     8754548 : bms_union(const Bitmapset *a, const Bitmapset *b)
     252             : {
     253             :     Bitmapset  *result;
     254             :     const Bitmapset *other;
     255             :     int         otherlen;
     256             :     int         i;
     257             : 
     258             :     Assert(bms_is_valid_set(a));
     259             :     Assert(bms_is_valid_set(b));
     260             : 
     261             :     /* Handle cases where either input is NULL */
     262     8754548 :     if (a == NULL)
     263     5585646 :         return bms_copy(b);
     264     3168902 :     if (b == NULL)
     265     1366400 :         return bms_copy(a);
     266             :     /* Identify shorter and longer input; copy the longer one */
     267     1802502 :     if (a->nwords <= b->nwords)
     268             :     {
     269     1802498 :         result = bms_copy(b);
     270     1802498 :         other = a;
     271             :     }
     272             :     else
     273             :     {
     274           4 :         result = bms_copy(a);
     275           4 :         other = b;
     276             :     }
     277             :     /* And union the shorter input into the result */
     278     1802502 :     otherlen = other->nwords;
     279     1802502 :     i = 0;
     280             :     do
     281             :     {
     282     1805058 :         result->words[i] |= other->words[i];
     283     1805058 :     } while (++i < otherlen);
     284     1802502 :     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             :  */
     291             : Bitmapset *
     292     1326586 : bms_intersect(const Bitmapset *a, const Bitmapset *b)
     293             : {
     294             :     Bitmapset  *result;
     295             :     const Bitmapset *other;
     296             :     int         lastnonzero;
     297             :     int         resultlen;
     298             :     int         i;
     299             : 
     300             :     Assert(bms_is_valid_set(a));
     301             :     Assert(bms_is_valid_set(b));
     302             : 
     303             :     /* Handle cases where either input is NULL */
     304     1326586 :     if (a == NULL || b == NULL)
     305      223692 :         return NULL;
     306             : 
     307             :     /* Identify shorter and longer input; copy the shorter one */
     308     1102894 :     if (a->nwords <= b->nwords)
     309             :     {
     310     1102890 :         result = bms_copy(a);
     311     1102890 :         other = b;
     312             :     }
     313             :     else
     314             :     {
     315           4 :         result = bms_copy(b);
     316           4 :         other = a;
     317             :     }
     318             :     /* And intersect the longer input with the result */
     319     1102894 :     resultlen = result->nwords;
     320     1102894 :     lastnonzero = -1;
     321     1102894 :     i = 0;
     322             :     do
     323             :     {
     324     1105450 :         result->words[i] &= other->words[i];
     325             : 
     326     1105450 :         if (result->words[i] != 0)
     327     1094576 :             lastnonzero = i;
     328     1105450 :     } while (++i < resultlen);
     329             :     /* If we computed an empty result, we must return NULL */
     330     1102894 :     if (lastnonzero == -1)
     331             :     {
     332        8596 :         pfree(result);
     333        8596 :         return NULL;
     334             :     }
     335             : 
     336             :     /* get rid of trailing zero words */
     337     1094298 :     result->nwords = lastnonzero + 1;
     338     1094298 :     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             :  */
     345             : Bitmapset *
     346     2316620 : bms_difference(const Bitmapset *a, const Bitmapset *b)
     347             : {
     348             :     Bitmapset  *result;
     349             :     int         i;
     350             : 
     351             :     Assert(bms_is_valid_set(a));
     352             :     Assert(bms_is_valid_set(b));
     353             : 
     354             :     /* Handle cases where either input is NULL */
     355     2316620 :     if (a == NULL)
     356      626552 :         return NULL;
     357     1690068 :     if (b == NULL)
     358     1223704 :         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             :      */
     365      466364 :     if (!bms_nonempty_difference(a, b))
     366      140232 :         return NULL;
     367             : 
     368             :     /* Copy the left input */
     369      326132 :     result = bms_copy(a);
     370             : 
     371             :     /* And remove b's bits from result */
     372      326132 :     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           4 :         i = 0;
     379             :         do
     380             :         {
     381           4 :             result->words[i] &= ~b->words[i];
     382           4 :         } while (++i < b->nwords);
     383             :     }
     384             :     else
     385             :     {
     386      326128 :         int         lastnonzero = -1;
     387             : 
     388             :         /* we may need to remove trailing zero words from the result. */
     389      326128 :         i = 0;
     390             :         do
     391             :         {
     392      326130 :             result->words[i] &= ~b->words[i];
     393             : 
     394             :             /* remember the last non-zero word */
     395      326130 :             if (result->words[i] != 0)
     396      326128 :                 lastnonzero = i;
     397      326130 :         } while (++i < result->nwords);
     398             : 
     399             :         /* trim off trailing zero words */
     400      326128 :         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      326132 :     return result;
     406             : }
     407             : 
     408             : /*
     409             :  * bms_is_subset - is A a subset of B?
     410             :  */
     411             : bool
     412    21576702 : bms_is_subset(const Bitmapset *a, const Bitmapset *b)
     413             : {
     414             :     int         i;
     415             : 
     416             :     Assert(bms_is_valid_set(a));
     417             :     Assert(bms_is_valid_set(b));
     418             : 
     419             :     /* Handle cases where either input is NULL */
     420    21576702 :     if (a == NULL)
     421     2007576 :         return true;            /* empty set is a subset of anything */
     422    19569126 :     if (b == NULL)
     423      422912 :         return false;
     424             : 
     425             :     /* 'a' can't be a subset of 'b' if it contains more words */
     426    19146214 :     if (a->nwords > b->nwords)
     427           4 :         return false;
     428             : 
     429             :     /* Check all 'a' members are set in 'b' */
     430    19146210 :     i = 0;
     431             :     do
     432             :     {
     433    19146210 :         if ((a->words[i] & ~b->words[i]) != 0)
     434     7390372 :             return false;
     435    11755838 :     } while (++i < a->nwords);
     436    11755838 :     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             :  */
     444             : BMS_Comparison
     445     2771990 : bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
     446             : {
     447             :     BMS_Comparison result;
     448             :     int         shortlen;
     449             :     int         i;
     450             : 
     451             :     Assert(bms_is_valid_set(a));
     452             :     Assert(bms_is_valid_set(b));
     453             : 
     454             :     /* Handle cases where either input is NULL */
     455     2771990 :     if (a == NULL)
     456             :     {
     457     2347746 :         if (b == NULL)
     458     2276178 :             return BMS_EQUAL;
     459       71568 :         return BMS_SUBSET1;
     460             :     }
     461      424244 :     if (b == NULL)
     462      203102 :         return BMS_SUBSET2;
     463             : 
     464             :     /* Check common words */
     465      221142 :     result = BMS_EQUAL;         /* status so far */
     466      221142 :     shortlen = Min(a->nwords, b->nwords);
     467      221142 :     i = 0;
     468             :     do
     469             :     {
     470      221148 :         bitmapword  aword = a->words[i];
     471      221148 :         bitmapword  bword = b->words[i];
     472             : 
     473      221148 :         if ((aword & ~bword) != 0)
     474             :         {
     475             :             /* a is not a subset of b */
     476       59226 :             if (result == BMS_SUBSET1)
     477           4 :                 return BMS_DIFFERENT;
     478       59222 :             result = BMS_SUBSET2;
     479             :         }
     480      221144 :         if ((bword & ~aword) != 0)
     481             :         {
     482             :             /* b is not a subset of a */
     483       59594 :             if (result == BMS_SUBSET2)
     484       55242 :                 return BMS_DIFFERENT;
     485        4352 :             result = BMS_SUBSET1;
     486             :         }
     487      165902 :     } while (++i < shortlen);
     488             :     /* Check extra words */
     489      165896 :     if (a->nwords > b->nwords)
     490             :     {
     491             :         /* if a has more words then a is not a subset of b */
     492           4 :         if (result == BMS_SUBSET1)
     493           2 :             return BMS_DIFFERENT;
     494           2 :         return BMS_SUBSET2;
     495             :     }
     496      165892 :     else if (a->nwords < b->nwords)
     497             :     {
     498             :         /* if b has more words then b is not a subset of a */
     499           8 :         if (result == BMS_SUBSET2)
     500           4 :             return BMS_DIFFERENT;
     501           4 :         return BMS_SUBSET1;
     502             :     }
     503      165884 :     return result;
     504             : }
     505             : 
     506             : /*
     507             :  * bms_is_member - is X a member of A?
     508             :  */
     509             : bool
     510    16649094 : bms_is_member(int x, const Bitmapset *a)
     511             : {
     512             :     int         wordnum,
     513             :                 bitnum;
     514             : 
     515             :     Assert(bms_is_valid_set(a));
     516             : 
     517             :     /* XXX better to just return false for x<0 ? */
     518    16649094 :     if (x < 0)
     519           2 :         elog(ERROR, "negative bitmapset member not allowed");
     520    16649092 :     if (a == NULL)
     521     9416628 :         return false;
     522             : 
     523     7232464 :     wordnum = WORDNUM(x);
     524     7232464 :     bitnum = BITNUM(x);
     525     7232464 :     if (wordnum >= a->nwords)
     526         618 :         return false;
     527     7231846 :     if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
     528     5193488 :         return true;
     529     2038358 :     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             :  */
     538             : int
     539        5318 : bms_member_index(Bitmapset *a, int x)
     540             : {
     541             :     int         bitnum;
     542             :     int         wordnum;
     543        5318 :     int         result = 0;
     544             :     bitmapword  mask;
     545             : 
     546             :     Assert(bms_is_valid_set(a));
     547             : 
     548             :     /* return -1 if not a member of the bitmap */
     549        5318 :     if (!bms_is_member(x, a))
     550           4 :         return -1;
     551             : 
     552        5314 :     wordnum = WORDNUM(x);
     553        5314 :     bitnum = BITNUM(x);
     554             : 
     555             :     /* count bits in preceding words */
     556        5328 :     for (int i = 0; i < wordnum; i++)
     557             :     {
     558          14 :         bitmapword  w = a->words[i];
     559             : 
     560             :         /* No need to count the bits in a zero word */
     561          14 :         if (w != 0)
     562           6 :             result += bmw_popcount(w);
     563             :     }
     564             : 
     565             :     /*
     566             :      * Now add bits of the last word, but only those before the item. We can
     567             :      * do that by applying a mask and then using popcount again. To get
     568             :      * 0-based index, we want to count only preceding bits, not the item
     569             :      * itself, so we subtract 1.
     570             :      */
     571        5314 :     mask = ((bitmapword) 1 << bitnum) - 1;
     572        5314 :     result += bmw_popcount(a->words[wordnum] & mask);
     573             : 
     574        5314 :     return result;
     575             : }
     576             : 
     577             : /*
     578             :  * bms_overlap - do sets overlap (ie, have a nonempty intersection)?
     579             :  */
     580             : bool
     581    14746622 : bms_overlap(const Bitmapset *a, const Bitmapset *b)
     582             : {
     583             :     int         shortlen;
     584             :     int         i;
     585             : 
     586             :     Assert(bms_is_valid_set(a));
     587             :     Assert(bms_is_valid_set(b));
     588             : 
     589             :     /* Handle cases where either input is NULL */
     590    14746622 :     if (a == NULL || b == NULL)
     591     6275044 :         return false;
     592             :     /* Check words in common */
     593     8471578 :     shortlen = Min(a->nwords, b->nwords);
     594     8471578 :     i = 0;
     595             :     do
     596             :     {
     597     8471578 :         if ((a->words[i] & b->words[i]) != 0)
     598     5454398 :             return true;
     599     3017180 :     } while (++i < shortlen);
     600     3017180 :     return false;
     601             : }
     602             : 
     603             : /*
     604             :  * bms_overlap_list - does a set overlap an integer list?
     605             :  */
     606             : bool
     607        1646 : bms_overlap_list(const Bitmapset *a, const List *b)
     608             : {
     609             :     ListCell   *lc;
     610             :     int         wordnum,
     611             :                 bitnum;
     612             : 
     613             :     Assert(bms_is_valid_set(a));
     614             : 
     615        1646 :     if (a == NULL || b == NIL)
     616        1494 :         return false;
     617             : 
     618         284 :     foreach(lc, b)
     619             :     {
     620         222 :         int         x = lfirst_int(lc);
     621             : 
     622         222 :         if (x < 0)
     623           4 :             elog(ERROR, "negative bitmapset member not allowed");
     624         218 :         wordnum = WORDNUM(x);
     625         218 :         bitnum = BITNUM(x);
     626         218 :         if (wordnum < a->nwords)
     627         218 :             if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
     628          86 :                 return true;
     629             :     }
     630             : 
     631          62 :     return false;
     632             : }
     633             : 
     634             : /*
     635             :  * bms_nonempty_difference - do sets have a nonempty difference?
     636             :  *
     637             :  * i.e., are any members set in 'a' that are not also set in 'b'.
     638             :  */
     639             : bool
     640     3067464 : bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
     641             : {
     642             :     int         i;
     643             : 
     644             :     Assert(bms_is_valid_set(a));
     645             :     Assert(bms_is_valid_set(b));
     646             : 
     647             :     /* Handle cases where either input is NULL */
     648     3067464 :     if (a == NULL)
     649        5728 :         return false;
     650     3061736 :     if (b == NULL)
     651           2 :         return true;
     652             :     /* if 'a' has more words then it must contain additional members */
     653     3061734 :     if (a->nwords > b->nwords)
     654           6 :         return true;
     655             :     /* Check all 'a' members are set in 'b' */
     656     3061728 :     i = 0;
     657             :     do
     658             :     {
     659     3061728 :         if ((a->words[i] & ~b->words[i]) != 0)
     660     1766118 :             return true;
     661     1295610 :     } while (++i < a->nwords);
     662     1295610 :     return false;
     663             : }
     664             : 
     665             : /*
     666             :  * bms_singleton_member - return the sole integer member of set
     667             :  *
     668             :  * Raises error if |a| is not 1.
     669             :  */
     670             : int
     671       22456 : bms_singleton_member(const Bitmapset *a)
     672             : {
     673       22456 :     int         result = -1;
     674             :     int         nwords;
     675             :     int         wordnum;
     676             : 
     677             :     Assert(bms_is_valid_set(a));
     678             : 
     679       22456 :     if (a == NULL)
     680           2 :         elog(ERROR, "bitmapset is empty");
     681             : 
     682       22454 :     nwords = a->nwords;
     683       22454 :     wordnum = 0;
     684             :     do
     685             :     {
     686       22454 :         bitmapword  w = a->words[wordnum];
     687             : 
     688       22454 :         if (w != 0)
     689             :         {
     690       22454 :             if (result >= 0 || HAS_MULTIPLE_ONES(w))
     691           2 :                 elog(ERROR, "bitmapset has multiple members");
     692       22452 :             result = wordnum * BITS_PER_BITMAPWORD;
     693       22452 :             result += bmw_rightmost_one_pos(w);
     694             :         }
     695       22452 :     } while (++wordnum < nwords);
     696             : 
     697             :     /* we don't expect non-NULL sets to be empty */
     698             :     Assert(result >= 0);
     699       22452 :     return result;
     700             : }
     701             : 
     702             : /*
     703             :  * bms_get_singleton_member
     704             :  *
     705             :  * Test whether the given set is a singleton.
     706             :  * If so, set *member to the value of its sole member, and return true.
     707             :  * If not, return false, without changing *member.
     708             :  *
     709             :  * This is more convenient and faster than calling bms_membership() and then
     710             :  * bms_singleton_member(), if we don't care about distinguishing empty sets
     711             :  * from multiple-member sets.
     712             :  */
     713             : bool
     714     2628058 : bms_get_singleton_member(const Bitmapset *a, int *member)
     715             : {
     716     2628058 :     int         result = -1;
     717             :     int         nwords;
     718             :     int         wordnum;
     719             : 
     720             :     Assert(bms_is_valid_set(a));
     721             : 
     722     2628058 :     if (a == NULL)
     723           4 :         return false;
     724             : 
     725     2628054 :     nwords = a->nwords;
     726     2628054 :     wordnum = 0;
     727             :     do
     728             :     {
     729     2628066 :         bitmapword  w = a->words[wordnum];
     730             : 
     731     2628066 :         if (w != 0)
     732             :         {
     733     2628054 :             if (result >= 0 || HAS_MULTIPLE_ONES(w))
     734      468840 :                 return false;
     735     2159214 :             result = wordnum * BITS_PER_BITMAPWORD;
     736     2159214 :             result += bmw_rightmost_one_pos(w);
     737             :         }
     738     2159226 :     } while (++wordnum < nwords);
     739             : 
     740             :     /* we don't expect non-NULL sets to be empty */
     741             :     Assert(result >= 0);
     742     2159214 :     *member = result;
     743     2159214 :     return true;
     744             : }
     745             : 
     746             : /*
     747             :  * bms_num_members - count members of set
     748             :  */
     749             : int
     750     1972424 : bms_num_members(const Bitmapset *a)
     751             : {
     752     1972424 :     int         result = 0;
     753             :     int         nwords;
     754             :     int         wordnum;
     755             : 
     756             :     Assert(bms_is_valid_set(a));
     757             : 
     758     1972424 :     if (a == NULL)
     759      211572 :         return 0;
     760             : 
     761     1760852 :     nwords = a->nwords;
     762     1760852 :     wordnum = 0;
     763             :     do
     764             :     {
     765     1760854 :         bitmapword  w = a->words[wordnum];
     766             : 
     767             :         /* No need to count the bits in a zero word */
     768     1760854 :         if (w != 0)
     769     1760854 :             result += bmw_popcount(w);
     770     1760854 :     } while (++wordnum < nwords);
     771     1760852 :     return result;
     772             : }
     773             : 
     774             : /*
     775             :  * bms_membership - does a set have zero, one, or multiple members?
     776             :  *
     777             :  * This is faster than making an exact count with bms_num_members().
     778             :  */
     779             : BMS_Membership
     780     1365218 : bms_membership(const Bitmapset *a)
     781             : {
     782     1365218 :     BMS_Membership result = BMS_EMPTY_SET;
     783             :     int         nwords;
     784             :     int         wordnum;
     785             : 
     786             :     Assert(bms_is_valid_set(a));
     787             : 
     788     1365218 :     if (a == NULL)
     789         486 :         return BMS_EMPTY_SET;
     790             : 
     791     1364732 :     nwords = a->nwords;
     792     1364732 :     wordnum = 0;
     793             :     do
     794             :     {
     795     1364732 :         bitmapword  w = a->words[wordnum];
     796             : 
     797     1364732 :         if (w != 0)
     798             :         {
     799     1364732 :             if (result != BMS_EMPTY_SET || HAS_MULTIPLE_ONES(w))
     800      483978 :                 return BMS_MULTIPLE;
     801      880754 :             result = BMS_SINGLETON;
     802             :         }
     803      880754 :     } while (++wordnum < nwords);
     804      880754 :     return result;
     805             : }
     806             : 
     807             : 
     808             : /*
     809             :  * bms_add_member - add a specified member to set
     810             :  *
     811             :  * 'a' is recycled when possible.
     812             :  */
     813             : Bitmapset *
     814    22621366 : bms_add_member(Bitmapset *a, int x)
     815             : {
     816             :     int         wordnum,
     817             :                 bitnum;
     818             : 
     819             :     Assert(bms_is_valid_set(a));
     820             : 
     821    22621366 :     if (x < 0)
     822           4 :         elog(ERROR, "negative bitmapset member not allowed");
     823    22621362 :     if (a == NULL)
     824    11792912 :         return bms_make_singleton(x);
     825             : 
     826    10828450 :     wordnum = WORDNUM(x);
     827    10828450 :     bitnum = BITNUM(x);
     828             : 
     829             :     /* enlarge the set if necessary */
     830    10828450 :     if (wordnum >= a->nwords)
     831             :     {
     832         710 :         int         oldnwords = a->nwords;
     833             :         int         i;
     834             : 
     835         710 :         a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(wordnum + 1));
     836         710 :         a->nwords = wordnum + 1;
     837             :         /* zero out the enlarged portion */
     838         710 :         i = oldnwords;
     839             :         do
     840             :         {
     841       77346 :             a->words[i] = 0;
     842       77346 :         } while (++i < a->nwords);
     843             :     }
     844             : 
     845    10828450 :     a->words[wordnum] |= ((bitmapword) 1 << bitnum);
     846             : 
     847             : #ifdef REALLOCATE_BITMAPSETS
     848             : 
     849             :     /*
     850             :      * There's no guarantee that the repalloc returned a new pointer, so copy
     851             :      * and free unconditionally here.
     852             :      */
     853             :     a = bms_copy_and_free(a);
     854             : #endif
     855             : 
     856    10828450 :     return a;
     857             : }
     858             : 
     859             : /*
     860             :  * bms_del_member - remove a specified member from set
     861             :  *
     862             :  * No error if x is not currently a member of set
     863             :  *
     864             :  * 'a' is recycled when possible.
     865             :  */
     866             : Bitmapset *
     867     1804284 : bms_del_member(Bitmapset *a, int x)
     868             : {
     869             :     int         wordnum,
     870             :                 bitnum;
     871             : 
     872             :     Assert(bms_is_valid_set(a));
     873             : 
     874     1804284 :     if (x < 0)
     875           2 :         elog(ERROR, "negative bitmapset member not allowed");
     876     1804282 :     if (a == NULL)
     877      651220 :         return NULL;
     878             : 
     879     1153062 :     wordnum = WORDNUM(x);
     880     1153062 :     bitnum = BITNUM(x);
     881             : 
     882             : #ifdef REALLOCATE_BITMAPSETS
     883             :     a = bms_copy_and_free(a);
     884             : #endif
     885             : 
     886             :     /* member can't exist.  Return 'a' unmodified */
     887     1153062 :     if (unlikely(wordnum >= a->nwords))
     888           0 :         return a;
     889             : 
     890     1153062 :     a->words[wordnum] &= ~((bitmapword) 1 << bitnum);
     891             : 
     892             :     /* when last word becomes empty, trim off all trailing empty words */
     893     1153062 :     if (a->words[wordnum] == 0 && wordnum == a->nwords - 1)
     894             :     {
     895             :         /* find the last non-empty word and make that the new final word */
     896      748408 :         for (int i = wordnum - 1; i >= 0; i--)
     897             :         {
     898      167046 :             if (a->words[i] != 0)
     899             :             {
     900         368 :                 a->nwords = i + 1;
     901         368 :                 return a;
     902             :             }
     903             :         }
     904             : 
     905             :         /* the set is now empty */
     906      581362 :         pfree(a);
     907      581362 :         return NULL;
     908             :     }
     909      571332 :     return a;
     910             : }
     911             : 
     912             : /*
     913             :  * bms_add_members - like bms_union, but left input is recycled when possible
     914             :  */
     915             : Bitmapset *
     916    15465268 : bms_add_members(Bitmapset *a, const Bitmapset *b)
     917             : {
     918             :     Bitmapset  *result;
     919             :     const Bitmapset *other;
     920             :     int         otherlen;
     921             :     int         i;
     922             : 
     923             :     Assert(bms_is_valid_set(a));
     924             :     Assert(bms_is_valid_set(b));
     925             : 
     926             :     /* Handle cases where either input is NULL */
     927    15465268 :     if (a == NULL)
     928     8089884 :         return bms_copy(b);
     929     7375384 :     if (b == NULL)
     930             :     {
     931             : #ifdef REALLOCATE_BITMAPSETS
     932             :         a = bms_copy_and_free(a);
     933             : #endif
     934             : 
     935     4768162 :         return a;
     936             :     }
     937             :     /* Identify shorter and longer input; copy the longer one if needed */
     938     2607222 :     if (a->nwords < b->nwords)
     939             :     {
     940           2 :         result = bms_copy(b);
     941           2 :         other = a;
     942             :     }
     943             :     else
     944             :     {
     945     2607220 :         result = a;
     946     2607220 :         other = b;
     947             :     }
     948             :     /* And union the shorter input into the result */
     949     2607222 :     otherlen = other->nwords;
     950     2607222 :     i = 0;
     951             :     do
     952             :     {
     953     2607222 :         result->words[i] |= other->words[i];
     954     2607222 :     } while (++i < otherlen);
     955     2607222 :     if (result != a)
     956           2 :         pfree(a);
     957             : #ifdef REALLOCATE_BITMAPSETS
     958             :     else
     959             :         result = bms_copy_and_free(result);
     960             : #endif
     961             : 
     962     2607222 :     return result;
     963             : }
     964             : 
     965             : /*
     966             :  * bms_replace_members
     967             :  *      Remove all existing members from 'a' and repopulate the set with members
     968             :  *      from 'b', recycling 'a', when possible.
     969             :  */
     970             : Bitmapset *
     971       13494 : bms_replace_members(Bitmapset *a, const Bitmapset *b)
     972             : {
     973             :     int         i;
     974             : 
     975             :     Assert(bms_is_valid_set(a));
     976             :     Assert(bms_is_valid_set(b));
     977             : 
     978       13494 :     if (a == NULL)
     979           2 :         return bms_copy(b);
     980       13492 :     if (b == NULL)
     981             :     {
     982           2 :         pfree(a);
     983           2 :         return NULL;
     984             :     }
     985             : 
     986       13490 :     if (a->nwords < b->nwords)
     987           2 :         a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(b->nwords));
     988             : 
     989       13490 :     i = 0;
     990             :     do
     991             :     {
     992       13508 :         a->words[i] = b->words[i];
     993       13508 :     } while (++i < b->nwords);
     994             : 
     995       13490 :     a->nwords = b->nwords;
     996             : 
     997             : #ifdef REALLOCATE_BITMAPSETS
     998             : 
     999             :     /*
    1000             :      * There's no guarantee that the repalloc returned a new pointer, so copy
    1001             :      * and free unconditionally here.
    1002             :      */
    1003             :     a = bms_copy_and_free(a);
    1004             : #endif
    1005             : 
    1006       13490 :     return a;
    1007             : }
    1008             : 
    1009             : /*
    1010             :  * bms_add_range
    1011             :  *      Add members in the range of 'lower' to 'upper' to the set.
    1012             :  *
    1013             :  * Note this could also be done by calling bms_add_member in a loop, however,
    1014             :  * using this function will be faster when the range is large as we work at
    1015             :  * the bitmapword level rather than at bit level.
    1016             :  */
    1017             : Bitmapset *
    1018       66168 : bms_add_range(Bitmapset *a, int lower, int upper)
    1019             : {
    1020             :     int         lwordnum,
    1021             :                 lbitnum,
    1022             :                 uwordnum,
    1023             :                 ushiftbits,
    1024             :                 wordnum;
    1025             : 
    1026             :     Assert(bms_is_valid_set(a));
    1027             : 
    1028             :     /* do nothing if nothing is called for, without further checking */
    1029       66168 :     if (upper < lower)
    1030             :     {
    1031             : #ifdef REALLOCATE_BITMAPSETS
    1032             :         a = bms_copy_and_free(a);
    1033             : #endif
    1034             : 
    1035          30 :         return a;
    1036             :     }
    1037             : 
    1038       66138 :     if (lower < 0)
    1039           2 :         elog(ERROR, "negative bitmapset member not allowed");
    1040       66136 :     uwordnum = WORDNUM(upper);
    1041             : 
    1042       66136 :     if (a == NULL)
    1043             :     {
    1044       46090 :         a = (Bitmapset *) palloc0(BITMAPSET_SIZE(uwordnum + 1));
    1045       46090 :         a->type = T_Bitmapset;
    1046       46090 :         a->nwords = uwordnum + 1;
    1047             :     }
    1048       20046 :     else if (uwordnum >= a->nwords)
    1049             :     {
    1050           6 :         int         oldnwords = a->nwords;
    1051             :         int         i;
    1052             : 
    1053             :         /* ensure we have enough words to store the upper bit */
    1054           6 :         a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(uwordnum + 1));
    1055           6 :         a->nwords = uwordnum + 1;
    1056             :         /* zero out the enlarged portion */
    1057           6 :         i = oldnwords;
    1058             :         do
    1059             :         {
    1060          10 :             a->words[i] = 0;
    1061          10 :         } while (++i < a->nwords);
    1062             :     }
    1063             : 
    1064       66136 :     wordnum = lwordnum = WORDNUM(lower);
    1065             : 
    1066       66136 :     lbitnum = BITNUM(lower);
    1067       66136 :     ushiftbits = BITS_PER_BITMAPWORD - (BITNUM(upper) + 1);
    1068             : 
    1069             :     /*
    1070             :      * Special case when lwordnum is the same as uwordnum we must perform the
    1071             :      * upper and lower masking on the word.
    1072             :      */
    1073       66136 :     if (lwordnum == uwordnum)
    1074             :     {
    1075       64252 :         a->words[lwordnum] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1)
    1076       64252 :             & (~(bitmapword) 0) >> ushiftbits;
    1077             :     }
    1078             :     else
    1079             :     {
    1080             :         /* turn on lbitnum and all bits left of it */
    1081        1884 :         a->words[wordnum++] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1);
    1082             : 
    1083             :         /* turn on all bits for any intermediate words */
    1084        1920 :         while (wordnum < uwordnum)
    1085          36 :             a->words[wordnum++] = ~(bitmapword) 0;
    1086             : 
    1087             :         /* turn on upper's bit and all bits right of it. */
    1088        1884 :         a->words[uwordnum] |= (~(bitmapword) 0) >> ushiftbits;
    1089             :     }
    1090             : 
    1091             : #ifdef REALLOCATE_BITMAPSETS
    1092             : 
    1093             :     /*
    1094             :      * There's no guarantee that the repalloc returned a new pointer, so copy
    1095             :      * and free unconditionally here.
    1096             :      */
    1097             :     a = bms_copy_and_free(a);
    1098             : #endif
    1099             : 
    1100       66136 :     return a;
    1101             : }
    1102             : 
    1103             : /*
    1104             :  * bms_int_members - like bms_intersect, but left input is recycled when
    1105             :  * possible
    1106             :  */
    1107             : Bitmapset *
    1108      724480 : bms_int_members(Bitmapset *a, const Bitmapset *b)
    1109             : {
    1110             :     int         lastnonzero;
    1111             :     int         shortlen;
    1112             :     int         i;
    1113             : 
    1114             :     Assert(bms_is_valid_set(a));
    1115             :     Assert(bms_is_valid_set(b));
    1116             : 
    1117             :     /* Handle cases where either input is NULL */
    1118      724480 :     if (a == NULL)
    1119       28272 :         return NULL;
    1120      696208 :     if (b == NULL)
    1121             :     {
    1122        5232 :         pfree(a);
    1123        5232 :         return NULL;
    1124             :     }
    1125             : 
    1126             :     /* Intersect b into a; we need never copy */
    1127      690976 :     shortlen = Min(a->nwords, b->nwords);
    1128      690976 :     lastnonzero = -1;
    1129      690976 :     i = 0;
    1130             :     do
    1131             :     {
    1132      690978 :         a->words[i] &= b->words[i];
    1133             : 
    1134      690978 :         if (a->words[i] != 0)
    1135      571958 :             lastnonzero = i;
    1136      690978 :     } while (++i < shortlen);
    1137             : 
    1138             :     /* If we computed an empty result, we must return NULL */
    1139      690976 :     if (lastnonzero == -1)
    1140             :     {
    1141      119020 :         pfree(a);
    1142      119020 :         return NULL;
    1143             :     }
    1144             : 
    1145             :     /* get rid of trailing zero words */
    1146      571956 :     a->nwords = lastnonzero + 1;
    1147             : 
    1148             : #ifdef REALLOCATE_BITMAPSETS
    1149             :     a = bms_copy_and_free(a);
    1150             : #endif
    1151             : 
    1152      571956 :     return a;
    1153             : }
    1154             : 
    1155             : /*
    1156             :  * bms_del_members - delete members in 'a' that are set in 'b'.  'a' is
    1157             :  * recycled when possible.
    1158             :  */
    1159             : Bitmapset *
    1160     2331938 : bms_del_members(Bitmapset *a, const Bitmapset *b)
    1161             : {
    1162             :     int         i;
    1163             : 
    1164             :     Assert(bms_is_valid_set(a));
    1165             :     Assert(bms_is_valid_set(b));
    1166             : 
    1167             :     /* Handle cases where either input is NULL */
    1168     2331938 :     if (a == NULL)
    1169     1006000 :         return NULL;
    1170     1325938 :     if (b == NULL)
    1171             :     {
    1172             : #ifdef REALLOCATE_BITMAPSETS
    1173             :         a = bms_copy_and_free(a);
    1174             : #endif
    1175             : 
    1176      212282 :         return a;
    1177             :     }
    1178             : 
    1179             :     /* Remove b's bits from a; we need never copy */
    1180     1113656 :     if (a->nwords > b->nwords)
    1181             :     {
    1182             :         /*
    1183             :          * We'll never need to remove trailing zero words when 'a' has more
    1184             :          * words than 'b'.
    1185             :          */
    1186           2 :         i = 0;
    1187             :         do
    1188             :         {
    1189           2 :             a->words[i] &= ~b->words[i];
    1190           2 :         } while (++i < b->nwords);
    1191             :     }
    1192             :     else
    1193             :     {
    1194     1113654 :         int         lastnonzero = -1;
    1195             : 
    1196             :         /* we may need to remove trailing zero words from the result. */
    1197     1113654 :         i = 0;
    1198             :         do
    1199             :         {
    1200     1113670 :             a->words[i] &= ~b->words[i];
    1201             : 
    1202             :             /* remember the last non-zero word */
    1203     1113670 :             if (a->words[i] != 0)
    1204      240176 :                 lastnonzero = i;
    1205     1113670 :         } while (++i < a->nwords);
    1206             : 
    1207             :         /* check if 'a' has become empty */
    1208     1113654 :         if (lastnonzero == -1)
    1209             :         {
    1210      873482 :             pfree(a);
    1211      873482 :             return NULL;
    1212             :         }
    1213             : 
    1214             :         /* trim off any trailing zero words */
    1215      240172 :         a->nwords = lastnonzero + 1;
    1216             :     }
    1217             : 
    1218             : #ifdef REALLOCATE_BITMAPSETS
    1219             :     a = bms_copy_and_free(a);
    1220             : #endif
    1221             : 
    1222      240174 :     return a;
    1223             : }
    1224             : 
    1225             : /*
    1226             :  * bms_join - like bms_union, but *either* input *may* be recycled
    1227             :  */
    1228             : Bitmapset *
    1229     1805872 : bms_join(Bitmapset *a, Bitmapset *b)
    1230             : {
    1231             :     Bitmapset  *result;
    1232             :     Bitmapset  *other;
    1233             :     int         otherlen;
    1234             :     int         i;
    1235             : 
    1236             :     Assert(bms_is_valid_set(a));
    1237             :     Assert(bms_is_valid_set(b));
    1238             : 
    1239             :     /* Handle cases where either input is NULL */
    1240     1805872 :     if (a == NULL)
    1241             :     {
    1242             : #ifdef REALLOCATE_BITMAPSETS
    1243             :         b = bms_copy_and_free(b);
    1244             : #endif
    1245             : 
    1246      750676 :         return b;
    1247             :     }
    1248     1055196 :     if (b == NULL)
    1249             :     {
    1250             : #ifdef REALLOCATE_BITMAPSETS
    1251             :         a = bms_copy_and_free(a);
    1252             : #endif
    1253             : 
    1254      193630 :         return a;
    1255             :     }
    1256             : 
    1257             :     /* Identify shorter and longer input; use longer one as result */
    1258      861566 :     if (a->nwords < b->nwords)
    1259             :     {
    1260           4 :         result = b;
    1261           4 :         other = a;
    1262             :     }
    1263             :     else
    1264             :     {
    1265      861562 :         result = a;
    1266      861562 :         other = b;
    1267             :     }
    1268             :     /* And union the shorter input into the result */
    1269      861566 :     otherlen = other->nwords;
    1270      861566 :     i = 0;
    1271             :     do
    1272             :     {
    1273      861566 :         result->words[i] |= other->words[i];
    1274      861566 :     } while (++i < otherlen);
    1275      861566 :     if (other != result)        /* pure paranoia */
    1276      861566 :         pfree(other);
    1277             : 
    1278             : #ifdef REALLOCATE_BITMAPSETS
    1279             :     result = bms_copy_and_free(result);
    1280             : #endif
    1281             : 
    1282      861566 :     return result;
    1283             : }
    1284             : 
    1285             : /*
    1286             :  * bms_next_member - find next member of a set
    1287             :  *
    1288             :  * Returns smallest member greater than "prevbit", or -2 if there is none.
    1289             :  * "prevbit" must NOT be less than -1, or the behavior is unpredictable.
    1290             :  *
    1291             :  * This is intended as support for iterating through the members of a set.
    1292             :  * The typical pattern is
    1293             :  *
    1294             :  *          x = -1;
    1295             :  *          while ((x = bms_next_member(inputset, x)) >= 0)
    1296             :  *              process member x;
    1297             :  *
    1298             :  * Notice that when there are no more members, we return -2, not -1 as you
    1299             :  * might expect.  The rationale for that is to allow distinguishing the
    1300             :  * loop-not-started state (x == -1) from the loop-completed state (x == -2).
    1301             :  * It makes no difference in simple loop usage, but complex iteration logic
    1302             :  * might need such an ability.
    1303             :  */
    1304             : int
    1305    23790404 : bms_next_member(const Bitmapset *a, int prevbit)
    1306             : {
    1307             :     int         nwords;
    1308             :     bitmapword  mask;
    1309             : 
    1310             :     Assert(bms_is_valid_set(a));
    1311             : 
    1312    23790404 :     if (a == NULL)
    1313     5654360 :         return -2;
    1314    18136044 :     nwords = a->nwords;
    1315    18136044 :     prevbit++;
    1316    18136044 :     mask = (~(bitmapword) 0) << BITNUM(prevbit);
    1317    23895090 :     for (int wordnum = WORDNUM(prevbit); wordnum < nwords; wordnum++)
    1318             :     {
    1319    18138736 :         bitmapword  w = a->words[wordnum];
    1320             : 
    1321             :         /* ignore bits before prevbit */
    1322    18138736 :         w &= mask;
    1323             : 
    1324    18138736 :         if (w != 0)
    1325             :         {
    1326             :             int         result;
    1327             : 
    1328    12379690 :             result = wordnum * BITS_PER_BITMAPWORD;
    1329    12379690 :             result += bmw_rightmost_one_pos(w);
    1330    12379690 :             return result;
    1331             :         }
    1332             : 
    1333             :         /* in subsequent words, consider all bits */
    1334     5759046 :         mask = (~(bitmapword) 0);
    1335             :     }
    1336     5756354 :     return -2;
    1337             : }
    1338             : 
    1339             : /*
    1340             :  * bms_prev_member - find prev member of a set
    1341             :  *
    1342             :  * Returns largest member less than "prevbit", or -2 if there is none.
    1343             :  * "prevbit" must NOT be more than one above the highest possible bit that can
    1344             :  * be set in the Bitmapset at its current size.
    1345             :  *
    1346             :  * To ease finding the highest set bit for the initial loop, the special
    1347             :  * prevbit value of -1 can be passed to have the function find the highest
    1348             :  * valued member in the set.
    1349             :  *
    1350             :  * This is intended as support for iterating through the members of a set in
    1351             :  * reverse.  The typical pattern is
    1352             :  *
    1353             :  *          x = -1;
    1354             :  *          while ((x = bms_prev_member(inputset, x)) >= 0)
    1355             :  *              process member x;
    1356             :  *
    1357             :  * Notice that when there are no more members, we return -2, not -1 as you
    1358             :  * might expect.  The rationale for that is to allow distinguishing the
    1359             :  * loop-not-started state (x == -1) from the loop-completed state (x == -2).
    1360             :  * It makes no difference in simple loop usage, but complex iteration logic
    1361             :  * might need such an ability.
    1362             :  */
    1363             : 
    1364             : int
    1365          30 : bms_prev_member(const Bitmapset *a, int prevbit)
    1366             : {
    1367             :     int         ushiftbits;
    1368             :     bitmapword  mask;
    1369             : 
    1370             :     Assert(bms_is_valid_set(a));
    1371             : 
    1372             :     /*
    1373             :      * If set is NULL or if there are no more bits to the right then we've
    1374             :      * nothing to do.
    1375             :      */
    1376          30 :     if (a == NULL || prevbit == 0)
    1377           4 :         return -2;
    1378             : 
    1379             :     /* Validate callers didn't give us something out of range */
    1380             :     Assert(prevbit <= a->nwords * BITS_PER_BITMAPWORD);
    1381             :     Assert(prevbit >= -1);
    1382             : 
    1383             :     /* transform -1 to the highest possible bit we could have set */
    1384          26 :     if (prevbit == -1)
    1385           2 :         prevbit = a->nwords * BITS_PER_BITMAPWORD - 1;
    1386             :     else
    1387          24 :         prevbit--;
    1388             : 
    1389          26 :     ushiftbits = BITS_PER_BITMAPWORD - (BITNUM(prevbit) + 1);
    1390          26 :     mask = (~(bitmapword) 0) >> ushiftbits;
    1391          34 :     for (int wordnum = WORDNUM(prevbit); wordnum >= 0; wordnum--)
    1392             :     {
    1393          26 :         bitmapword  w = a->words[wordnum];
    1394             : 
    1395             :         /* mask out bits left of prevbit */
    1396          26 :         w &= mask;
    1397             : 
    1398          26 :         if (w != 0)
    1399             :         {
    1400             :             int         result;
    1401             : 
    1402          18 :             result = wordnum * BITS_PER_BITMAPWORD;
    1403          18 :             result += bmw_leftmost_one_pos(w);
    1404          18 :             return result;
    1405             :         }
    1406             : 
    1407             :         /* in subsequent words, consider all bits */
    1408           8 :         mask = (~(bitmapword) 0);
    1409             :     }
    1410           8 :     return -2;
    1411             : }
    1412             : 
    1413             : /*
    1414             :  * bms_hash_value - compute a hash key for a Bitmapset
    1415             :  */
    1416             : uint32
    1417        7126 : bms_hash_value(const Bitmapset *a)
    1418             : {
    1419             :     Assert(bms_is_valid_set(a));
    1420             : 
    1421        7126 :     if (a == NULL)
    1422           8 :         return 0;               /* All empty sets hash to 0 */
    1423        7118 :     return DatumGetUInt32(hash_any((const unsigned char *) a->words,
    1424        7118 :                                    a->nwords * sizeof(bitmapword)));
    1425             : }
    1426             : 
    1427             : /*
    1428             :  * bitmap_hash - hash function for keys that are (pointers to) Bitmapsets
    1429             :  *
    1430             :  * Note: don't forget to specify bitmap_match as the match function!
    1431             :  */
    1432             : uint32
    1433        7112 : bitmap_hash(const void *key, Size keysize)
    1434             : {
    1435             :     Assert(keysize == sizeof(Bitmapset *));
    1436        7112 :     return bms_hash_value(*((const Bitmapset *const *) key));
    1437             : }
    1438             : 
    1439             : /*
    1440             :  * bitmap_match - match function to use with bitmap_hash
    1441             :  */
    1442             : int
    1443        4182 : bitmap_match(const void *key1, const void *key2, Size keysize)
    1444             : {
    1445             :     Assert(keysize == sizeof(Bitmapset *));
    1446        4182 :     return !bms_equal(*((const Bitmapset *const *) key1),
    1447             :                       *((const Bitmapset *const *) key2));
    1448             : }

Generated by: LCOV version 1.16