mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-04 00:02:52 -05:00 
			
		
		
		
	Add bms_prev_member function
This works very much like the existing bms_last_member function, only it traverses through the Bitmapset in the opposite direction from the most significant bit down to the least significant bit. A special prevbit value of -1 may be used to have the function determine the most significant bit. This is useful for starting a loop. When there are no members less than prevbit, the function returns -2 to indicate there are no more members. Author: David Rowley Discussion: https://postgr.es/m/CAKJS1f-K=3d5MDASNYFJpUpc20xcBnAwNC1-AOeunhn0OtkWbQ@mail.gmail.com
This commit is contained in:
		
							parent
							
								
									f16241bef7
								
							
						
					
					
						commit
						5c0675215e
					
				@ -58,6 +58,9 @@
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 * leftmost_one_pos[x] gives the bit number (0-7) of the leftmost 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
 | 
			
		||||
@ -84,6 +87,25 @@ static const uint8 rightmost_one_pos[256] = {
 | 
			
		||||
	4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const uint8 leftmost_one_pos[256] = {
 | 
			
		||||
	0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
 | 
			
		||||
	4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 | 
			
		||||
	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 | 
			
		||||
	5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
 | 
			
		||||
	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
 | 
			
		||||
	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
 | 
			
		||||
	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
 | 
			
		||||
	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
 | 
			
		||||
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 | 
			
		||||
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 | 
			
		||||
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 | 
			
		||||
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 | 
			
		||||
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 | 
			
		||||
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 | 
			
		||||
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
 | 
			
		||||
	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
@ -1088,6 +1110,79 @@ bms_next_member(const Bitmapset *a, int prevbit)
 | 
			
		||||
	return -2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * bms_prev_member - find prev member of a set
 | 
			
		||||
 *
 | 
			
		||||
 * Returns largest member less than "prevbit", or -2 if there is none.
 | 
			
		||||
 * "prevbit" must NOT be more than one above the highest possible bit that can
 | 
			
		||||
 * be set at the Bitmapset at its current size.
 | 
			
		||||
 *
 | 
			
		||||
 * To ease finding the highest set bit for the initial loop, the special
 | 
			
		||||
 * prevbit value of -1 can be passed to have the function find the highest
 | 
			
		||||
 * valued member in the set.
 | 
			
		||||
 *
 | 
			
		||||
 * This is intended as support for iterating through the members of a set in
 | 
			
		||||
 * reverse.  The typical pattern is
 | 
			
		||||
 *
 | 
			
		||||
 *			x = -1;
 | 
			
		||||
 *			while ((x = bms_prev_member(inputset, x)) >= 0)
 | 
			
		||||
 *				process member x;
 | 
			
		||||
 *
 | 
			
		||||
 * Notice that when there are no more members, we return -2, not -1 as you
 | 
			
		||||
 * might expect.  The rationale for that is to allow distinguishing the
 | 
			
		||||
 * loop-not-started state (x == -1) from the loop-completed state (x == -2).
 | 
			
		||||
 * It makes no difference in simple loop usage, but complex iteration logic
 | 
			
		||||
 * might need such an ability.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
bms_prev_member(const Bitmapset *a, int prevbit)
 | 
			
		||||
{
 | 
			
		||||
	int			wordnum;
 | 
			
		||||
	int			ushiftbits;
 | 
			
		||||
	bitmapword	mask;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If set is NULL or if there are no more bits to the right then we've
 | 
			
		||||
	 * nothing to do.
 | 
			
		||||
	 */
 | 
			
		||||
	if (a == NULL || prevbit == 0)
 | 
			
		||||
		return -2;
 | 
			
		||||
 | 
			
		||||
	/* transform -1 to the highest possible bit we could have set */
 | 
			
		||||
	if (prevbit == -1)
 | 
			
		||||
		prevbit = a->nwords * BITS_PER_BITMAPWORD - 1;
 | 
			
		||||
	else
 | 
			
		||||
		prevbit--;
 | 
			
		||||
 | 
			
		||||
	ushiftbits = BITS_PER_BITMAPWORD - (BITNUM(prevbit) + 1);
 | 
			
		||||
	mask = (~(bitmapword) 0) >> ushiftbits;
 | 
			
		||||
	for (wordnum = WORDNUM(prevbit); wordnum >= 0; wordnum--)
 | 
			
		||||
	{
 | 
			
		||||
		bitmapword	w = a->words[wordnum];
 | 
			
		||||
 | 
			
		||||
		/* mask out bits left of prevbit */
 | 
			
		||||
		w &= mask;
 | 
			
		||||
 | 
			
		||||
		if (w != 0)
 | 
			
		||||
		{
 | 
			
		||||
			int			result;
 | 
			
		||||
			int			shift = 24;
 | 
			
		||||
			result = wordnum * BITS_PER_BITMAPWORD;
 | 
			
		||||
 | 
			
		||||
			while ((w >> shift) == 0)
 | 
			
		||||
				shift -= 8;
 | 
			
		||||
 | 
			
		||||
			result += shift + leftmost_one_pos[(w >> shift) & 255];
 | 
			
		||||
			return result;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* in subsequent words, consider all bits */
 | 
			
		||||
		mask = (~(bitmapword) 0);
 | 
			
		||||
	}
 | 
			
		||||
	return -2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * bms_hash_value - compute a hash key for a Bitmapset
 | 
			
		||||
 *
 | 
			
		||||
 | 
			
		||||
@ -99,6 +99,7 @@ extern Bitmapset *bms_join(Bitmapset *a, Bitmapset *b);
 | 
			
		||||
/* support for iterating through the integer elements of a set: */
 | 
			
		||||
extern int	bms_first_member(Bitmapset *a);
 | 
			
		||||
extern int	bms_next_member(const Bitmapset *a, int prevbit);
 | 
			
		||||
extern int	bms_prev_member(const Bitmapset *a, int prevbit);
 | 
			
		||||
 | 
			
		||||
/* support for hashtables using Bitmapsets as keys: */
 | 
			
		||||
extern uint32 bms_hash_value(const Bitmapset *a);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user