aboutsummaryrefslogtreecommitdiff
path: root/src/backend/nodes/bitmapset.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/nodes/bitmapset.c')
-rw-r--r--src/backend/nodes/bitmapset.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c
index 07e6f03a871..4ad17d0c31e 100644
--- a/src/backend/nodes/bitmapset.c
+++ b/src/backend/nodes/bitmapset.c
@@ -444,6 +444,50 @@ bms_is_member(int x, const Bitmapset *a)
}
/*
+ * bms_member_index
+ * determine 0-based index of member x in the bitmap
+ *
+ * Returns (-1) when x is not a member.
+ */
+int
+bms_member_index(Bitmapset *a, int x)
+{
+ int i;
+ int bitnum;
+ int wordnum;
+ int result = 0;
+ bitmapword mask;
+
+ /* 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);
+ }
+
+ /*
+ * Now add bits of the last word, but only those before the item.
+ * We can do that by applying a mask and then using popcount again.
+ * To get 0-based index, we want to count only preceding bits, not
+ * the item itself, so we subtract 1.
+ */
+ mask = ((bitmapword) 1 << bitnum) - 1;
+ result += bmw_popcount(a->words[wordnum] & mask);
+
+ return result;
+}
+
+/*
* bms_overlap - do sets overlap (ie, have a nonempty intersection)?
*/
bool