📄 bitmapset.c
字号:
/*------------------------------------------------------------------------- * * bitmapset.c * PostgreSQL generic bitmap set package * * A bitmap set can represent any set of nonnegative integers, although * it is mainly intended for sets where the maximum value is not large, * say at most a few hundred. By convention, a NULL pointer is always * accepted by all operations to represent the empty set. (But beware * that this is not the only representation of the empty set. Use * bms_is_empty() in preference to testing for NULL.) * * * Copyright (c) 2003-2005, PostgreSQL Global Development Group * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/nodes/bitmapset.c,v 1.10 2005/10/15 02:49:18 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "nodes/bitmapset.h"#define WORDNUM(x) ((x) / BITS_PER_BITMAPWORD)#define BITNUM(x) ((x) % BITS_PER_BITMAPWORD)#define BITMAPSET_SIZE(nwords) \ (offsetof(Bitmapset, words) + (nwords) * sizeof(bitmapword))/*---------- * This is a well-known cute trick for isolating the rightmost one-bit * in a word. It assumes two's complement arithmetic. Consider any * nonzero value, and focus attention on the rightmost one. The value is * then something like * xxxxxx10000 * where x's are unspecified bits. The two's complement negative is formed * by inverting all the bits and adding one. Inversion gives * yyyyyy01111 * where each y is the inverse of the corresponding x. Incrementing gives * yyyyyy10000 * and then ANDing with the original value gives * 00000010000 * This works for all cases except original value = zero, where of course * we get zero. *---------- */#define RIGHTMOST_ONE(x) ((signedbitmapword) (x) & -((signedbitmapword) (x)))#define HAS_MULTIPLE_ONES(x) ((bitmapword) RIGHTMOST_ONE(x) != (x))/* * Lookup tables to avoid need for bit-by-bit groveling * * rightmost_one_pos[x] gives the bit number (0-7) of the rightmost one bit * in a nonzero byte value x. The entry for x=0 is never used. * * number_of_ones[x] gives the number of one-bits (0-8) in a byte value x. * * We could make these tables larger and reduce the number of iterations * in the functions that use them, but bytewise shifts and masks are * especially fast on many machines, so working a byte at a time seems best. */static const uint8 rightmost_one_pos[256] = { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};static const uint8 number_of_ones[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};/* * bms_copy - make a palloc'd copy of a bitmapset */Bitmapset *bms_copy(const Bitmapset *a){ Bitmapset *result; size_t size; if (a == NULL) return NULL; size = BITMAPSET_SIZE(a->nwords); result = (Bitmapset *) palloc(size); memcpy(result, a, size); return result;}/* * bms_equal - are two bitmapsets equal? * * This is logical not physical equality; in particular, a NULL pointer will * be reported as equal to a palloc'd value containing no members. */boolbms_equal(const Bitmapset *a, const Bitmapset *b){ const Bitmapset *shorter; const Bitmapset *longer; int shortlen; int longlen; int i; /* Handle cases where either input is NULL */ if (a == NULL) { if (b == NULL) return true; return bms_is_empty(b); } else if (b == NULL) return bms_is_empty(a); /* Identify shorter and longer input */ if (a->nwords <= b->nwords) { shorter = a; longer = b; } else { shorter = b; longer = a; } /* And process */ shortlen = shorter->nwords; for (i = 0; i < shortlen; i++) { if (shorter->words[i] != longer->words[i]) return false; } longlen = longer->nwords; for (; i < longlen; i++) { if (longer->words[i] != 0) return false; } return true;}/* * bms_make_singleton - build a bitmapset containing a single member */Bitmapset *bms_make_singleton(int x){ Bitmapset *result; int wordnum, bitnum; if (x < 0) elog(ERROR, "negative bitmapset member not allowed"); wordnum = WORDNUM(x); bitnum = BITNUM(x); result = (Bitmapset *) palloc0(BITMAPSET_SIZE(wordnum + 1)); result->nwords = wordnum + 1; result->words[wordnum] = ((bitmapword) 1 << bitnum); return result;}/* * bms_free - free a bitmapset * * Same as pfree except for allowing NULL input */voidbms_free(Bitmapset *a){ if (a) pfree(a);}/* * These operations all make a freshly palloc'd result, * leaving their inputs untouched *//* * bms_union - set union */Bitmapset *bms_union(const 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) 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; for (i = 0; i < otherlen; i++) result->words[i] |= other->words[i]; return result;}/* * bms_intersect - set intersection */Bitmapset *bms_intersect(const Bitmapset *a, const Bitmapset *b){ Bitmapset *result; const Bitmapset *other; 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; for (i = 0; i < resultlen; i++) result->words[i] &= other->words[i]; return result;}/* * bms_difference - set difference (ie, A without members of B) */Bitmapset *bms_difference(const Bitmapset *a, const Bitmapset *b){ Bitmapset *result; int shortlen; int i; /* Handle cases where either input is NULL */ if (a == NULL) return NULL; if (b == NULL) return bms_copy(a); /* Copy the left input */ result = bms_copy(a); /* And remove b's bits from result */ shortlen = Min(a->nwords, b->nwords); for (i = 0; i < shortlen; i++) result->words[i] &= ~b->words[i]; return result;}/* * bms_is_subset - is A a subset of B? */boolbms_is_subset(const Bitmapset *a, const Bitmapset *b){ int shortlen; int longlen; int i; /* Handle cases where either input is NULL */ if (a == NULL) return true; /* empty set is a subset of anything */ if (b == NULL) return bms_is_empty(a); /* Check common words */ shortlen = Min(a->nwords, b->nwords); for (i = 0; i < shortlen; i++) { if ((a->words[i] & ~b->words[i]) != 0) return false; } /* Check extra words */ if (a->nwords > b->nwords) { longlen = a->nwords; for (; i < longlen; i++) { if (a->words[i] != 0) return false; } } return true;}/* * bms_is_member - is X a member of A? */boolbms_is_member(int x, const Bitmapset *a){ int wordnum, bitnum; /* XXX better to just return false for x<0 ? */ if (x < 0) elog(ERROR, "negative bitmapset member not allowed"); if (a == NULL) return false; wordnum = WORDNUM(x); bitnum = BITNUM(x); if (wordnum >= a->nwords) return false; if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0) return true; return false;}/* * bms_overlap - do sets overlap (ie, have a nonempty intersection)? */boolbms_overlap(const Bitmapset *a, const Bitmapset *b){ int shortlen; int i; /* Handle cases where either input is NULL */ if (a == NULL || b == NULL) return false; /* Check words in common */ shortlen = Min(a->nwords, b->nwords); for (i = 0; i < shortlen; i++) { if ((a->words[i] & b->words[i]) != 0) return true; } return false;}/* * bms_nonempty_difference - do sets have a nonempty difference? */boolbms_nonempty_difference(const Bitmapset *a, const Bitmapset *b){ int shortlen; int i; /* Handle cases where either input is NULL */ if (a == NULL) return false; if (b == NULL) return !bms_is_empty(a); /* Check words in common */ shortlen = Min(a->nwords, b->nwords); for (i = 0; i < shortlen; i++) { if ((a->words[i] & ~b->words[i]) != 0) return true; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -