LCOV - code coverage report
Current view: top level - src/backend/nodes - bitmapset.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 380 446 85.2 %
Date: 2024-11-21 10:14:43 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-2024, 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    43212150 : bms_copy(const Bitmapset *a)
     123             : {
     124             :     Bitmapset  *result;
     125             :     size_t      size;
     126             : 
     127             :     Assert(bms_is_valid_set(a));
     128             : 
     129    43212150 :     if (a == NULL)
     130    28688744 :         return NULL;
     131             : 
     132    14523406 :     size = BITMAPSET_SIZE(a->nwords);
     133    14523406 :     result = (Bitmapset *) palloc(size);
     134    14523406 :     memcpy(result, a, size);
     135    14523406 :     return result;
     136             : }
     137             : 
     138             : /*
     139             :  * bms_equal - are two bitmapsets equal? or both NULL?
     140             :  */
     141             : bool
     142    21112310 : 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    21112310 :     if (a == NULL)
     151             :     {
     152    14913778 :         if (b == NULL)
     153    14862970 :             return true;
     154       50808 :         return false;
     155             :     }
     156     6198532 :     else if (b == NULL)
     157       32216 :         return false;
     158             : 
     159             :     /* can't be equal if the word counts don't match */
     160     6166316 :     if (a->nwords != b->nwords)
     161           0 :         return false;
     162             : 
     163             :     /* check each word matches */
     164     6166316 :     i = 0;
     165             :     do
     166             :     {
     167     6166724 :         if (a->words[i] != b->words[i])
     168     2634910 :             return false;
     169     3531814 :     } while (++i < a->nwords);
     170             : 
     171     3531406 :     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       20568 : 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       20568 :     if (a == NULL)
     192           0 :         return (b == NULL) ? 0 : -1;
     193       20568 :     else if (b == NULL)
     194           0 :         return +1;
     195             : 
     196             :     /* the set with the most words must be greater */
     197       20568 :     if (a->nwords != b->nwords)
     198           0 :         return (a->nwords > b->nwords) ? +1 : -1;
     199             : 
     200       20568 :     i = a->nwords - 1;
     201             :     do
     202             :     {
     203       20568 :         bitmapword  aw = a->words[i];
     204       20568 :         bitmapword  bw = b->words[i];
     205             : 
     206       20568 :         if (aw != bw)
     207       20568 :             return (aw > bw) ? +1 : -1;
     208           0 :     } while (--i >= 0);
     209           0 :     return 0;
     210             : }
     211             : 
     212             : /*
     213             :  * bms_make_singleton - build a bitmapset containing a single member
     214             :  */
     215             : Bitmapset *
     216    13294580 : bms_make_singleton(int x)
     217             : {
     218             :     Bitmapset  *result;
     219             :     int         wordnum,
     220             :                 bitnum;
     221             : 
     222    13294580 :     if (x < 0)
     223           0 :         elog(ERROR, "negative bitmapset member not allowed");
     224    13294580 :     wordnum = WORDNUM(x);
     225    13294580 :     bitnum = BITNUM(x);
     226    13294580 :     result = (Bitmapset *) palloc0(BITMAPSET_SIZE(wordnum + 1));
     227    13294580 :     result->type = T_Bitmapset;
     228    13294580 :     result->nwords = wordnum + 1;
     229    13294580 :     result->words[wordnum] = ((bitmapword) 1 << bitnum);
     230    13294580 :     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    17512820 : bms_free(Bitmapset *a)
     240             : {
     241    17512820 :     if (a)
     242     7452088 :         pfree(a);
     243    17512820 : }
     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     6931496 : 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     6931496 :     if (a == NULL)
     263     4345218 :         return bms_copy(b);
     264     2586278 :     if (b == NULL)
     265     1165064 :         return bms_copy(a);
     266             :     /* Identify shorter and longer input; copy the longer one */
     267     1421214 :     if (a->nwords <= b->nwords)
     268             :     {
     269     1421214 :         result = bms_copy(b);
     270     1421214 :         other = a;
     271             :     }
     272             :     else
     273             :     {
     274           0 :         result = bms_copy(a);
     275           0 :         other = b;
     276             :     }
     277             :     /* And union the shorter input into the result */
     278     1421214 :     otherlen = other->nwords;
     279     1421214 :     i = 0;
     280             :     do
     281             :     {
     282     1421214 :         result->words[i] |= other->words[i];
     283     1421214 :     } while (++i < otherlen);
     284     1421214 :     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      946360 : 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      946360 :     if (a == NULL || b == NULL)
     305      192194 :         return NULL;
     306             : 
     307             :     /* Identify shorter and longer input; copy the shorter one */
     308      754166 :     if (a->nwords <= b->nwords)
     309             :     {
     310      754166 :         result = bms_copy(a);
     311      754166 :         other = b;
     312             :     }
     313             :     else
     314             :     {
     315           0 :         result = bms_copy(b);
     316           0 :         other = a;
     317             :     }
     318             :     /* And intersect the longer input with the result */
     319      754166 :     resultlen = result->nwords;
     320      754166 :     lastnonzero = -1;
     321      754166 :     i = 0;
     322             :     do
     323             :     {
     324      754166 :         result->words[i] &= other->words[i];
     325             : 
     326      754166 :         if (result->words[i] != 0)
     327      747050 :             lastnonzero = i;
     328      754166 :     } while (++i < resultlen);
     329             :     /* If we computed an empty result, we must return NULL */
     330      754166 :     if (lastnonzero == -1)
     331             :     {
     332        7116 :         pfree(result);
     333        7116 :         return NULL;
     334             :     }
     335             : 
     336             :     /* get rid of trailing zero words */
     337      747050 :     result->nwords = lastnonzero + 1;
     338      747050 :     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      770928 : 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      770928 :     if (a == NULL)
     356       12550 :         return NULL;
     357      758378 :     if (b == NULL)
     358      489374 :         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      269004 :     if (!bms_nonempty_difference(a, b))
     366      100902 :         return NULL;
     367             : 
     368             :     /* Copy the left input */
     369      168102 :     result = bms_copy(a);
     370             : 
     371             :     /* And remove b's bits from result */
     372      168102 :     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           0 :         i = 0;
     379             :         do
     380             :         {
     381           0 :             result->words[i] &= ~b->words[i];
     382           0 :         } while (++i < b->nwords);
     383             :     }
     384             :     else
     385             :     {
     386      168102 :         int         lastnonzero = -1;
     387             : 
     388             :         /* we may need to remove trailing zero words from the result. */
     389      168102 :         i = 0;
     390             :         do
     391             :         {
     392      168102 :             result->words[i] &= ~b->words[i];
     393             : 
     394             :             /* remember the last non-zero word */
     395      168102 :             if (result->words[i] != 0)
     396      168102 :                 lastnonzero = i;
     397      168102 :         } while (++i < result->nwords);
     398             : 
     399             :         /* trim off trailing zero words */
     400      168102 :         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      168102 :     return result;
     406             : }
     407             : 
     408             : /*
     409             :  * bms_is_subset - is A a subset of B?
     410             :  */
     411             : bool
     412    16579948 : 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    16579948 :     if (a == NULL)
     421     1550982 :         return true;            /* empty set is a subset of anything */
     422    15028966 :     if (b == NULL)
     423      411244 :         return false;
     424             : 
     425             :     /* 'a' can't be a subset of 'b' if it contains more words */
     426    14617722 :     if (a->nwords > b->nwords)
     427           0 :         return false;
     428             : 
     429             :     /* Check all 'a' members are set in 'b' */
     430    14617722 :     i = 0;
     431             :     do
     432             :     {
     433    14617722 :         if ((a->words[i] & ~b->words[i]) != 0)
     434     5804268 :             return false;
     435     8813454 :     } while (++i < a->nwords);
     436     8813454 :     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     2124488 : 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     2124488 :     if (a == NULL)
     456             :     {
     457     1802812 :         if (b == NULL)
     458     1740510 :             return BMS_EQUAL;
     459       62302 :         return BMS_SUBSET1;
     460             :     }
     461      321676 :     if (b == NULL)
     462      153548 :         return BMS_SUBSET2;
     463             : 
     464             :     /* Check common words */
     465      168128 :     result = BMS_EQUAL;         /* status so far */
     466      168128 :     shortlen = Min(a->nwords, b->nwords);
     467      168128 :     i = 0;
     468             :     do
     469             :     {
     470      168128 :         bitmapword  aword = a->words[i];
     471      168128 :         bitmapword  bword = b->words[i];
     472             : 
     473      168128 :         if ((aword & ~bword) != 0)
     474             :         {
     475             :             /* a is not a subset of b */
     476       40178 :             if (result == BMS_SUBSET1)
     477           0 :                 return BMS_DIFFERENT;
     478       40178 :             result = BMS_SUBSET2;
     479             :         }
     480      168128 :         if ((bword & ~aword) != 0)
     481             :         {
     482             :             /* b is not a subset of a */
     483       40116 :             if (result == BMS_SUBSET2)
     484       37572 :                 return BMS_DIFFERENT;
     485        2544 :             result = BMS_SUBSET1;
     486             :         }
     487      130556 :     } while (++i < shortlen);
     488             :     /* Check extra words */
     489      130556 :     if (a->nwords > b->nwords)
     490             :     {
     491             :         /* if a has more words then a is not a subset of b */
     492           0 :         if (result == BMS_SUBSET1)
     493           0 :             return BMS_DIFFERENT;
     494           0 :         return BMS_SUBSET2;
     495             :     }
     496      130556 :     else if (a->nwords < b->nwords)
     497             :     {
     498             :         /* if b has more words then b is not a subset of a */
     499           0 :         if (result == BMS_SUBSET2)
     500           0 :             return BMS_DIFFERENT;
     501           0 :         return BMS_SUBSET1;
     502             :     }
     503      130556 :     return result;
     504             : }
     505             : 
     506             : /*
     507             :  * bms_is_member - is X a member of A?
     508             :  */
     509             : bool
     510    12021030 : 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    12021030 :     if (x < 0)
     519           0 :         elog(ERROR, "negative bitmapset member not allowed");
     520    12021030 :     if (a == NULL)
     521     7250942 :         return false;
     522             : 
     523     4770088 :     wordnum = WORDNUM(x);
     524     4770088 :     bitnum = BITNUM(x);
     525     4770088 :     if (wordnum >= a->nwords)
     526         226 :         return false;
     527     4769862 :     if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
     528     3257274 :         return true;
     529     1512588 :     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        4038 : bms_member_index(Bitmapset *a, int x)
     540             : {
     541             :     int         i;
     542             :     int         bitnum;
     543             :     int         wordnum;
     544        4038 :     int         result = 0;
     545             :     bitmapword  mask;
     546             : 
     547             :     Assert(bms_is_valid_set(a));
     548             : 
     549             :     /* return -1 if not a member of the bitmap */
     550        4038 :     if (!bms_is_member(x, a))
     551           0 :         return -1;
     552             : 
     553        4038 :     wordnum = WORDNUM(x);
     554        4038 :     bitnum = BITNUM(x);
     555             : 
     556             :     /* count bits in preceding words */
     557        4038 :     for (i = 0; i < wordnum; i++)
     558             :     {
     559           0 :         bitmapword  w = a->words[i];
     560             : 
     561             :         /* No need to count the bits in a zero word */
     562           0 :         if (w != 0)
     563           0 :             result += bmw_popcount(w);
     564             :     }
     565             : 
     566             :     /*
     567             :      * Now add bits of the last word, but only those before the item. We can
     568             :      * do that by applying a mask and then using popcount again. To get
     569             :      * 0-based index, we want to count only preceding bits, not the item
     570             :      * itself, so we subtract 1.
     571             :      */
     572        4038 :     mask = ((bitmapword) 1 << bitnum) - 1;
     573        4038 :     result += bmw_popcount(a->words[wordnum] & mask);
     574             : 
     575        4038 :     return result;
     576             : }
     577             : 
     578             : /*
     579             :  * bms_overlap - do sets overlap (ie, have a nonempty intersection)?
     580             :  */
     581             : bool
     582    11390914 : bms_overlap(const Bitmapset *a, const Bitmapset *b)
     583             : {
     584             :     int         shortlen;
     585             :     int         i;
     586             : 
     587             :     Assert(bms_is_valid_set(a));
     588             :     Assert(bms_is_valid_set(b));
     589             : 
     590             :     /* Handle cases where either input is NULL */
     591    11390914 :     if (a == NULL || b == NULL)
     592     4753664 :         return false;
     593             :     /* Check words in common */
     594     6637250 :     shortlen = Min(a->nwords, b->nwords);
     595     6637250 :     i = 0;
     596             :     do
     597             :     {
     598     6637250 :         if ((a->words[i] & b->words[i]) != 0)
     599     4306712 :             return true;
     600     2330538 :     } while (++i < shortlen);
     601     2330538 :     return false;
     602             : }
     603             : 
     604             : /*
     605             :  * bms_overlap_list - does a set overlap an integer list?
     606             :  */
     607             : bool
     608        1450 : bms_overlap_list(const Bitmapset *a, const List *b)
     609             : {
     610             :     ListCell   *lc;
     611             :     int         wordnum,
     612             :                 bitnum;
     613             : 
     614             :     Assert(bms_is_valid_set(a));
     615             : 
     616        1450 :     if (a == NULL || b == NIL)
     617        1312 :         return false;
     618             : 
     619         258 :     foreach(lc, b)
     620             :     {
     621         198 :         int         x = lfirst_int(lc);
     622             : 
     623         198 :         if (x < 0)
     624           0 :             elog(ERROR, "negative bitmapset member not allowed");
     625         198 :         wordnum = WORDNUM(x);
     626         198 :         bitnum = BITNUM(x);
     627         198 :         if (wordnum < a->nwords)
     628         198 :             if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
     629          78 :                 return true;
     630             :     }
     631             : 
     632          60 :     return false;
     633             : }
     634             : 
     635             : /*
     636             :  * bms_nonempty_difference - do sets have a nonempty difference?
     637             :  *
     638             :  * i.e., are any members set in 'a' that are not also set in 'b'.
     639             :  */
     640             : bool
     641     2184154 : bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
     642             : {
     643             :     int         i;
     644             : 
     645             :     Assert(bms_is_valid_set(a));
     646             :     Assert(bms_is_valid_set(b));
     647             : 
     648             :     /* Handle cases where either input is NULL */
     649     2184154 :     if (a == NULL)
     650        4662 :         return false;
     651     2179492 :     if (b == NULL)
     652           0 :         return true;
     653             :     /* if 'a' has more words then it must contain additional members */
     654     2179492 :     if (a->nwords > b->nwords)
     655           0 :         return true;
     656             :     /* Check all 'a' members are set in 'b' */
     657     2179492 :     i = 0;
     658             :     do
     659             :     {
     660     2179492 :         if ((a->words[i] & ~b->words[i]) != 0)
     661     1267114 :             return true;
     662      912378 :     } while (++i < a->nwords);
     663      912378 :     return false;
     664             : }
     665             : 
     666             : /*
     667             :  * bms_singleton_member - return the sole integer member of set
     668             :  *
     669             :  * Raises error if |a| is not 1.
     670             :  */
     671             : int
     672       12424 : bms_singleton_member(const Bitmapset *a)
     673             : {
     674       12424 :     int         result = -1;
     675             :     int         nwords;
     676             :     int         wordnum;
     677             : 
     678             :     Assert(bms_is_valid_set(a));
     679             : 
     680       12424 :     if (a == NULL)
     681           0 :         elog(ERROR, "bitmapset is empty");
     682             : 
     683       12424 :     nwords = a->nwords;
     684       12424 :     wordnum = 0;
     685             :     do
     686             :     {
     687       12424 :         bitmapword  w = a->words[wordnum];
     688             : 
     689       12424 :         if (w != 0)
     690             :         {
     691       12424 :             if (result >= 0 || HAS_MULTIPLE_ONES(w))
     692           0 :                 elog(ERROR, "bitmapset has multiple members");
     693       12424 :             result = wordnum * BITS_PER_BITMAPWORD;
     694       12424 :             result += bmw_rightmost_one_pos(w);
     695             :         }
     696       12424 :     } while (++wordnum < nwords);
     697             : 
     698             :     /* we don't expect non-NULL sets to be empty */
     699             :     Assert(result >= 0);
     700       12424 :     return result;
     701             : }
     702             : 
     703             : /*
     704             :  * bms_get_singleton_member
     705             :  *
     706             :  * Test whether the given set is a singleton.
     707             :  * If so, set *member to the value of its sole member, and return true.
     708             :  * If not, return false, without changing *member.
     709             :  *
     710             :  * This is more convenient and faster than calling bms_membership() and then
     711             :  * bms_singleton_member(), if we don't care about distinguishing empty sets
     712             :  * from multiple-member sets.
     713             :  */
     714             : bool
     715     2044002 : bms_get_singleton_member(const Bitmapset *a, int *member)
     716             : {
     717     2044002 :     int         result = -1;
     718             :     int         nwords;
     719             :     int         wordnum;
     720             : 
     721             :     Assert(bms_is_valid_set(a));
     722             : 
     723     2044002 :     if (a == NULL)
     724           0 :         return false;
     725             : 
     726     2044002 :     nwords = a->nwords;
     727     2044002 :     wordnum = 0;
     728             :     do
     729             :     {
     730     2044002 :         bitmapword  w = a->words[wordnum];
     731             : 
     732     2044002 :         if (w != 0)
     733             :         {
     734     2044002 :             if (result >= 0 || HAS_MULTIPLE_ONES(w))
     735      356674 :                 return false;
     736     1687328 :             result = wordnum * BITS_PER_BITMAPWORD;
     737     1687328 :             result += bmw_rightmost_one_pos(w);
     738             :         }
     739     1687328 :     } while (++wordnum < nwords);
     740             : 
     741             :     /* we don't expect non-NULL sets to be empty */
     742             :     Assert(result >= 0);
     743     1687328 :     *member = result;
     744     1687328 :     return true;
     745             : }
     746             : 
     747             : /*
     748             :  * bms_num_members - count members of set
     749             :  */
     750             : int
     751     1732236 : bms_num_members(const Bitmapset *a)
     752             : {
     753     1732236 :     int         result = 0;
     754             :     int         nwords;
     755             :     int         wordnum;
     756             : 
     757             :     Assert(bms_is_valid_set(a));
     758             : 
     759     1732236 :     if (a == NULL)
     760      137530 :         return 0;
     761             : 
     762     1594706 :     nwords = a->nwords;
     763     1594706 :     wordnum = 0;
     764             :     do
     765             :     {
     766     1594706 :         bitmapword  w = a->words[wordnum];
     767             : 
     768             :         /* No need to count the bits in a zero word */
     769     1594706 :         if (w != 0)
     770     1594706 :             result += bmw_popcount(w);
     771     1594706 :     } while (++wordnum < nwords);
     772     1594706 :     return result;
     773             : }
     774             : 
     775             : /*
     776             :  * bms_membership - does a set have zero, one, or multiple members?
     777             :  *
     778             :  * This is faster than making an exact count with bms_num_members().
     779             :  */
     780             : BMS_Membership
     781      934020 : bms_membership(const Bitmapset *a)
     782             : {
     783      934020 :     BMS_Membership result = BMS_EMPTY_SET;
     784             :     int         nwords;
     785             :     int         wordnum;
     786             : 
     787             :     Assert(bms_is_valid_set(a));
     788             : 
     789      934020 :     if (a == NULL)
     790         518 :         return BMS_EMPTY_SET;
     791             : 
     792      933502 :     nwords = a->nwords;
     793      933502 :     wordnum = 0;
     794             :     do
     795             :     {
     796      933502 :         bitmapword  w = a->words[wordnum];
     797             : 
     798      933502 :         if (w != 0)
     799             :         {
     800      933502 :             if (result != BMS_EMPTY_SET || HAS_MULTIPLE_ONES(w))
     801      235876 :                 return BMS_MULTIPLE;
     802      697626 :             result = BMS_SINGLETON;
     803             :         }
     804      697626 :     } while (++wordnum < nwords);
     805      697626 :     return result;
     806             : }
     807             : 
     808             : 
     809             : /*
     810             :  * bms_add_member - add a specified member to set
     811             :  *
     812             :  * 'a' is recycled when possible.
     813             :  */
     814             : Bitmapset *
     815    22170576 : bms_add_member(Bitmapset *a, int x)
     816             : {
     817             :     int         wordnum,
     818             :                 bitnum;
     819             : 
     820             :     Assert(bms_is_valid_set(a));
     821             : 
     822    22170576 :     if (x < 0)
     823           0 :         elog(ERROR, "negative bitmapset member not allowed");
     824    22170576 :     if (a == NULL)
     825    11223074 :         return bms_make_singleton(x);
     826             : 
     827    10947502 :     wordnum = WORDNUM(x);
     828    10947502 :     bitnum = BITNUM(x);
     829             : 
     830             :     /* enlarge the set if necessary */
     831    10947502 :     if (wordnum >= a->nwords)
     832             :     {
     833         204 :         int         oldnwords = a->nwords;
     834             :         int         i;
     835             : 
     836         204 :         a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(wordnum + 1));
     837         204 :         a->nwords = wordnum + 1;
     838             :         /* zero out the enlarged portion */
     839         204 :         i = oldnwords;
     840             :         do
     841             :         {
     842         876 :             a->words[i] = 0;
     843         876 :         } while (++i < a->nwords);
     844             :     }
     845             : 
     846    10947502 :     a->words[wordnum] |= ((bitmapword) 1 << bitnum);
     847             : 
     848             : #ifdef REALLOCATE_BITMAPSETS
     849             : 
     850             :     /*
     851             :      * There's no guarantee that the repalloc returned a new pointer, so copy
     852             :      * and free unconditionally here.
     853             :      */
     854             :     a = bms_copy_and_free(a);
     855             : #endif
     856             : 
     857    10947502 :     return a;
     858             : }
     859             : 
     860             : /*
     861             :  * bms_del_member - remove a specified member from set
     862             :  *
     863             :  * No error if x is not currently a member of set
     864             :  *
     865             :  * 'a' is recycled when possible.
     866             :  */
     867             : Bitmapset *
     868     1356182 : bms_del_member(Bitmapset *a, int x)
     869             : {
     870             :     int         wordnum,
     871             :                 bitnum;
     872             : 
     873             :     Assert(bms_is_valid_set(a));
     874             : 
     875     1356182 :     if (x < 0)
     876           0 :         elog(ERROR, "negative bitmapset member not allowed");
     877     1356182 :     if (a == NULL)
     878      578514 :         return NULL;
     879             : 
     880      777668 :     wordnum = WORDNUM(x);
     881      777668 :     bitnum = BITNUM(x);
     882             : 
     883             : #ifdef REALLOCATE_BITMAPSETS
     884             :     a = bms_copy_and_free(a);
     885             : #endif
     886             : 
     887             :     /* member can't exist.  Return 'a' unmodified */
     888      777668 :     if (unlikely(wordnum >= a->nwords))
     889           0 :         return a;
     890             : 
     891      777668 :     a->words[wordnum] &= ~((bitmapword) 1 << bitnum);
     892             : 
     893             :     /* when last word becomes empty, trim off all trailing empty words */
     894      777668 :     if (a->words[wordnum] == 0 && wordnum == a->nwords - 1)
     895             :     {
     896             :         /* find the last non-empty word and make that the new final word */
     897      419876 :         for (int i = wordnum - 1; i >= 0; i--)
     898             :         {
     899           0 :             if (a->words[i] != 0)
     900             :             {
     901           0 :                 a->nwords = i + 1;
     902           0 :                 return a;
     903             :             }
     904             :         }
     905             : 
     906             :         /* the set is now empty */
     907      419876 :         pfree(a);
     908      419876 :         return NULL;
     909             :     }
     910      357792 :     return a;
     911             : }
     912             : 
     913             : /*
     914             :  * bms_add_members - like bms_union, but left input is recycled when possible
     915             :  */
     916             : Bitmapset *
     917    12625596 : bms_add_members(Bitmapset *a, const Bitmapset *b)
     918             : {
     919             :     Bitmapset  *result;
     920             :     const Bitmapset *other;
     921             :     int         otherlen;
     922             :     int         i;
     923             : 
     924             :     Assert(bms_is_valid_set(a));
     925             :     Assert(bms_is_valid_set(b));
     926             : 
     927             :     /* Handle cases where either input is NULL */
     928    12625596 :     if (a == NULL)
     929     6680212 :         return bms_copy(b);
     930     5945384 :     if (b == NULL)
     931             :     {
     932             : #ifdef REALLOCATE_BITMAPSETS
     933             :         a = bms_copy_and_free(a);
     934             : #endif
     935             : 
     936     3797994 :         return a;
     937             :     }
     938             :     /* Identify shorter and longer input; copy the longer one if needed */
     939     2147390 :     if (a->nwords < b->nwords)
     940             :     {
     941           0 :         result = bms_copy(b);
     942           0 :         other = a;
     943             :     }
     944             :     else
     945             :     {
     946     2147390 :         result = a;
     947     2147390 :         other = b;
     948             :     }
     949             :     /* And union the shorter input into the result */
     950     2147390 :     otherlen = other->nwords;
     951     2147390 :     i = 0;
     952             :     do
     953             :     {
     954     2147390 :         result->words[i] |= other->words[i];
     955     2147390 :     } while (++i < otherlen);
     956     2147390 :     if (result != a)
     957           0 :         pfree(a);
     958             : #ifdef REALLOCATE_BITMAPSETS
     959             :     else
     960             :         result = bms_copy_and_free(result);
     961             : #endif
     962             : 
     963     2147390 :     return result;
     964             : }
     965             : 
     966             : /*
     967             :  * bms_replace_members
     968             :  *      Remove all existing members from 'a' and repopulate the set with members
     969             :  *      from 'b', recycling 'a', when possible.
     970             :  */
     971             : Bitmapset *
     972       12900 : bms_replace_members(Bitmapset *a, const Bitmapset *b)
     973             : {
     974             :     int         i;
     975             : 
     976             :     Assert(bms_is_valid_set(a));
     977             :     Assert(bms_is_valid_set(b));
     978             : 
     979       12900 :     if (a == NULL)
     980           0 :         return bms_copy(b);
     981       12900 :     if (b == NULL)
     982             :     {
     983           0 :         pfree(a);
     984           0 :         return NULL;
     985             :     }
     986             : 
     987       12900 :     if (a->nwords < b->nwords)
     988           0 :         a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(b->nwords));
     989             : 
     990       12900 :     i = 0;
     991             :     do
     992             :     {
     993       12900 :         a->words[i] = b->words[i];
     994       12900 :     } while (++i < b->nwords);
     995             : 
     996       12900 :     a->nwords = b->nwords;
     997             : 
     998             : #ifdef REALLOCATE_BITMAPSETS
     999             : 
    1000             :     /*
    1001             :      * There's no guarantee that the repalloc returned a new pointer, so copy
    1002             :      * and free unconditionally here.
    1003             :      */
    1004             :     a = bms_copy_and_free(a);
    1005             : #endif
    1006             : 
    1007       12900 :     return a;
    1008             : }
    1009             : 
    1010             : /*
    1011             :  * bms_add_range
    1012             :  *      Add members in the range of 'lower' to 'upper' to the set.
    1013             :  *
    1014             :  * Note this could also be done by calling bms_add_member in a loop, however,
    1015             :  * using this function will be faster when the range is large as we work at
    1016             :  * the bitmapword level rather than at bit level.
    1017             :  */
    1018             : Bitmapset *
    1019       37826 : bms_add_range(Bitmapset *a, int lower, int upper)
    1020             : {
    1021             :     int         lwordnum,
    1022             :                 lbitnum,
    1023             :                 uwordnum,
    1024             :                 ushiftbits,
    1025             :                 wordnum;
    1026             : 
    1027             :     Assert(bms_is_valid_set(a));
    1028             : 
    1029             :     /* do nothing if nothing is called for, without further checking */
    1030       37826 :     if (upper < lower)
    1031             :     {
    1032             : #ifdef REALLOCATE_BITMAPSETS
    1033             :         a = bms_copy_and_free(a);
    1034             : #endif
    1035             : 
    1036          28 :         return a;
    1037             :     }
    1038             : 
    1039       37798 :     if (lower < 0)
    1040           0 :         elog(ERROR, "negative bitmapset member not allowed");
    1041       37798 :     uwordnum = WORDNUM(upper);
    1042             : 
    1043       37798 :     if (a == NULL)
    1044             :     {
    1045       37798 :         a = (Bitmapset *) palloc0(BITMAPSET_SIZE(uwordnum + 1));
    1046       37798 :         a->type = T_Bitmapset;
    1047       37798 :         a->nwords = uwordnum + 1;
    1048             :     }
    1049           0 :     else if (uwordnum >= a->nwords)
    1050             :     {
    1051           0 :         int         oldnwords = a->nwords;
    1052             :         int         i;
    1053             : 
    1054             :         /* ensure we have enough words to store the upper bit */
    1055           0 :         a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(uwordnum + 1));
    1056           0 :         a->nwords = uwordnum + 1;
    1057             :         /* zero out the enlarged portion */
    1058           0 :         i = oldnwords;
    1059             :         do
    1060             :         {
    1061           0 :             a->words[i] = 0;
    1062           0 :         } while (++i < a->nwords);
    1063             :     }
    1064             : 
    1065       37798 :     wordnum = lwordnum = WORDNUM(lower);
    1066             : 
    1067       37798 :     lbitnum = BITNUM(lower);
    1068       37798 :     ushiftbits = BITS_PER_BITMAPWORD - (BITNUM(upper) + 1);
    1069             : 
    1070             :     /*
    1071             :      * Special case when lwordnum is the same as uwordnum we must perform the
    1072             :      * upper and lower masking on the word.
    1073             :      */
    1074       37798 :     if (lwordnum == uwordnum)
    1075             :     {
    1076       37798 :         a->words[lwordnum] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1)
    1077       37798 :             & (~(bitmapword) 0) >> ushiftbits;
    1078             :     }
    1079             :     else
    1080             :     {
    1081             :         /* turn on lbitnum and all bits left of it */
    1082           0 :         a->words[wordnum++] |= ~(bitmapword) (((bitmapword) 1 << lbitnum) - 1);
    1083             : 
    1084             :         /* turn on all bits for any intermediate words */
    1085           0 :         while (wordnum < uwordnum)
    1086           0 :             a->words[wordnum++] = ~(bitmapword) 0;
    1087             : 
    1088             :         /* turn on upper's bit and all bits right of it. */
    1089           0 :         a->words[uwordnum] |= (~(bitmapword) 0) >> ushiftbits;
    1090             :     }
    1091             : 
    1092             : #ifdef REALLOCATE_BITMAPSETS
    1093             : 
    1094             :     /*
    1095             :      * There's no guarantee that the repalloc returned a new pointer, so copy
    1096             :      * and free unconditionally here.
    1097             :      */
    1098             :     a = bms_copy_and_free(a);
    1099             : #endif
    1100             : 
    1101       37798 :     return a;
    1102             : }
    1103             : 
    1104             : /*
    1105             :  * bms_int_members - like bms_intersect, but left input is recycled when
    1106             :  * possible
    1107             :  */
    1108             : Bitmapset *
    1109      562902 : bms_int_members(Bitmapset *a, const Bitmapset *b)
    1110             : {
    1111             :     int         lastnonzero;
    1112             :     int         shortlen;
    1113             :     int         i;
    1114             : 
    1115             :     Assert(bms_is_valid_set(a));
    1116             :     Assert(bms_is_valid_set(b));
    1117             : 
    1118             :     /* Handle cases where either input is NULL */
    1119      562902 :     if (a == NULL)
    1120       26666 :         return NULL;
    1121      536236 :     if (b == NULL)
    1122             :     {
    1123        3998 :         pfree(a);
    1124        3998 :         return NULL;
    1125             :     }
    1126             : 
    1127             :     /* Intersect b into a; we need never copy */
    1128      532238 :     shortlen = Min(a->nwords, b->nwords);
    1129      532238 :     lastnonzero = -1;
    1130      532238 :     i = 0;
    1131             :     do
    1132             :     {
    1133      532238 :         a->words[i] &= b->words[i];
    1134             : 
    1135      532238 :         if (a->words[i] != 0)
    1136      436404 :             lastnonzero = i;
    1137      532238 :     } while (++i < shortlen);
    1138             : 
    1139             :     /* If we computed an empty result, we must return NULL */
    1140      532238 :     if (lastnonzero == -1)
    1141             :     {
    1142       95834 :         pfree(a);
    1143       95834 :         return NULL;
    1144             :     }
    1145             : 
    1146             :     /* get rid of trailing zero words */
    1147      436404 :     a->nwords = lastnonzero + 1;
    1148             : 
    1149             : #ifdef REALLOCATE_BITMAPSETS
    1150             :     a = bms_copy_and_free(a);
    1151             : #endif
    1152             : 
    1153      436404 :     return a;
    1154             : }
    1155             : 
    1156             : /*
    1157             :  * bms_del_members - delete members in 'a' that are set in 'b'.  'a' is
    1158             :  * recycled when possible.
    1159             :  */
    1160             : Bitmapset *
    1161     1852544 : bms_del_members(Bitmapset *a, const Bitmapset *b)
    1162             : {
    1163             :     int         i;
    1164             : 
    1165             :     Assert(bms_is_valid_set(a));
    1166             :     Assert(bms_is_valid_set(b));
    1167             : 
    1168             :     /* Handle cases where either input is NULL */
    1169     1852544 :     if (a == NULL)
    1170      828416 :         return NULL;
    1171     1024128 :     if (b == NULL)
    1172             :     {
    1173             : #ifdef REALLOCATE_BITMAPSETS
    1174             :         a = bms_copy_and_free(a);
    1175             : #endif
    1176             : 
    1177      173064 :         return a;
    1178             :     }
    1179             : 
    1180             :     /* Remove b's bits from a; we need never copy */
    1181      851064 :     if (a->nwords > b->nwords)
    1182             :     {
    1183             :         /*
    1184             :          * We'll never need to remove trailing zero words when 'a' has more
    1185             :          * words than 'b'.
    1186             :          */
    1187           0 :         i = 0;
    1188             :         do
    1189             :         {
    1190           0 :             a->words[i] &= ~b->words[i];
    1191           0 :         } while (++i < b->nwords);
    1192             :     }
    1193             :     else
    1194             :     {
    1195      851064 :         int         lastnonzero = -1;
    1196             : 
    1197             :         /* we may need to remove trailing zero words from the result. */
    1198      851064 :         i = 0;
    1199             :         do
    1200             :         {
    1201      851064 :             a->words[i] &= ~b->words[i];
    1202             : 
    1203             :             /* remember the last non-zero word */
    1204      851064 :             if (a->words[i] != 0)
    1205      160852 :                 lastnonzero = i;
    1206      851064 :         } while (++i < a->nwords);
    1207             : 
    1208             :         /* check if 'a' has become empty */
    1209      851064 :         if (lastnonzero == -1)
    1210             :         {
    1211      690212 :             pfree(a);
    1212      690212 :             return NULL;
    1213             :         }
    1214             : 
    1215             :         /* trim off any trailing zero words */
    1216      160852 :         a->nwords = lastnonzero + 1;
    1217             :     }
    1218             : 
    1219             : #ifdef REALLOCATE_BITMAPSETS
    1220             :     a = bms_copy_and_free(a);
    1221             : #endif
    1222             : 
    1223      160852 :     return a;
    1224             : }
    1225             : 
    1226             : /*
    1227             :  * bms_join - like bms_union, but *either* input *may* be recycled
    1228             :  */
    1229             : Bitmapset *
    1230     1351476 : bms_join(Bitmapset *a, Bitmapset *b)
    1231             : {
    1232             :     Bitmapset  *result;
    1233             :     Bitmapset  *other;
    1234             :     int         otherlen;
    1235             :     int         i;
    1236             : 
    1237             :     Assert(bms_is_valid_set(a));
    1238             :     Assert(bms_is_valid_set(b));
    1239             : 
    1240             :     /* Handle cases where either input is NULL */
    1241     1351476 :     if (a == NULL)
    1242             :     {
    1243             : #ifdef REALLOCATE_BITMAPSETS
    1244             :         b = bms_copy_and_free(b);
    1245             : #endif
    1246             : 
    1247      590764 :         return b;
    1248             :     }
    1249      760712 :     if (b == NULL)
    1250             :     {
    1251             : #ifdef REALLOCATE_BITMAPSETS
    1252             :         a = bms_copy_and_free(a);
    1253             : #endif
    1254             : 
    1255      164746 :         return a;
    1256             :     }
    1257             : 
    1258             :     /* Identify shorter and longer input; use longer one as result */
    1259      595966 :     if (a->nwords < b->nwords)
    1260             :     {
    1261           0 :         result = b;
    1262           0 :         other = a;
    1263             :     }
    1264             :     else
    1265             :     {
    1266      595966 :         result = a;
    1267      595966 :         other = b;
    1268             :     }
    1269             :     /* And union the shorter input into the result */
    1270      595966 :     otherlen = other->nwords;
    1271      595966 :     i = 0;
    1272             :     do
    1273             :     {
    1274      595966 :         result->words[i] |= other->words[i];
    1275      595966 :     } while (++i < otherlen);
    1276      595966 :     if (other != result)        /* pure paranoia */
    1277      595966 :         pfree(other);
    1278             : 
    1279             : #ifdef REALLOCATE_BITMAPSETS
    1280             :     result = bms_copy_and_free(result);
    1281             : #endif
    1282             : 
    1283      595966 :     return result;
    1284             : }
    1285             : 
    1286             : /*
    1287             :  * bms_next_member - find next member of a set
    1288             :  *
    1289             :  * Returns smallest member greater than "prevbit", or -2 if there is none.
    1290             :  * "prevbit" must NOT be less than -1, or the behavior is unpredictable.
    1291             :  *
    1292             :  * This is intended as support for iterating through the members of a set.
    1293             :  * The typical pattern is
    1294             :  *
    1295             :  *          x = -1;
    1296             :  *          while ((x = bms_next_member(inputset, x)) >= 0)
    1297             :  *              process member x;
    1298             :  *
    1299             :  * Notice that when there are no more members, we return -2, not -1 as you
    1300             :  * might expect.  The rationale for that is to allow distinguishing the
    1301             :  * loop-not-started state (x == -1) from the loop-completed state (x == -2).
    1302             :  * It makes no difference in simple loop usage, but complex iteration logic
    1303             :  * might need such an ability.
    1304             :  */
    1305             : int
    1306    34583500 : bms_next_member(const Bitmapset *a, int prevbit)
    1307             : {
    1308             :     int         nwords;
    1309             :     int         wordnum;
    1310             :     bitmapword  mask;
    1311             : 
    1312             :     Assert(bms_is_valid_set(a));
    1313             : 
    1314    34583500 :     if (a == NULL)
    1315    14999002 :         return -2;
    1316    19584498 :     nwords = a->nwords;
    1317    19584498 :     prevbit++;
    1318    19584498 :     mask = (~(bitmapword) 0) << BITNUM(prevbit);
    1319    25906484 :     for (wordnum = WORDNUM(prevbit); wordnum < nwords; wordnum++)
    1320             :     {
    1321    19584906 :         bitmapword  w = a->words[wordnum];
    1322             : 
    1323             :         /* ignore bits before prevbit */
    1324    19584906 :         w &= mask;
    1325             : 
    1326    19584906 :         if (w != 0)
    1327             :         {
    1328             :             int         result;
    1329             : 
    1330    13262920 :             result = wordnum * BITS_PER_BITMAPWORD;
    1331    13262920 :             result += bmw_rightmost_one_pos(w);
    1332    13262920 :             return result;
    1333             :         }
    1334             : 
    1335             :         /* in subsequent words, consider all bits */
    1336     6321986 :         mask = (~(bitmapword) 0);
    1337             :     }
    1338     6321578 :     return -2;
    1339             : }
    1340             : 
    1341             : /*
    1342             :  * bms_prev_member - find prev member of a set
    1343             :  *
    1344             :  * Returns largest member less than "prevbit", or -2 if there is none.
    1345             :  * "prevbit" must NOT be more than one above the highest possible bit that can
    1346             :  * be set at the Bitmapset at its current size.
    1347             :  *
    1348             :  * To ease finding the highest set bit for the initial loop, the special
    1349             :  * prevbit value of -1 can be passed to have the function find the highest
    1350             :  * valued member in the set.
    1351             :  *
    1352             :  * This is intended as support for iterating through the members of a set in
    1353             :  * reverse.  The typical pattern is
    1354             :  *
    1355             :  *          x = -1;
    1356             :  *          while ((x = bms_prev_member(inputset, x)) >= 0)
    1357             :  *              process member x;
    1358             :  *
    1359             :  * Notice that when there are no more members, we return -2, not -1 as you
    1360             :  * might expect.  The rationale for that is to allow distinguishing the
    1361             :  * loop-not-started state (x == -1) from the loop-completed state (x == -2).
    1362             :  * It makes no difference in simple loop usage, but complex iteration logic
    1363             :  * might need such an ability.
    1364             :  */
    1365             : 
    1366             : int
    1367          18 : bms_prev_member(const Bitmapset *a, int prevbit)
    1368             : {
    1369             :     int         wordnum;
    1370             :     int         ushiftbits;
    1371             :     bitmapword  mask;
    1372             : 
    1373             :     Assert(bms_is_valid_set(a));
    1374             : 
    1375             :     /*
    1376             :      * If set is NULL or if there are no more bits to the right then we've
    1377             :      * nothing to do.
    1378             :      */
    1379          18 :     if (a == NULL || prevbit == 0)
    1380           0 :         return -2;
    1381             : 
    1382             :     /* transform -1 to the highest possible bit we could have set */
    1383          18 :     if (prevbit == -1)
    1384           0 :         prevbit = a->nwords * BITS_PER_BITMAPWORD - 1;
    1385             :     else
    1386          18 :         prevbit--;
    1387             : 
    1388          18 :     ushiftbits = BITS_PER_BITMAPWORD - (BITNUM(prevbit) + 1);
    1389          18 :     mask = (~(bitmapword) 0) >> ushiftbits;
    1390          24 :     for (wordnum = WORDNUM(prevbit); wordnum >= 0; wordnum--)
    1391             :     {
    1392          18 :         bitmapword  w = a->words[wordnum];
    1393             : 
    1394             :         /* mask out bits left of prevbit */
    1395          18 :         w &= mask;
    1396             : 
    1397          18 :         if (w != 0)
    1398             :         {
    1399             :             int         result;
    1400             : 
    1401          12 :             result = wordnum * BITS_PER_BITMAPWORD;
    1402          12 :             result += bmw_leftmost_one_pos(w);
    1403          12 :             return result;
    1404             :         }
    1405             : 
    1406             :         /* in subsequent words, consider all bits */
    1407           6 :         mask = (~(bitmapword) 0);
    1408             :     }
    1409           6 :     return -2;
    1410             : }
    1411             : 
    1412             : /*
    1413             :  * bms_hash_value - compute a hash key for a Bitmapset
    1414             :  */
    1415             : uint32
    1416        5298 : bms_hash_value(const Bitmapset *a)
    1417             : {
    1418             :     Assert(bms_is_valid_set(a));
    1419             : 
    1420        5298 :     if (a == NULL)
    1421           0 :         return 0;               /* All empty sets hash to 0 */
    1422        5298 :     return DatumGetUInt32(hash_any((const unsigned char *) a->words,
    1423        5298 :                                    a->nwords * sizeof(bitmapword)));
    1424             : }
    1425             : 
    1426             : /*
    1427             :  * bitmap_hash - hash function for keys that are (pointers to) Bitmapsets
    1428             :  *
    1429             :  * Note: don't forget to specify bitmap_match as the match function!
    1430             :  */
    1431             : uint32
    1432        5298 : bitmap_hash(const void *key, Size keysize)
    1433             : {
    1434             :     Assert(keysize == sizeof(Bitmapset *));
    1435        5298 :     return bms_hash_value(*((const Bitmapset *const *) key));
    1436             : }
    1437             : 
    1438             : /*
    1439             :  * bitmap_match - match function to use with bitmap_hash
    1440             :  */
    1441             : int
    1442        3204 : bitmap_match(const void *key1, const void *key2, Size keysize)
    1443             : {
    1444             :     Assert(keysize == sizeof(Bitmapset *));
    1445        3204 :     return !bms_equal(*((const Bitmapset *const *) key1),
    1446             :                       *((const Bitmapset *const *) key2));
    1447             : }

Generated by: LCOV version 1.14