Header And Logo

PostgreSQL
| The world's most advanced open source database.

bitmapset.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * bitmapset.c
00004  *    PostgreSQL generic bitmap set package
00005  *
00006  * A bitmap set can represent any set of nonnegative integers, although
00007  * it is mainly intended for sets where the maximum value is not large,
00008  * say at most a few hundred.  By convention, a NULL pointer is always
00009  * accepted by all operations to represent the empty set.  (But beware
00010  * that this is not the only representation of the empty set.  Use
00011  * bms_is_empty() in preference to testing for NULL.)
00012  *
00013  *
00014  * Copyright (c) 2003-2013, PostgreSQL Global Development Group
00015  *
00016  * IDENTIFICATION
00017  *    src/backend/nodes/bitmapset.c
00018  *
00019  *-------------------------------------------------------------------------
00020  */
00021 #include "postgres.h"
00022 
00023 #include "access/hash.h"
00024 
00025 
00026 #define WORDNUM(x)  ((x) / BITS_PER_BITMAPWORD)
00027 #define BITNUM(x)   ((x) % BITS_PER_BITMAPWORD)
00028 
00029 #define BITMAPSET_SIZE(nwords)  \
00030     (offsetof(Bitmapset, words) + (nwords) * sizeof(bitmapword))
00031 
00032 /*----------
00033  * This is a well-known cute trick for isolating the rightmost one-bit
00034  * in a word.  It assumes two's complement arithmetic.  Consider any
00035  * nonzero value, and focus attention on the rightmost one.  The value is
00036  * then something like
00037  *              xxxxxx10000
00038  * where x's are unspecified bits.  The two's complement negative is formed
00039  * by inverting all the bits and adding one.  Inversion gives
00040  *              yyyyyy01111
00041  * where each y is the inverse of the corresponding x.  Incrementing gives
00042  *              yyyyyy10000
00043  * and then ANDing with the original value gives
00044  *              00000010000
00045  * This works for all cases except original value = zero, where of course
00046  * we get zero.
00047  *----------
00048  */
00049 #define RIGHTMOST_ONE(x) ((signedbitmapword) (x) & -((signedbitmapword) (x)))
00050 
00051 #define HAS_MULTIPLE_ONES(x)    ((bitmapword) RIGHTMOST_ONE(x) != (x))
00052 
00053 
00054 /*
00055  * Lookup tables to avoid need for bit-by-bit groveling
00056  *
00057  * rightmost_one_pos[x] gives the bit number (0-7) of the rightmost one bit
00058  * in a nonzero byte value x.  The entry for x=0 is never used.
00059  *
00060  * number_of_ones[x] gives the number of one-bits (0-8) in a byte value x.
00061  *
00062  * We could make these tables larger and reduce the number of iterations
00063  * in the functions that use them, but bytewise shifts and masks are
00064  * especially fast on many machines, so working a byte at a time seems best.
00065  */
00066 
00067 static const uint8 rightmost_one_pos[256] = {
00068     0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00069     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00070     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00071     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00072     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00073     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00074     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00075     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00076     7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00077     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00078     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00079     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00080     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00081     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00082     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
00083     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
00084 };
00085 
00086 static const uint8 number_of_ones[256] = {
00087     0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
00088     1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00089     1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00090     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00091     1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00092     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00093     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00094     3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00095     1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00096     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00097     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00098     3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00099     2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00100     3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00101     3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00102     4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
00103 };
00104 
00105 
00106 /*
00107  * bms_copy - make a palloc'd copy of a bitmapset
00108  */
00109 Bitmapset *
00110 bms_copy(const Bitmapset *a)
00111 {
00112     Bitmapset  *result;
00113     size_t      size;
00114 
00115     if (a == NULL)
00116         return NULL;
00117     size = BITMAPSET_SIZE(a->nwords);
00118     result = (Bitmapset *) palloc(size);
00119     memcpy(result, a, size);
00120     return result;
00121 }
00122 
00123 /*
00124  * bms_equal - are two bitmapsets equal?
00125  *
00126  * This is logical not physical equality; in particular, a NULL pointer will
00127  * be reported as equal to a palloc'd value containing no members.
00128  */
00129 bool
00130 bms_equal(const Bitmapset *a, const Bitmapset *b)
00131 {
00132     const Bitmapset *shorter;
00133     const Bitmapset *longer;
00134     int         shortlen;
00135     int         longlen;
00136     int         i;
00137 
00138     /* Handle cases where either input is NULL */
00139     if (a == NULL)
00140     {
00141         if (b == NULL)
00142             return true;
00143         return bms_is_empty(b);
00144     }
00145     else if (b == NULL)
00146         return bms_is_empty(a);
00147     /* Identify shorter and longer input */
00148     if (a->nwords <= b->nwords)
00149     {
00150         shorter = a;
00151         longer = b;
00152     }
00153     else
00154     {
00155         shorter = b;
00156         longer = a;
00157     }
00158     /* And process */
00159     shortlen = shorter->nwords;
00160     for (i = 0; i < shortlen; i++)
00161     {
00162         if (shorter->words[i] != longer->words[i])
00163             return false;
00164     }
00165     longlen = longer->nwords;
00166     for (; i < longlen; i++)
00167     {
00168         if (longer->words[i] != 0)
00169             return false;
00170     }
00171     return true;
00172 }
00173 
00174 /*
00175  * bms_make_singleton - build a bitmapset containing a single member
00176  */
00177 Bitmapset *
00178 bms_make_singleton(int x)
00179 {
00180     Bitmapset  *result;
00181     int         wordnum,
00182                 bitnum;
00183 
00184     if (x < 0)
00185         elog(ERROR, "negative bitmapset member not allowed");
00186     wordnum = WORDNUM(x);
00187     bitnum = BITNUM(x);
00188     result = (Bitmapset *) palloc0(BITMAPSET_SIZE(wordnum + 1));
00189     result->nwords = wordnum + 1;
00190     result->words[wordnum] = ((bitmapword) 1 << bitnum);
00191     return result;
00192 }
00193 
00194 /*
00195  * bms_free - free a bitmapset
00196  *
00197  * Same as pfree except for allowing NULL input
00198  */
00199 void
00200 bms_free(Bitmapset *a)
00201 {
00202     if (a)
00203         pfree(a);
00204 }
00205 
00206 
00207 /*
00208  * These operations all make a freshly palloc'd result,
00209  * leaving their inputs untouched
00210  */
00211 
00212 
00213 /*
00214  * bms_union - set union
00215  */
00216 Bitmapset *
00217 bms_union(const Bitmapset *a, const Bitmapset *b)
00218 {
00219     Bitmapset  *result;
00220     const Bitmapset *other;
00221     int         otherlen;
00222     int         i;
00223 
00224     /* Handle cases where either input is NULL */
00225     if (a == NULL)
00226         return bms_copy(b);
00227     if (b == NULL)
00228         return bms_copy(a);
00229     /* Identify shorter and longer input; copy the longer one */
00230     if (a->nwords <= b->nwords)
00231     {
00232         result = bms_copy(b);
00233         other = a;
00234     }
00235     else
00236     {
00237         result = bms_copy(a);
00238         other = b;
00239     }
00240     /* And union the shorter input into the result */
00241     otherlen = other->nwords;
00242     for (i = 0; i < otherlen; i++)
00243         result->words[i] |= other->words[i];
00244     return result;
00245 }
00246 
00247 /*
00248  * bms_intersect - set intersection
00249  */
00250 Bitmapset *
00251 bms_intersect(const Bitmapset *a, const Bitmapset *b)
00252 {
00253     Bitmapset  *result;
00254     const Bitmapset *other;
00255     int         resultlen;
00256     int         i;
00257 
00258     /* Handle cases where either input is NULL */
00259     if (a == NULL || b == NULL)
00260         return NULL;
00261     /* Identify shorter and longer input; copy the shorter one */
00262     if (a->nwords <= b->nwords)
00263     {
00264         result = bms_copy(a);
00265         other = b;
00266     }
00267     else
00268     {
00269         result = bms_copy(b);
00270         other = a;
00271     }
00272     /* And intersect the longer input with the result */
00273     resultlen = result->nwords;
00274     for (i = 0; i < resultlen; i++)
00275         result->words[i] &= other->words[i];
00276     return result;
00277 }
00278 
00279 /*
00280  * bms_difference - set difference (ie, A without members of B)
00281  */
00282 Bitmapset *
00283 bms_difference(const Bitmapset *a, const Bitmapset *b)
00284 {
00285     Bitmapset  *result;
00286     int         shortlen;
00287     int         i;
00288 
00289     /* Handle cases where either input is NULL */
00290     if (a == NULL)
00291         return NULL;
00292     if (b == NULL)
00293         return bms_copy(a);
00294     /* Copy the left input */
00295     result = bms_copy(a);
00296     /* And remove b's bits from result */
00297     shortlen = Min(a->nwords, b->nwords);
00298     for (i = 0; i < shortlen; i++)
00299         result->words[i] &= ~b->words[i];
00300     return result;
00301 }
00302 
00303 /*
00304  * bms_is_subset - is A a subset of B?
00305  */
00306 bool
00307 bms_is_subset(const Bitmapset *a, const Bitmapset *b)
00308 {
00309     int         shortlen;
00310     int         longlen;
00311     int         i;
00312 
00313     /* Handle cases where either input is NULL */
00314     if (a == NULL)
00315         return true;            /* empty set is a subset of anything */
00316     if (b == NULL)
00317         return bms_is_empty(a);
00318     /* Check common words */
00319     shortlen = Min(a->nwords, b->nwords);
00320     for (i = 0; i < shortlen; i++)
00321     {
00322         if ((a->words[i] & ~b->words[i]) != 0)
00323             return false;
00324     }
00325     /* Check extra words */
00326     if (a->nwords > b->nwords)
00327     {
00328         longlen = a->nwords;
00329         for (; i < longlen; i++)
00330         {
00331             if (a->words[i] != 0)
00332                 return false;
00333         }
00334     }
00335     return true;
00336 }
00337 
00338 /*
00339  * bms_subset_compare - compare A and B for equality/subset relationships
00340  *
00341  * This is more efficient than testing bms_is_subset in both directions.
00342  */
00343 BMS_Comparison
00344 bms_subset_compare(const Bitmapset *a, const Bitmapset *b)
00345 {
00346     BMS_Comparison result;
00347     int         shortlen;
00348     int         longlen;
00349     int         i;
00350 
00351     /* Handle cases where either input is NULL */
00352     if (a == NULL)
00353     {
00354         if (b == NULL)
00355             return BMS_EQUAL;
00356         return bms_is_empty(b) ? BMS_EQUAL : BMS_SUBSET1;
00357     }
00358     if (b == NULL)
00359         return bms_is_empty(a) ? BMS_EQUAL : BMS_SUBSET2;
00360     /* Check common words */
00361     result = BMS_EQUAL;         /* status so far */
00362     shortlen = Min(a->nwords, b->nwords);
00363     for (i = 0; i < shortlen; i++)
00364     {
00365         bitmapword  aword = a->words[i];
00366         bitmapword  bword = b->words[i];
00367 
00368         if ((aword & ~bword) != 0)
00369         {
00370             /* a is not a subset of b */
00371             if (result == BMS_SUBSET1)
00372                 return BMS_DIFFERENT;
00373             result = BMS_SUBSET2;
00374         }
00375         if ((bword & ~aword) != 0)
00376         {
00377             /* b is not a subset of a */
00378             if (result == BMS_SUBSET2)
00379                 return BMS_DIFFERENT;
00380             result = BMS_SUBSET1;
00381         }
00382     }
00383     /* Check extra words */
00384     if (a->nwords > b->nwords)
00385     {
00386         longlen = a->nwords;
00387         for (; i < longlen; i++)
00388         {
00389             if (a->words[i] != 0)
00390             {
00391                 /* a is not a subset of b */
00392                 if (result == BMS_SUBSET1)
00393                     return BMS_DIFFERENT;
00394                 result = BMS_SUBSET2;
00395             }
00396         }
00397     }
00398     else if (a->nwords < b->nwords)
00399     {
00400         longlen = b->nwords;
00401         for (; i < longlen; i++)
00402         {
00403             if (b->words[i] != 0)
00404             {
00405                 /* b is not a subset of a */
00406                 if (result == BMS_SUBSET2)
00407                     return BMS_DIFFERENT;
00408                 result = BMS_SUBSET1;
00409             }
00410         }
00411     }
00412     return result;
00413 }
00414 
00415 /*
00416  * bms_is_member - is X a member of A?
00417  */
00418 bool
00419 bms_is_member(int x, const Bitmapset *a)
00420 {
00421     int         wordnum,
00422                 bitnum;
00423 
00424     /* XXX better to just return false for x<0 ? */
00425     if (x < 0)
00426         elog(ERROR, "negative bitmapset member not allowed");
00427     if (a == NULL)
00428         return false;
00429     wordnum = WORDNUM(x);
00430     bitnum = BITNUM(x);
00431     if (wordnum >= a->nwords)
00432         return false;
00433     if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
00434         return true;
00435     return false;
00436 }
00437 
00438 /*
00439  * bms_overlap - do sets overlap (ie, have a nonempty intersection)?
00440  */
00441 bool
00442 bms_overlap(const Bitmapset *a, const Bitmapset *b)
00443 {
00444     int         shortlen;
00445     int         i;
00446 
00447     /* Handle cases where either input is NULL */
00448     if (a == NULL || b == NULL)
00449         return false;
00450     /* Check words in common */
00451     shortlen = Min(a->nwords, b->nwords);
00452     for (i = 0; i < shortlen; i++)
00453     {
00454         if ((a->words[i] & b->words[i]) != 0)
00455             return true;
00456     }
00457     return false;
00458 }
00459 
00460 /*
00461  * bms_nonempty_difference - do sets have a nonempty difference?
00462  */
00463 bool
00464 bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
00465 {
00466     int         shortlen;
00467     int         i;
00468 
00469     /* Handle cases where either input is NULL */
00470     if (a == NULL)
00471         return false;
00472     if (b == NULL)
00473         return !bms_is_empty(a);
00474     /* Check words in common */
00475     shortlen = Min(a->nwords, b->nwords);
00476     for (i = 0; i < shortlen; i++)
00477     {
00478         if ((a->words[i] & ~b->words[i]) != 0)
00479             return true;
00480     }
00481     /* Check extra words in a */
00482     for (; i < a->nwords; i++)
00483     {
00484         if (a->words[i] != 0)
00485             return true;
00486     }
00487     return false;
00488 }
00489 
00490 /*
00491  * bms_singleton_member - return the sole integer member of set
00492  *
00493  * Raises error if |a| is not 1.
00494  */
00495 int
00496 bms_singleton_member(const Bitmapset *a)
00497 {
00498     int         result = -1;
00499     int         nwords;
00500     int         wordnum;
00501 
00502     if (a == NULL)
00503         elog(ERROR, "bitmapset is empty");
00504     nwords = a->nwords;
00505     for (wordnum = 0; wordnum < nwords; wordnum++)
00506     {
00507         bitmapword  w = a->words[wordnum];
00508 
00509         if (w != 0)
00510         {
00511             if (result >= 0 || HAS_MULTIPLE_ONES(w))
00512                 elog(ERROR, "bitmapset has multiple members");
00513             result = wordnum * BITS_PER_BITMAPWORD;
00514             while ((w & 255) == 0)
00515             {
00516                 w >>= 8;
00517                 result += 8;
00518             }
00519             result += rightmost_one_pos[w & 255];
00520         }
00521     }
00522     if (result < 0)
00523         elog(ERROR, "bitmapset is empty");
00524     return result;
00525 }
00526 
00527 /*
00528  * bms_num_members - count members of set
00529  */
00530 int
00531 bms_num_members(const Bitmapset *a)
00532 {
00533     int         result = 0;
00534     int         nwords;
00535     int         wordnum;
00536 
00537     if (a == NULL)
00538         return 0;
00539     nwords = a->nwords;
00540     for (wordnum = 0; wordnum < nwords; wordnum++)
00541     {
00542         bitmapword  w = a->words[wordnum];
00543 
00544         /* we assume here that bitmapword is an unsigned type */
00545         while (w != 0)
00546         {
00547             result += number_of_ones[w & 255];
00548             w >>= 8;
00549         }
00550     }
00551     return result;
00552 }
00553 
00554 /*
00555  * bms_membership - does a set have zero, one, or multiple members?
00556  *
00557  * This is faster than making an exact count with bms_num_members().
00558  */
00559 BMS_Membership
00560 bms_membership(const Bitmapset *a)
00561 {
00562     BMS_Membership result = BMS_EMPTY_SET;
00563     int         nwords;
00564     int         wordnum;
00565 
00566     if (a == NULL)
00567         return BMS_EMPTY_SET;
00568     nwords = a->nwords;
00569     for (wordnum = 0; wordnum < nwords; wordnum++)
00570     {
00571         bitmapword  w = a->words[wordnum];
00572 
00573         if (w != 0)
00574         {
00575             if (result != BMS_EMPTY_SET || HAS_MULTIPLE_ONES(w))
00576                 return BMS_MULTIPLE;
00577             result = BMS_SINGLETON;
00578         }
00579     }
00580     return result;
00581 }
00582 
00583 /*
00584  * bms_is_empty - is a set empty?
00585  *
00586  * This is even faster than bms_membership().
00587  */
00588 bool
00589 bms_is_empty(const Bitmapset *a)
00590 {
00591     int         nwords;
00592     int         wordnum;
00593 
00594     if (a == NULL)
00595         return true;
00596     nwords = a->nwords;
00597     for (wordnum = 0; wordnum < nwords; wordnum++)
00598     {
00599         bitmapword  w = a->words[wordnum];
00600 
00601         if (w != 0)
00602             return false;
00603     }
00604     return true;
00605 }
00606 
00607 
00608 /*
00609  * These operations all "recycle" their non-const inputs, ie, either
00610  * return the modified input or pfree it if it can't hold the result.
00611  *
00612  * These should generally be used in the style
00613  *
00614  *      foo = bms_add_member(foo, x);
00615  */
00616 
00617 
00618 /*
00619  * bms_add_member - add a specified member to set
00620  *
00621  * Input set is modified or recycled!
00622  */
00623 Bitmapset *
00624 bms_add_member(Bitmapset *a, int x)
00625 {
00626     int         wordnum,
00627                 bitnum;
00628 
00629     if (x < 0)
00630         elog(ERROR, "negative bitmapset member not allowed");
00631     if (a == NULL)
00632         return bms_make_singleton(x);
00633     wordnum = WORDNUM(x);
00634     bitnum = BITNUM(x);
00635     if (wordnum >= a->nwords)
00636     {
00637         /* Slow path: make a larger set and union the input set into it */
00638         Bitmapset  *result;
00639         int         nwords;
00640         int         i;
00641 
00642         result = bms_make_singleton(x);
00643         nwords = a->nwords;
00644         for (i = 0; i < nwords; i++)
00645             result->words[i] |= a->words[i];
00646         pfree(a);
00647         return result;
00648     }
00649     /* Fast path: x fits in existing set */
00650     a->words[wordnum] |= ((bitmapword) 1 << bitnum);
00651     return a;
00652 }
00653 
00654 /*
00655  * bms_del_member - remove a specified member from set
00656  *
00657  * No error if x is not currently a member of set
00658  *
00659  * Input set is modified in-place!
00660  */
00661 Bitmapset *
00662 bms_del_member(Bitmapset *a, int x)
00663 {
00664     int         wordnum,
00665                 bitnum;
00666 
00667     if (x < 0)
00668         elog(ERROR, "negative bitmapset member not allowed");
00669     if (a == NULL)
00670         return NULL;
00671     wordnum = WORDNUM(x);
00672     bitnum = BITNUM(x);
00673     if (wordnum < a->nwords)
00674         a->words[wordnum] &= ~((bitmapword) 1 << bitnum);
00675     return a;
00676 }
00677 
00678 /*
00679  * bms_add_members - like bms_union, but left input is recycled
00680  */
00681 Bitmapset *
00682 bms_add_members(Bitmapset *a, const Bitmapset *b)
00683 {
00684     Bitmapset  *result;
00685     const Bitmapset *other;
00686     int         otherlen;
00687     int         i;
00688 
00689     /* Handle cases where either input is NULL */
00690     if (a == NULL)
00691         return bms_copy(b);
00692     if (b == NULL)
00693         return a;
00694     /* Identify shorter and longer input; copy the longer one if needed */
00695     if (a->nwords < b->nwords)
00696     {
00697         result = bms_copy(b);
00698         other = a;
00699     }
00700     else
00701     {
00702         result = a;
00703         other = b;
00704     }
00705     /* And union the shorter input into the result */
00706     otherlen = other->nwords;
00707     for (i = 0; i < otherlen; i++)
00708         result->words[i] |= other->words[i];
00709     if (result != a)
00710         pfree(a);
00711     return result;
00712 }
00713 
00714 /*
00715  * bms_int_members - like bms_intersect, but left input is recycled
00716  */
00717 Bitmapset *
00718 bms_int_members(Bitmapset *a, const Bitmapset *b)
00719 {
00720     int         shortlen;
00721     int         i;
00722 
00723     /* Handle cases where either input is NULL */
00724     if (a == NULL)
00725         return NULL;
00726     if (b == NULL)
00727     {
00728         pfree(a);
00729         return NULL;
00730     }
00731     /* Intersect b into a; we need never copy */
00732     shortlen = Min(a->nwords, b->nwords);
00733     for (i = 0; i < shortlen; i++)
00734         a->words[i] &= b->words[i];
00735     for (; i < a->nwords; i++)
00736         a->words[i] = 0;
00737     return a;
00738 }
00739 
00740 /*
00741  * bms_del_members - like bms_difference, but left input is recycled
00742  */
00743 Bitmapset *
00744 bms_del_members(Bitmapset *a, const Bitmapset *b)
00745 {
00746     int         shortlen;
00747     int         i;
00748 
00749     /* Handle cases where either input is NULL */
00750     if (a == NULL)
00751         return NULL;
00752     if (b == NULL)
00753         return a;
00754     /* Remove b's bits from a; we need never copy */
00755     shortlen = Min(a->nwords, b->nwords);
00756     for (i = 0; i < shortlen; i++)
00757         a->words[i] &= ~b->words[i];
00758     return a;
00759 }
00760 
00761 /*
00762  * bms_join - like bms_union, but *both* inputs are recycled
00763  */
00764 Bitmapset *
00765 bms_join(Bitmapset *a, Bitmapset *b)
00766 {
00767     Bitmapset  *result;
00768     Bitmapset  *other;
00769     int         otherlen;
00770     int         i;
00771 
00772     /* Handle cases where either input is NULL */
00773     if (a == NULL)
00774         return b;
00775     if (b == NULL)
00776         return a;
00777     /* Identify shorter and longer input; use longer one as result */
00778     if (a->nwords < b->nwords)
00779     {
00780         result = b;
00781         other = a;
00782     }
00783     else
00784     {
00785         result = a;
00786         other = b;
00787     }
00788     /* And union the shorter input into the result */
00789     otherlen = other->nwords;
00790     for (i = 0; i < otherlen; i++)
00791         result->words[i] |= other->words[i];
00792     if (other != result)        /* pure paranoia */
00793         pfree(other);
00794     return result;
00795 }
00796 
00797 /*----------
00798  * bms_first_member - find and remove first member of a set
00799  *
00800  * Returns -1 if set is empty.  NB: set is destructively modified!
00801  *
00802  * This is intended as support for iterating through the members of a set.
00803  * The typical pattern is
00804  *
00805  *          tmpset = bms_copy(inputset);
00806  *          while ((x = bms_first_member(tmpset)) >= 0)
00807  *              process member x;
00808  *          bms_free(tmpset);
00809  *----------
00810  */
00811 int
00812 bms_first_member(Bitmapset *a)
00813 {
00814     int         nwords;
00815     int         wordnum;
00816 
00817     if (a == NULL)
00818         return -1;
00819     nwords = a->nwords;
00820     for (wordnum = 0; wordnum < nwords; wordnum++)
00821     {
00822         bitmapword  w = a->words[wordnum];
00823 
00824         if (w != 0)
00825         {
00826             int         result;
00827 
00828             w = RIGHTMOST_ONE(w);
00829             a->words[wordnum] &= ~w;
00830 
00831             result = wordnum * BITS_PER_BITMAPWORD;
00832             while ((w & 255) == 0)
00833             {
00834                 w >>= 8;
00835                 result += 8;
00836             }
00837             result += rightmost_one_pos[w & 255];
00838             return result;
00839         }
00840     }
00841     return -1;
00842 }
00843 
00844 /*
00845  * bms_hash_value - compute a hash key for a Bitmapset
00846  *
00847  * Note: we must ensure that any two bitmapsets that are bms_equal() will
00848  * hash to the same value; in practice this means that trailing all-zero
00849  * words must not affect the result.  Hence we strip those before applying
00850  * hash_any().
00851  */
00852 uint32
00853 bms_hash_value(const Bitmapset *a)
00854 {
00855     int         lastword;
00856 
00857     if (a == NULL)
00858         return 0;               /* All empty sets hash to 0 */
00859     for (lastword = a->nwords; --lastword >= 0;)
00860     {
00861         if (a->words[lastword] != 0)
00862             break;
00863     }
00864     if (lastword < 0)
00865         return 0;               /* All empty sets hash to 0 */
00866     return DatumGetUInt32(hash_any((const unsigned char *) a->words,
00867                                    (lastword + 1) * sizeof(bitmapword)));
00868 }