diff options
Diffstat (limited to 'mysys/my_bitmap.c')
-rw-r--r-- | mysys/my_bitmap.c | 189 |
1 files changed, 112 insertions, 77 deletions
diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index 3401c7301e9..22199758112 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -40,16 +40,31 @@ #include <m_string.h> #include <my_bit.h> -void create_last_word_mask(MY_BITMAP *map) + +/* Create a mask of the significant bits for the last byte (1,3,7,..255) */ + +static inline uchar last_byte_mask(uint bits) { - /* Get the number of used bits (1..8) in the last byte */ - unsigned int const used= 1U + ((map->n_bits-1U) & 0x7U); + /* Get the number of used bits-1 (0..7) in the last byte */ + unsigned int const used= (bits - 1U) & 7U; + /* Return bitmask for the significant bits */ + return ((2U << used) - 1); +} + +/* + Create a mask with the upper 'unused' bits set and the lower 'used' + bits clear. The bits within each byte is stored in big-endian order. +*/ + +static inline uchar invers_last_byte_mask(uint bits) +{ + return last_byte_mask(bits) ^ 255; +} - /* - Create a mask with the upper 'unused' bits set and the lower 'used' - bits clear. The bits within each byte is stored in big-endian order. - */ - unsigned char const mask= (~((1 << used) - 1)) & 255; + +void create_last_word_mask(MY_BITMAP *map) +{ + unsigned char const mask= invers_last_byte_mask(map->n_bits); /* The first bytes are to be set to zero since they represent real bits @@ -267,40 +282,41 @@ void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) { - uint prefix_bits= prefix_size & 0x7, res; - uchar *m= (uchar*)map->bitmap; - uchar *end_prefix= m+prefix_size/8; + uint prefix_mask= last_byte_mask(prefix_size); + uchar *m= (uchar*) map->bitmap; + uchar *end_prefix= m+(prefix_size-1)/8; uchar *end; DBUG_ASSERT(m && prefix_size <= map->n_bits); - end= m+no_bytes_in_map(map); + + /* Empty prefix is always true */ + if (!prefix_size) + return 1; while (m < end_prefix) if (*m++ != 0xff) return 0; - *map->last_word_ptr&= ~map->last_word_mask; /*Clear bits*/ - res= 0; - if (prefix_bits && *m++ != (1 << prefix_bits)-1) - goto ret; + end= ((uchar*) map->bitmap) + no_bytes_in_map(map) - 1; + if (m == end) + return ((*m & last_byte_mask(map->n_bits)) == prefix_mask); - while (m < end) - if (*m++ != 0) - goto ret; - res= 1; -ret: - return res; -} + if (*m != prefix_mask) + return 0; + while (++m < end) + if (*m != 0) + return 0; + return ((*m & last_byte_mask(map->n_bits)) == 0); +} my_bool bitmap_is_set_all(const MY_BITMAP *map) { my_bitmap_map *data_ptr= map->bitmap; my_bitmap_map *end= map->last_word_ptr; - *map->last_word_ptr |= map->last_word_mask; - for (; data_ptr <= end; data_ptr++) + for (; data_ptr < end; data_ptr++) if (*data_ptr != 0xFFFFFFFF) return FALSE; - return TRUE; + return (*data_ptr | map->last_word_mask) == 0xFFFFFFFF; } @@ -308,13 +324,11 @@ my_bool bitmap_is_clear_all(const MY_BITMAP *map) { my_bitmap_map *data_ptr= map->bitmap; my_bitmap_map *end; - if (*map->last_word_ptr & ~map->last_word_mask) - return FALSE; end= map->last_word_ptr; for (; data_ptr < end; data_ptr++) if (*data_ptr) return FALSE; - return TRUE; + return (*data_ptr & ~map->last_word_mask) == 0; } /* Return TRUE if map1 is a subset of map2 */ @@ -327,14 +341,13 @@ my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) map1->n_bits==map2->n_bits); end= map1->last_word_ptr; - *map1->last_word_ptr &= ~map1->last_word_mask; - *map2->last_word_ptr &= ~map2->last_word_mask; - while (m1 <= end) + while (m1 < end) { if ((*m1++) & ~(*m2++)) return 0; } - return 1; + /* here both maps have the same number of bits - see assert above */ + return ((*m1 & ~*m2 & ~map1->last_word_mask) ? 0 : 1); } /* True if bitmaps has any common bits */ @@ -347,14 +360,13 @@ my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2) map1->n_bits==map2->n_bits); end= map1->last_word_ptr; - *map1->last_word_ptr &= ~map1->last_word_mask; - *map2->last_word_ptr &= ~map2->last_word_mask; - while (m1 <= end) + while (m1 < end) { if ((*m1++) & (*m2++)) return 1; } - return 0; + /* here both maps have the same number of bits - see assert above */ + return ((*m1 & *m2 & ~map1->last_word_mask) ? 1 : 0); } @@ -366,18 +378,35 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) DBUG_ASSERT(map->bitmap && map2->bitmap); end= to+min(len,len2); - *map2->last_word_ptr&= ~map2->last_word_mask; /*Clear last bits in map2*/ while (to < end) *to++ &= *from++; - if (len2 < len) + if (len2 <= len) { - end+=len-len2; + to[-1]&= ~map2->last_word_mask; /* Clear last not relevant bits */ + end+= len-len2; while (to < end) - *to++=0; + *to++= 0; } } +/* True if union of bitmaps have all bits set */ + +my_bool bitmap_union_is_set_all(const MY_BITMAP *map1, const MY_BITMAP *map2) +{ + my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; + + DBUG_ASSERT(map1->bitmap && map2->bitmap && + map1->n_bits==map2->n_bits); + end= map1->last_word_ptr; + while ( m1 < end) + if ((*m1++ | *m2++) != 0xFFFFFFFF) + return FALSE; + /* here both maps have the same number of bits - see assert above */ + return ((*m1 | *m2 | map1->last_word_mask) != 0xFFFFFFFF); +} + + /* Set/clear all bits above a bit. @@ -461,14 +490,13 @@ void bitmap_invert(MY_BITMAP *map) uint bitmap_bits_set(const MY_BITMAP *map) { uchar *m= (uchar*)map->bitmap; - uchar *end= m + no_bytes_in_map(map); + uchar *end= m + no_bytes_in_map(map) - 1; uint res= 0; DBUG_ASSERT(map->bitmap); - *map->last_word_ptr&= ~map->last_word_mask; /*Reset last bits to zero*/ while (m < end) res+= my_count_bits_ushort(*m++); - return res; + return res + my_count_bits_ushort(*m & last_byte_mask(map->n_bits)); } @@ -492,27 +520,30 @@ uint bitmap_get_first_set(const MY_BITMAP *map) DBUG_ASSERT(map->bitmap); data_ptr= map->bitmap; - *map->last_word_ptr &= ~map->last_word_mask; - for (i=0; data_ptr <= end; data_ptr++, i++) - { + for (i=0; data_ptr < end; data_ptr++, i++) if (*data_ptr) + goto found; + if (!(*data_ptr & ~map->last_word_mask)) + return MY_BIT_NONE; + +found: + { + byte_ptr= (uchar*)data_ptr; + for (j=0; ; j++, byte_ptr++) { - byte_ptr= (uchar*)data_ptr; - for (j=0; ; j++, byte_ptr++) + if (*byte_ptr) { - if (*byte_ptr) + for (k=0; ; k++) { - for (k=0; ; k++) - { - if (*byte_ptr & (1 << k)) - return (i*32) + (j*8) + k; - } + if (*byte_ptr & (1 << k)) + return (i*32) + (j*8) + k; } } } } - return MY_BIT_NONE; + DBUG_ASSERT(0); + return MY_BIT_NONE; /* Impossible */ } @@ -526,25 +557,29 @@ uint bitmap_get_first(const MY_BITMAP *map) data_ptr= map->bitmap; *map->last_word_ptr|= map->last_word_mask; - for (i=0; data_ptr <= end; data_ptr++, i++) - { + for (i=0; data_ptr < end; data_ptr++, i++) if (*data_ptr != 0xFFFFFFFF) + goto found; + if ((*data_ptr | map->last_word_mask) == 0xFFFFFFFF) + return MY_BIT_NONE; + +found: + { + byte_ptr= (uchar*)data_ptr; + for (j=0; ; j++, byte_ptr++) { - byte_ptr= (uchar*)data_ptr; - for (j=0; ; j++, byte_ptr++) + if (*byte_ptr != 0xFF) { - if (*byte_ptr != 0xFF) + for (k=0; ; k++) { - for (k=0; ; k++) - { - if (!(*byte_ptr & (1 << k))) - return (i*32) + (j*8) + k; - } + if (!(*byte_ptr & (1 << k))) + return (i*32) + (j*8) + k; } } } } - return MY_BIT_NONE; + DBUG_ASSERT(0); + return MY_BIT_NONE; /* Impossible */ } @@ -573,7 +608,7 @@ uint get_rand_bit(uint bitsize) return (rand() % bitsize); } -bool test_set_get_clear_bit(MY_BITMAP *map, uint bitsize) +my_bool test_set_get_clear_bit(MY_BITMAP *map, uint bitsize) { uint i, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -596,7 +631,7 @@ error2: return TRUE; } -bool test_flip_bit(MY_BITMAP *map, uint bitsize) +my_bool test_flip_bit(MY_BITMAP *map, uint bitsize) { uint i, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -619,13 +654,13 @@ error2: return TRUE; } -bool test_operators(MY_BITMAP *map __attribute__((unused)), +my_bool test_operators(MY_BITMAP *map __attribute__((unused)), uint bitsize __attribute__((unused))) { return FALSE; } -bool test_get_all_bits(MY_BITMAP *map, uint bitsize) +my_bool test_get_all_bits(MY_BITMAP *map, uint bitsize) { uint i; bitmap_set_all(map); @@ -667,7 +702,7 @@ error6: return TRUE; } -bool test_compare_operators(MY_BITMAP *map, uint bitsize) +my_bool test_compare_operators(MY_BITMAP *map, uint bitsize) { uint i, j, test_bit1, test_bit2, test_bit3,test_bit4; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -773,7 +808,7 @@ error5: return TRUE; } -bool test_count_bits_set(MY_BITMAP *map, uint bitsize) +my_bool test_count_bits_set(MY_BITMAP *map, uint bitsize) { uint i, bit_count=0, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -799,7 +834,7 @@ error2: return TRUE; } -bool test_get_first_bit(MY_BITMAP *map, uint bitsize) +my_bool test_get_first_bit(MY_BITMAP *map, uint bitsize) { uint i, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -824,7 +859,7 @@ error2: return TRUE; } -bool test_get_next_bit(MY_BITMAP *map, uint bitsize) +my_bool test_get_next_bit(MY_BITMAP *map, uint bitsize) { uint i, j, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -843,7 +878,7 @@ error1: return TRUE; } -bool test_prefix(MY_BITMAP *map, uint bitsize) +my_bool test_prefix(MY_BITMAP *map, uint bitsize) { uint i, j, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; @@ -878,7 +913,7 @@ error3: } -bool do_test(uint bitsize) +my_bool do_test(uint bitsize) { MY_BITMAP map; my_bitmap_map buf[1024]; |