Skip to content

Commit a32d5c3

Browse files
committed
Added bitmap_get_last_set functions.
This can be used by replication to optimize unpack_row and other things
1 parent 04aaff9 commit a32d5c3

File tree

3 files changed

+74
-2
lines changed

3 files changed

+74
-2
lines changed

include/my_bitmap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ extern my_bool bitmap_exists_intersection(MY_BITMAP **bitmap_array,
6161
extern uint bitmap_set_next(MY_BITMAP *map);
6262
extern uint bitmap_get_first_clear(const MY_BITMAP *map);
6363
extern uint bitmap_get_first_set(const MY_BITMAP *map);
64+
extern uint bitmap_get_last_set(const MY_BITMAP *map);
6465
extern uint bitmap_bits_set(const MY_BITMAP *map);
6566
extern uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit);
6667
extern void my_bitmap_free(MY_BITMAP *map);

mysys/my_bitmap.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,13 +579,44 @@ uint bitmap_get_first_set(const MY_BITMAP *map)
579579
my_bitmap_map *data_ptr= map->bitmap, *end= map->last_word_ptr;
580580
DBUG_ASSERT_BITMAP(map);
581581

582-
for (uint i=0; data_ptr <= end; data_ptr++, i++)
582+
for (uint i= 0; data_ptr <= end; data_ptr++, i++)
583583
if (*data_ptr)
584584
return my_find_first_bit(*data_ptr) + i * sizeof(my_bitmap_map)*8;
585585
return MY_BIT_NONE;
586586
}
587587

588588

589+
/*
590+
Find last set bit in a bitmap (0 - (bit_map_size -1))
591+
Returns MY_BIT_NONE if no bits.
592+
*/
593+
594+
#define step(x) if (n >= (1ULL) << x) { bit+= x; n >>= x; }
595+
596+
uint get_last_bit(ulonglong n)
597+
{
598+
int bit= 0;
599+
DBUG_ASSERT(n > 0);
600+
601+
step(32) ; step(16); step(8); step(4); step(2); step(1);
602+
return bit;
603+
}
604+
#undef step
605+
606+
uint bitmap_get_last_set(const MY_BITMAP *map)
607+
{
608+
my_bitmap_map *data_ptr= map->bitmap, *end= map->last_word_ptr;
609+
DBUG_ASSERT_BITMAP(map);
610+
611+
do
612+
{
613+
if (*end)
614+
return (uint) ((end-data_ptr)*sizeof(my_bitmap_map))*8 + get_last_bit(*end);
615+
} while (end-- > data_ptr);
616+
return MY_BIT_NONE;
617+
}
618+
619+
589620
/**
590621
Get the next set bit.
591622

unittest/mysys/bitmap-t.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,44 @@ my_bool test_get_first_bit(MY_BITMAP *map, uint bitsize)
297297
return TRUE;
298298
}
299299

300+
301+
my_bool test_get_last_bit(MY_BITMAP *map, uint bitsize)
302+
{
303+
uint i, test_bit= 0;
304+
uint no_loops= bitsize > 128 ? 128 : bitsize;
305+
306+
bitmap_set_all(map);
307+
test_bit= bitsize;
308+
if (bitmap_get_last_set(map) != bitsize-1)
309+
goto error1;
310+
311+
bitmap_clear_all(map);
312+
test_bit= 0;
313+
if (bitmap_get_last_set(map) != MY_BIT_NONE)
314+
goto error1;
315+
316+
for (i=0; i < no_loops; i++)
317+
{
318+
uint test_bit1, test_bit2;
319+
bitmap_clear_all(map);
320+
test_bit1= get_rand_bit(bitsize);
321+
bitmap_set_bit(map, test_bit1);
322+
323+
test_bit2= get_rand_bit(bitsize);
324+
bitmap_set_bit(map, test_bit2);
325+
326+
test_bit= MY_MAX(test_bit1, test_bit2);
327+
if (bitmap_get_last_set(map) != test_bit)
328+
goto error1;
329+
}
330+
return FALSE;
331+
error1:
332+
diag("get_last_set error bitsize=%u, test_bit=%u, res: %u",
333+
bitsize, test_bit, bitmap_get_last_set(map));
334+
return TRUE;
335+
}
336+
337+
300338
my_bool test_get_next_bit(MY_BITMAP *map, uint bitsize)
301339
{
302340
uint i, j, test_bit;
@@ -641,6 +679,8 @@ my_bool do_test(uint bitsize)
641679
bitmap_clear_all(&map);
642680
if (test_get_first_bit(&map,bitsize))
643681
goto error;
682+
if (test_get_last_bit(&map,bitsize))
683+
goto error;
644684
bitmap_clear_all(&map);
645685
if (test_get_next_bit(&map,bitsize))
646686
goto error;
@@ -674,7 +714,7 @@ int main(int argc __attribute__((unused)),char *argv[])
674714
plan((max_size - min_size)/7+1);
675715

676716
/*
677-
It's ok to do steps in 7, as i module 64 will go trough all values 1..63.
717+
It's ok to do steps in 7, as i module 64 will go through all values 1..63.
678718
Any errors in the code should manifest as we are working with integers
679719
of size 16, 32, or 64 bits...
680720
*/

0 commit comments

Comments
 (0)