LCOV - code coverage report
Current view: top level - src/backend/nodes - bitmapset.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 99.8 % 485 484
Test Date: 2026-07-13 21:15:41 Functions: 100.0 % 33 33
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 91.7 % 326 299

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

Generated by: LCOV version 2.0-1