Added bitmap_get_last_set functions.

This can be used by replication to optimize unpack_row and other things
This commit is contained in:
Monty 2025-09-30 16:49:20 +03:00
parent 04aaff9c0c
commit a32d5c340f
3 changed files with 74 additions and 2 deletions

View File

@ -61,6 +61,7 @@ extern my_bool bitmap_exists_intersection(MY_BITMAP **bitmap_array,
extern uint bitmap_set_next(MY_BITMAP *map);
extern uint bitmap_get_first_clear(const MY_BITMAP *map);
extern uint bitmap_get_first_set(const MY_BITMAP *map);
extern uint bitmap_get_last_set(const MY_BITMAP *map);
extern uint bitmap_bits_set(const MY_BITMAP *map);
extern uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit);
extern void my_bitmap_free(MY_BITMAP *map);

View File

@ -579,13 +579,44 @@ uint bitmap_get_first_set(const MY_BITMAP *map)
my_bitmap_map *data_ptr= map->bitmap, *end= map->last_word_ptr;
DBUG_ASSERT_BITMAP(map);
for (uint i=0; data_ptr <= end; data_ptr++, i++)
for (uint i= 0; data_ptr <= end; data_ptr++, i++)
if (*data_ptr)
return my_find_first_bit(*data_ptr) + i * sizeof(my_bitmap_map)*8;
return MY_BIT_NONE;
}
/*
Find last set bit in a bitmap (0 - (bit_map_size -1))
Returns MY_BIT_NONE if no bits.
*/
#define step(x) if (n >= (1ULL) << x) { bit+= x; n >>= x; }
uint get_last_bit(ulonglong n)
{
int bit= 0;
DBUG_ASSERT(n > 0);
step(32) ; step(16); step(8); step(4); step(2); step(1);
return bit;
}
#undef step
uint bitmap_get_last_set(const MY_BITMAP *map)
{
my_bitmap_map *data_ptr= map->bitmap, *end= map->last_word_ptr;
DBUG_ASSERT_BITMAP(map);
do
{
if (*end)
return (uint) ((end-data_ptr)*sizeof(my_bitmap_map))*8 + get_last_bit(*end);
} while (end-- > data_ptr);
return MY_BIT_NONE;
}
/**
Get the next set bit.

View File

@ -297,6 +297,44 @@ error2:
return TRUE;
}
my_bool test_get_last_bit(MY_BITMAP *map, uint bitsize)
{
uint i, test_bit= 0;
uint no_loops= bitsize > 128 ? 128 : bitsize;
bitmap_set_all(map);
test_bit= bitsize;
if (bitmap_get_last_set(map) != bitsize-1)
goto error1;
bitmap_clear_all(map);
test_bit= 0;
if (bitmap_get_last_set(map) != MY_BIT_NONE)
goto error1;
for (i=0; i < no_loops; i++)
{
uint test_bit1, test_bit2;
bitmap_clear_all(map);
test_bit1= get_rand_bit(bitsize);
bitmap_set_bit(map, test_bit1);
test_bit2= get_rand_bit(bitsize);
bitmap_set_bit(map, test_bit2);
test_bit= MY_MAX(test_bit1, test_bit2);
if (bitmap_get_last_set(map) != test_bit)
goto error1;
}
return FALSE;
error1:
diag("get_last_set error bitsize=%u, test_bit=%u, res: %u",
bitsize, test_bit, bitmap_get_last_set(map));
return TRUE;
}
my_bool test_get_next_bit(MY_BITMAP *map, uint bitsize)
{
uint i, j, test_bit;
@ -641,6 +679,8 @@ my_bool do_test(uint bitsize)
bitmap_clear_all(&map);
if (test_get_first_bit(&map,bitsize))
goto error;
if (test_get_last_bit(&map,bitsize))
goto error;
bitmap_clear_all(&map);
if (test_get_next_bit(&map,bitsize))
goto error;
@ -674,7 +714,7 @@ int main(int argc __attribute__((unused)),char *argv[])
plan((max_size - min_size)/7+1);
/*
It's ok to do steps in 7, as i module 64 will go trough all values 1..63.
It's ok to do steps in 7, as i module 64 will go through all values 1..63.
Any errors in the code should manifest as we are working with integers
of size 16, 32, or 64 bits...
*/