#ifdef USE_ASSERT_CHECKING /* *bms_is_valid_set-forcassertbuildstocheckforvalidsets
*/ staticbool
bms_is_valid_set(const Bitmapset *a)
{ /* NULL is the correct representation of an empty set */ if (a == NULL) returntrue;
/* check the node tag is set correctly. pfree'd pointer, maybe? */ if (!IsA(a, Bitmapset)) returnfalse;
/* trailing zero words are not allowed */ if (a->words[a->nwords - 1] == 0) returnfalse;
/* Handle cases where either input is NULL */ if (a == NULL) return bms_copy(b); if (b == NULL) return bms_copy(a); /* Identify shorter and longer input; copy the longer one */ if (a->nwords <= b->nwords)
{
result = bms_copy(b);
other = a;
} else
{
result = bms_copy(a);
other = b;
} /* And union the shorter input into the result */
otherlen = other->nwords;
i = 0; do
{
result->words[i] |= other->words[i];
} while (++i < otherlen); return result;
}
/* *bms_intersect-createandreturnanewsetcontainingmemberswhichboth *inputsetshaveincommon.Bothinputsareleftunmodified.
*/
Bitmapset *
bms_intersect(const Bitmapset *a, const Bitmapset *b)
{
Bitmapset *result; const Bitmapset *other; int lastnonzero; int resultlen; int i;
/* Handle cases where either input is NULL */ if (a == NULL || b == NULL) return NULL;
/* Identify shorter and longer input; copy the shorter one */ if (a->nwords <= b->nwords)
{
result = bms_copy(a);
other = b;
} else
{
result = bms_copy(b);
other = a;
} /* And intersect the longer input with the result */
resultlen = result->nwords;
lastnonzero = -1;
i = 0; do
{
result->words[i] &= other->words[i];
if (result->words[i] != 0)
lastnonzero = i;
} while (++i < resultlen); /* If we computed an empty result, we must return NULL */ if (lastnonzero == -1)
{
pfree(result); return NULL;
}
/* get rid of trailing zero words */
result->nwords = lastnonzero + 1; return result;
}
/* Handle cases where either input is NULL */ if (a == NULL) return NULL; if (b == NULL) return bms_copy(a);
/* *InPostgres'usage,anemptyresultisaverycommoncase,soit's *worthoptimizingforthatbytestingbms_nonempty_difference().This *savesusapalloc/pfreecyclecomparedtocheckingafter-the-fact.
*/ if (!bms_nonempty_difference(a, b)) return NULL;
/* Copy the left input */
result = bms_copy(a);
/* And remove b's bits from result */ if (result->nwords > b->nwords)
{ /* *We'llneverneedtoremovetrailingzerowordswhen'a'hasmore *wordsthan'b'astheadditionalwordsmustbenon-zero.
*/
i = 0; do
{
result->words[i] &= ~b->words[i];
} while (++i < b->nwords);
} else
{ int lastnonzero = -1;
/* we may need to remove trailing zero words from the result. */
i = 0; do
{
result->words[i] &= ~b->words[i];
/* remember the last non-zero word */ if (result->words[i] != 0)
lastnonzero = i;
} while (++i < result->nwords);
/* trim off trailing zero words */
result->nwords = lastnonzero + 1;
}
Assert(result->nwords != 0);
/* Need not check for empty result, since we handled that case above */ return result;
}
/* Handle cases where either input is NULL */ if (a == NULL)
{ if (b == NULL) return BMS_EQUAL; return BMS_SUBSET1;
} if (b == NULL) return BMS_SUBSET2;
/* Check common words */
result = BMS_EQUAL; /* status so far */
shortlen = Min(a->nwords, b->nwords);
i = 0; do
{
bitmapword aword = a->words[i];
bitmapword bword = b->words[i];
if ((aword & ~bword) != 0)
{ /* a is not a subset of b */ if (result == BMS_SUBSET1) return BMS_DIFFERENT;
result = BMS_SUBSET2;
} if ((bword & ~aword) != 0)
{ /* b is not a subset of a */ if (result == BMS_SUBSET2) return BMS_DIFFERENT;
result = BMS_SUBSET1;
}
} while (++i < shortlen); /* Check extra words */ if (a->nwords > b->nwords)
{ /* if a has more words then a is not a subset of b */ if (result == BMS_SUBSET1) return BMS_DIFFERENT; return BMS_SUBSET2;
} elseif (a->nwords < b->nwords)
{ /* if b has more words then b is not a subset of a */ if (result == BMS_SUBSET2) return BMS_DIFFERENT; return BMS_SUBSET1;
} return result;
}
/* *bms_member_index *determine0-basedindexofmemberxinthebitmap * *Returns(-1)whenxisnotamember.
*/ int
bms_member_index(Bitmapset *a, int x)
{ int i; int bitnum; int wordnum; int result = 0;
bitmapword mask;
Assert(bms_is_valid_set(a));
/* return -1 if not a member of the bitmap */ if (!bms_is_member(x, a)) return -1;
wordnum = WORDNUM(x);
bitnum = BITNUM(x);
/* count bits in preceding words */ for (i = 0; i < wordnum; i++)
{
bitmapword w = a->words[i];
/* No need to count the bits in a zero word */ if (w != 0)
result += bmw_popcount(w);
}
/* Handle cases where either input is NULL */ if (a == NULL || b == NULL) returnfalse; /* Check words in common */
shortlen = Min(a->nwords, b->nwords);
i = 0; do
{ if ((a->words[i] & b->words[i]) != 0) returntrue;
} while (++i < shortlen); returnfalse;
}
/* *bms_overlap_list-doesasetoverlapanintegerlist?
*/ bool
bms_overlap_list(const Bitmapset *a, const List *b)
{
ListCell *lc; int wordnum,
bitnum;
Assert(bms_is_valid_set(a));
if (a == NULL || b == NIL) returnfalse;
foreach(lc, b)
{ int x = lfirst_int(lc);
if (x < 0)
elog(ERROR, "negative bitmapset member not allowed");
wordnum = WORDNUM(x);
bitnum = BITNUM(x); if (wordnum < a->nwords) if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0) returntrue;
}
/* Handle cases where either input is NULL */ if (a == NULL) returnfalse; if (b == NULL) returntrue; /* if 'a' has more words then it must contain additional members */ if (a->nwords > b->nwords) returntrue; /* Check all 'a' members are set in 'b' */
i = 0; do
{ if ((a->words[i] & ~b->words[i]) != 0) returntrue;
} while (++i < a->nwords); returnfalse;
}
/* *bms_singleton_member-returnthesoleintegermemberofset * *Raiseserrorif|a|isnot1.
*/ int
bms_singleton_member(const Bitmapset *a)
{ int result = -1; int nwords; int wordnum;
Assert(bms_is_valid_set(a));
if (a == NULL)
elog(ERROR, "bitmapset is empty");
nwords = a->nwords;
wordnum = 0; do
{
bitmapword w = a->words[wordnum];
if (w != 0)
{ if (result >= 0 || HAS_MULTIPLE_ONES(w))
elog(ERROR, "bitmapset has multiple members");
result = wordnum * BITS_PER_BITMAPWORD;
result += bmw_rightmost_one_pos(w);
}
} while (++wordnum < nwords);
/* we don't expect non-NULL sets to be empty */
Assert(result >= 0); return result;
}
/* *bms_get_singleton_member * *Testwhetherthegivensetisasingleton. *Ifso,set*membertothevalueofitssolemember,andreturntrue. *Ifnot,returnfalse,withoutchanging*member. * *Thisismoreconvenientandfasterthancallingbms_membership()andthen *bms_singleton_member(),ifwedon'tcareaboutdistinguishingemptysets *frommultiple-membersets.
*/ bool
bms_get_singleton_member(const Bitmapset *a, int *member)
{ int result = -1; int nwords; int wordnum;
Assert(bms_is_valid_set(a));
if (a == NULL) returnfalse;
nwords = a->nwords;
wordnum = 0; do
{
bitmapword w = a->words[wordnum];
if (w != 0)
{ if (result >= 0 || HAS_MULTIPLE_ONES(w)) returnfalse;
result = wordnum * BITS_PER_BITMAPWORD;
result += bmw_rightmost_one_pos(w);
}
} while (++wordnum < nwords);
/* we don't expect non-NULL sets to be empty */
Assert(result >= 0);
*member = result; returntrue;
}
/* *bms_num_members-countmembersofset
*/ int
bms_num_members(const Bitmapset *a)
{ int result = 0; int nwords; int wordnum;
Assert(bms_is_valid_set(a));
if (a == NULL) return0;
nwords = a->nwords;
wordnum = 0; do
{
bitmapword w = a->words[wordnum];
/* No need to count the bits in a zero word */ if (w != 0)
result += bmw_popcount(w);
} while (++wordnum < nwords); return result;
}
/* *bms_membership-doesasethavezero,one,ormultiplemembers? * *Thisisfasterthanmakinganexactcountwithbms_num_members().
*/
BMS_Membership
bms_membership(const Bitmapset *a)
{
BMS_Membership result = BMS_EMPTY_SET; int nwords; int wordnum;
Assert(bms_is_valid_set(a));
if (a == NULL) return BMS_EMPTY_SET;
nwords = a->nwords;
wordnum = 0; do
{
bitmapword w = a->words[wordnum];
if (w != 0)
{ if (result != BMS_EMPTY_SET || HAS_MULTIPLE_ONES(w)) return BMS_MULTIPLE;
result = BMS_SINGLETON;
}
} while (++wordnum < nwords); return result;
}
/* *bms_add_member-addaspecifiedmembertoset * *'a'isrecycledwhenpossible.
*/
Bitmapset *
bms_add_member(Bitmapset *a, int x)
{ int wordnum,
bitnum;
Assert(bms_is_valid_set(a));
if (x < 0)
elog(ERROR, "negative bitmapset member not allowed"); if (a == NULL) return bms_make_singleton(x);
wordnum = WORDNUM(x);
bitnum = BITNUM(x);
/* enlarge the set if necessary */ if (wordnum >= a->nwords)
{ int oldnwords = a->nwords; int i;
a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(wordnum + 1));
a->nwords = wordnum + 1; /* zero out the enlarged portion */
i = oldnwords; do
{
a->words[i] = 0;
} while (++i < a->nwords);
}
a->words[wordnum] |= ((bitmapword) 1 << bitnum);
#ifdef REALLOCATE_BITMAPSETS
/* *There'snoguaranteethattherepallocreturnedanewpointer,socopy *andfreeunconditionallyhere.
*/
a = bms_copy_and_free(a); #endif
return a;
}
/* *bms_del_member-removeaspecifiedmemberfromset * *Noerrorifxisnotcurrentlyamemberofset * *'a'isrecycledwhenpossible.
*/
Bitmapset *
bms_del_member(Bitmapset *a, int x)
{ int wordnum,
bitnum;
Assert(bms_is_valid_set(a));
if (x < 0)
elog(ERROR, "negative bitmapset member not allowed"); if (a == NULL) return NULL;
wordnum = WORDNUM(x);
bitnum = BITNUM(x);
#ifdef REALLOCATE_BITMAPSETS
a = bms_copy_and_free(a); #endif
/* member can't exist. Return 'a' unmodified */ if (unlikely(wordnum >= a->nwords)) return a;
a->words[wordnum] &= ~((bitmapword) 1 << bitnum);
/* when last word becomes empty, trim off all trailing empty words */ if (a->words[wordnum] == 0 && wordnum == a->nwords - 1)
{ /* find the last non-empty word and make that the new final word */ for (int i = wordnum - 1; i >= 0; i--)
{ if (a->words[i] != 0)
{
a->nwords = i + 1; return a;
}
}
/* the set is now empty */
pfree(a); return NULL;
} return a;
}
/* *bms_add_members-likebms_union,butleftinputisrecycledwhenpossible
*/
Bitmapset *
bms_add_members(Bitmapset *a, const Bitmapset *b)
{
Bitmapset *result; const Bitmapset *other; int otherlen; int i;
/* Handle cases where either input is NULL */ if (a == NULL) return bms_copy(b); if (b == NULL)
{ #ifdef REALLOCATE_BITMAPSETS
a = bms_copy_and_free(a); #endif
return a;
} /* Identify shorter and longer input; copy the longer one if needed */ if (a->nwords < b->nwords)
{
result = bms_copy(b);
other = a;
} else
{
result = a;
other = b;
} /* And union the shorter input into the result */
otherlen = other->nwords;
i = 0; do
{
result->words[i] |= other->words[i];
} while (++i < otherlen); if (result != a)
pfree(a); #ifdef REALLOCATE_BITMAPSETS else
result = bms_copy_and_free(result); #endif
if (a == NULL) return bms_copy(b); if (b == NULL)
{
pfree(a); return NULL;
}
if (a->nwords < b->nwords)
a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(b->nwords));
i = 0; do
{
a->words[i] = b->words[i];
} while (++i < b->nwords);
a->nwords = b->nwords;
#ifdef REALLOCATE_BITMAPSETS
/* *There'snoguaranteethattherepallocreturnedanewpointer,socopy *andfreeunconditionallyhere.
*/
a = bms_copy_and_free(a); #endif
return a;
}
/* *bms_add_range *Addmembersintherangeof'lower'to'upper'totheset. * *Notethiscouldalsobedonebycallingbms_add_memberinaloop,however, *usingthisfunctionwillbefasterwhentherangeislargeasweworkat *thebitmapwordlevelratherthanatbitlevel.
*/
Bitmapset *
bms_add_range(Bitmapset *a, int lower, int upper)
{ int lwordnum,
lbitnum,
uwordnum,
ushiftbits,
wordnum;
Assert(bms_is_valid_set(a));
/* do nothing if nothing is called for, without further checking */ if (upper < lower)
{ #ifdef REALLOCATE_BITMAPSETS
a = bms_copy_and_free(a); #endif
return a;
}
if (lower < 0)
elog(ERROR, "negative bitmapset member not allowed");
uwordnum = WORDNUM(upper);
if (a == NULL)
{
a = (Bitmapset *) palloc0(BITMAPSET_SIZE(uwordnum + 1));
a->type = T_Bitmapset;
a->nwords = uwordnum + 1;
} elseif (uwordnum >= a->nwords)
{ int oldnwords = a->nwords; int i;
/* ensure we have enough words to store the upper bit */
a = (Bitmapset *) repalloc(a, BITMAPSET_SIZE(uwordnum + 1));
a->nwords = uwordnum + 1; /* zero out the enlarged portion */
i = oldnwords; do
{
a->words[i] = 0;
} while (++i < a->nwords);
}
/* Handle cases where either input is NULL */ if (a == NULL) return NULL; if (b == NULL)
{ #ifdef REALLOCATE_BITMAPSETS
a = bms_copy_and_free(a); #endif
return a;
}
/* Remove b's bits from a; we need never copy */ if (a->nwords > b->nwords)
{ /* *We'llneverneedtoremovetrailingzerowordswhen'a'hasmore *wordsthan'b'.
*/
i = 0; do
{
a->words[i] &= ~b->words[i];
} while (++i < b->nwords);
} else
{ int lastnonzero = -1;
/* we may need to remove trailing zero words from the result. */
i = 0; do
{
a->words[i] &= ~b->words[i];
/* remember the last non-zero word */ if (a->words[i] != 0)
lastnonzero = i;
} while (++i < a->nwords);
/* check if 'a' has become empty */ if (lastnonzero == -1)
{
pfree(a); return NULL;
}
/* trim off any trailing zero words */
a->nwords = lastnonzero + 1;
}
#ifdef REALLOCATE_BITMAPSETS
a = bms_copy_and_free(a); #endif
return a;
}
/* *bms_join-likebms_union,but*either*input*may*berecycled
*/
Bitmapset *
bms_join(Bitmapset *a, Bitmapset *b)
{
Bitmapset *result;
Bitmapset *other; int otherlen; int i;
/* Handle cases where either input is NULL */ if (a == NULL)
{ #ifdef REALLOCATE_BITMAPSETS
b = bms_copy_and_free(b); #endif
return b;
} if (b == NULL)
{ #ifdef REALLOCATE_BITMAPSETS
a = bms_copy_and_free(a); #endif
return a;
}
/* Identify shorter and longer input; use longer one as result */ if (a->nwords < b->nwords)
{
result = b;
other = a;
} else
{
result = a;
other = b;
} /* And union the shorter input into the result */
otherlen = other->nwords;
i = 0; do
{
result->words[i] |= other->words[i];
} while (++i < otherlen); if (other != result) /* pure paranoia */
pfree(other);
#ifdef REALLOCATE_BITMAPSETS
result = bms_copy_and_free(result); #endif
return result;
}
/* *bms_next_member-findnextmemberofaset * *Returnssmallestmembergreaterthan"prevbit",or-2ifthereisnone. *"prevbit"mustNOTbelessthan-1,orthebehaviorisunpredictable. * *Thisisintendedassupportforiteratingthroughthemembersofaset. *Thetypicalpatternis * *x=-1; *while((x=bms_next_member(inputset,x))>=0) *processmemberx; * *Noticethatwhentherearenomoremembers,wereturn-2,not-1asyou *mightexpect.Therationaleforthatistoallowdistinguishingthe *loop-not-startedstate(x==-1)fromtheloop-completedstate(x==-2). *Itmakesnodifferenceinsimpleloopusage,butcomplexiterationlogic *mightneedsuchanability.
*/ int
bms_next_member(const Bitmapset *a, int prevbit)
{ int nwords; int wordnum;
bitmapword mask;
Assert(bms_is_valid_set(a));
if (a == NULL) return -2;
nwords = a->nwords;
prevbit++;
mask = (~(bitmapword) 0) << BITNUM(prevbit); for (wordnum = WORDNUM(prevbit); wordnum < nwords; wordnum++)
{
bitmapword w = a->words[wordnum];
/* ignore bits before prevbit */
w &= mask;
if (w != 0)
{ int result;
result = wordnum * BITS_PER_BITMAPWORD;
result += bmw_rightmost_one_pos(w); return result;
}
/* in subsequent words, consider all bits */
mask = (~(bitmapword) 0);
} return -2;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.