1
/* Copyright (C) 2000 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
Handling of unsigned char arrays as large bitmaps.
19
API limitations (or, rather asserted safety assumptions,
20
to encourage correct programming)
22
* the internal size is a set of 32 bit words
23
* the number of bits specified in creation can be any number > 0
26
Original version created by Sergei Golubchik 2001 - 2004.
27
New version written and test program added and some changes to the interface
28
was made by Mikael Ronström 2005, with assistance of Tomas Ulin and Mats
32
#include "mysys_priv.h"
33
#include <mysys/my_bitmap.h>
34
#include <mystrings/m_string.h>
35
#include <mysys/my_bit.h>
41
void create_last_word_mask(MY_BITMAP *map)
43
/* Get the number of used bits (1..8) in the last byte */
44
unsigned int const used= 1U + ((map->n_bits-1U) & 0x7U);
47
Create a mask with the upper 'unused' bits set and the lower 'used'
48
bits clear. The bits within each byte is stored in big-endian order.
50
unsigned char const mask= (~((1 << used) - 1)) & 255;
53
The first bytes are to be set to zero since they represent real bits
54
in the bitvector. The last bytes are set to 0xFF since they represent
55
bytes not used by the bitvector. Finally the last byte contains bits
56
as set by the mask above.
58
unsigned char *ptr= (unsigned char*)&map->last_word_mask;
60
map->last_word_ptr= map->bitmap + no_words_in_map(map)-1;
61
switch (no_bytes_in_map(map) & 3) {
63
map->last_word_mask= UINT32_MAX;
67
map->last_word_mask= UINT32_MAX;
72
map->last_word_mask= 0;
77
map->last_word_mask= 0U;
84
bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint32_t n_bits)
88
uint32_t size_in_bytes= bitmap_buffer_size(n_bits);
89
size_in_bytes= ALIGN_SIZE(size_in_bytes);
90
if (!(buf= (my_bitmap_map*) malloc(size_in_bytes)))
96
create_last_word_mask(map);
97
bitmap_clear_all(map);
102
void bitmap_free(MY_BITMAP *map)
106
free((char*) map->bitmap);
114
test if bit already set and set it if it was not
117
bitmap_test_and_set()
126
bool bitmap_test_and_set(MY_BITMAP *map, uint32_t bitmap_bit)
128
unsigned char *value= ((unsigned char*) map->bitmap) + (bitmap_bit / 8);
129
unsigned char bit= 1 << ((bitmap_bit) & 7);
130
unsigned char res= (*value) & bit;
138
test if bit already set and clear it if it was set
141
bitmap_test_and_set()
150
bool bitmap_test_and_clear(MY_BITMAP *map, uint32_t bitmap_bit)
152
unsigned char *byte= (unsigned char*) map->bitmap + (bitmap_bit / 8);
153
unsigned char bit= 1 << ((bitmap_bit) & 7);
154
unsigned char res= (*byte) & bit;
161
uint32_t bitmap_set_next(MY_BITMAP *map)
165
if ((bit_found= bitmap_get_first(map)) != MY_BIT_NONE)
166
bitmap_set_bit(map, bit_found);
171
void bitmap_set_prefix(MY_BITMAP *map, uint32_t prefix_size)
173
uint32_t prefix_bytes, prefix_bits, d;
174
unsigned char *m= (unsigned char *)map->bitmap;
176
assert(map->bitmap &&
177
(prefix_size <= map->n_bits || prefix_size == UINT32_MAX));
178
set_if_smaller(prefix_size, map->n_bits);
179
if ((prefix_bytes= prefix_size / 8))
180
memset(m, 0xff, prefix_bytes);
182
if ((prefix_bits= prefix_size & 7))
183
*m++= (1 << prefix_bits)-1;
184
if ((d= no_bytes_in_map(map)-prefix_bytes))
189
bool bitmap_is_prefix(const MY_BITMAP *map, uint32_t prefix_size)
191
uint32_t prefix_bits= prefix_size & 0x7, res;
192
unsigned char *m= (unsigned char*)map->bitmap;
193
unsigned char *end_prefix= m+prefix_size/8;
195
assert(m && prefix_size <= map->n_bits);
196
end= m+no_bytes_in_map(map);
198
while (m < end_prefix)
202
*map->last_word_ptr&= ~map->last_word_mask; /*Clear bits*/
204
if (prefix_bits && *m++ != (1 << prefix_bits)-1)
216
bool bitmap_is_set_all(const MY_BITMAP *map)
218
my_bitmap_map *data_ptr= map->bitmap;
219
my_bitmap_map *end= map->last_word_ptr;
220
*map->last_word_ptr |= map->last_word_mask;
221
for (; data_ptr <= end; data_ptr++)
222
if (*data_ptr != 0xFFFFFFFF)
228
bool bitmap_is_clear_all(const MY_BITMAP *map)
230
my_bitmap_map *data_ptr= map->bitmap;
232
if (*map->last_word_ptr & ~map->last_word_mask)
234
end= map->last_word_ptr;
235
for (; data_ptr < end; data_ptr++)
241
/* Return true if map1 is a subset of map2 */
243
bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2)
245
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
247
assert(map1->bitmap && map2->bitmap &&
248
map1->n_bits==map2->n_bits);
250
end= map1->last_word_ptr;
251
*map1->last_word_ptr &= ~map1->last_word_mask;
252
*map2->last_word_ptr &= ~map2->last_word_mask;
255
if ((*m1++) & ~(*m2++))
261
/* True if bitmaps has any common bits */
263
bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2)
265
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
267
assert(map1->bitmap && map2->bitmap &&
268
map1->n_bits==map2->n_bits);
270
end= map1->last_word_ptr;
271
*map1->last_word_ptr &= ~map1->last_word_mask;
272
*map2->last_word_ptr &= ~map2->last_word_mask;
275
if ((*m1++) & (*m2++))
282
void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
284
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
285
uint32_t len= no_words_in_map(map), len2 = no_words_in_map(map2);
287
assert(map->bitmap && map2->bitmap);
289
end= to+min(len,len2);
290
*map2->last_word_ptr&= ~map2->last_word_mask; /*Clear last bits in map2*/
304
Set/clear all bits above a bit.
308
map RETURN The bitmap to change.
309
from_byte The bitmap buffer byte offset to start with.
310
use_bit The bit value (1/0) to use for all upper bits.
313
You can only set/clear full bytes.
314
The function is meant for the situation that you copy a smaller bitmap
315
to a bigger bitmap. Bitmap lengths are always multiple of eigth (the
316
size of a byte). Using 'from_byte' saves multiplication and division
317
by eight during parameter passing.
323
void bitmap_set_above(MY_BITMAP *map, uint32_t from_byte, uint32_t use_bit)
325
unsigned char use_byte= use_bit ? 0xff : 0;
326
unsigned char *to= (unsigned char *)map->bitmap + from_byte;
327
unsigned char *end= (unsigned char *)map->bitmap + (map->n_bits+7)/8;
334
void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
336
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
337
assert(map->bitmap && map2->bitmap &&
338
map->n_bits==map2->n_bits);
340
end= map->last_word_ptr;
347
void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
349
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
351
assert(map->bitmap && map2->bitmap &&
352
map->n_bits==map2->n_bits);
353
end= map->last_word_ptr;
360
void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2)
362
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr;
363
assert(map->bitmap && map2->bitmap &&
364
map->n_bits==map2->n_bits);
370
void bitmap_invert(MY_BITMAP *map)
372
my_bitmap_map *to= map->bitmap, *end;
375
end= map->last_word_ptr;
382
uint32_t bitmap_bits_set(const MY_BITMAP *map)
384
unsigned char *m= (unsigned char*)map->bitmap;
385
unsigned char *end= m + no_bytes_in_map(map);
389
*map->last_word_ptr&= ~map->last_word_mask; /*Reset last bits to zero*/
391
res+= my_count_bits_uint16(*m++);
396
void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2)
398
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
400
assert(map->bitmap && map2->bitmap &&
401
map->n_bits==map2->n_bits);
402
end= map->last_word_ptr;
408
uint32_t bitmap_get_first_set(const MY_BITMAP *map)
410
unsigned char *byte_ptr;
412
my_bitmap_map *data_ptr, *end= map->last_word_ptr;
415
data_ptr= map->bitmap;
416
*map->last_word_ptr &= ~map->last_word_mask;
418
for (i=0; data_ptr <= end; data_ptr++, i++)
422
byte_ptr= (unsigned char*)data_ptr;
423
for (j=0; ; j++, byte_ptr++)
429
if (*byte_ptr & (1 << k))
430
return (i*32) + (j*8) + k;
440
uint32_t bitmap_get_first(const MY_BITMAP *map)
442
unsigned char *byte_ptr;
444
my_bitmap_map *data_ptr, *end= map->last_word_ptr;
447
data_ptr= map->bitmap;
448
*map->last_word_ptr|= map->last_word_mask;
450
for (i=0; data_ptr <= end; data_ptr++, i++)
452
if (*data_ptr != 0xFFFFFFFF)
454
byte_ptr= (unsigned char*)data_ptr;
455
for (j=0; ; j++, byte_ptr++)
457
if (*byte_ptr != 0xFF)
461
if (!(*byte_ptr & (1 << k)))
462
return (i*32) + (j*8) + k;
474
uint32_t get_rand_bit(uint32_t bitsize)
476
return (rand() % bitsize);
479
bool test_set_get_clear_bit(MY_BITMAP *map, uint32_t bitsize)
481
uint32_t i, test_bit;
482
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
483
for (i=0; i < no_loops; i++)
485
test_bit= get_rand_bit(bitsize);
486
bitmap_set_bit(map, test_bit);
487
if (!bitmap_is_set(map, test_bit))
489
bitmap_clear_bit(map, test_bit);
490
if (bitmap_is_set(map, test_bit))
495
printf("Error in set bit, bit %u, bitsize = %u", test_bit, bitsize);
498
printf("Error in clear bit, bit %u, bitsize = %u", test_bit, bitsize);
502
bool test_flip_bit(MY_BITMAP *map, uint32_t bitsize)
504
uint32_t i, test_bit;
505
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
506
for (i=0; i < no_loops; i++)
508
test_bit= get_rand_bit(bitsize);
509
bitmap_flip_bit(map, test_bit);
510
if (!bitmap_is_set(map, test_bit))
512
bitmap_flip_bit(map, test_bit);
513
if (bitmap_is_set(map, test_bit))
518
printf("Error in flip bit 1, bit %u, bitsize = %u", test_bit, bitsize);
521
printf("Error in flip bit 2, bit %u, bitsize = %u", test_bit, bitsize);
525
bool test_operators(MY_BITMAP *, uint32_t)
530
bool test_get_all_bits(MY_BITMAP *map, uint32_t bitsize)
534
if (!bitmap_is_set_all(map))
536
if (!bitmap_is_prefix(map, bitsize))
538
bitmap_clear_all(map);
539
if (!bitmap_is_clear_all(map))
541
if (!bitmap_is_prefix(map, 0))
543
for (i=0; i<bitsize;i++)
544
bitmap_set_bit(map, i);
545
if (!bitmap_is_set_all(map))
547
for (i=0; i<bitsize;i++)
548
bitmap_clear_bit(map, i);
549
if (!bitmap_is_clear_all(map))
553
printf("Error in set_all, bitsize = %u", bitsize);
556
printf("Error in clear_all, bitsize = %u", bitsize);
559
printf("Error in bitmap_is_set_all, bitsize = %u", bitsize);
562
printf("Error in bitmap_is_clear_all, bitsize = %u", bitsize);
565
printf("Error in set_all through set_prefix, bitsize = %u", bitsize);
568
printf("Error in clear_all through set_prefix, bitsize = %u", bitsize);
572
bool test_compare_operators(MY_BITMAP *map, uint32_t bitsize)
574
uint32_t i, j, test_bit1, test_bit2, test_bit3,test_bit4;
575
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
576
MY_BITMAP map2_obj, map3_obj;
577
MY_BITMAP *map2= &map2_obj, *map3= &map3_obj;
578
my_bitmap_map map2buf[1024];
579
my_bitmap_map map3buf[1024];
580
bitmap_init(&map2_obj, map2buf, bitsize);
581
bitmap_init(&map3_obj, map3buf, bitsize);
582
bitmap_clear_all(map2);
583
bitmap_clear_all(map3);
584
for (i=0; i < no_loops; i++)
586
test_bit1=get_rand_bit(bitsize);
587
bitmap_set_prefix(map, test_bit1);
588
test_bit2=get_rand_bit(bitsize);
589
bitmap_set_prefix(map2, test_bit2);
590
bitmap_intersect(map, map2);
591
test_bit3= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
592
bitmap_set_prefix(map3, test_bit3);
593
if (!bitmap_cmp(map, map3))
595
bitmap_clear_all(map);
596
bitmap_clear_all(map2);
597
bitmap_clear_all(map3);
598
test_bit1=get_rand_bit(bitsize);
599
test_bit2=get_rand_bit(bitsize);
600
test_bit3=get_rand_bit(bitsize);
601
bitmap_set_prefix(map, test_bit1);
602
bitmap_set_prefix(map2, test_bit2);
603
test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
604
bitmap_set_prefix(map3, test_bit3);
605
bitmap_union(map, map2);
606
if (!bitmap_cmp(map, map3))
608
bitmap_clear_all(map);
609
bitmap_clear_all(map2);
610
bitmap_clear_all(map3);
611
test_bit1=get_rand_bit(bitsize);
612
test_bit2=get_rand_bit(bitsize);
613
test_bit3=get_rand_bit(bitsize);
614
bitmap_set_prefix(map, test_bit1);
615
bitmap_set_prefix(map2, test_bit2);
616
bitmap_xor(map, map2);
617
test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
618
test_bit4= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
619
bitmap_set_prefix(map3, test_bit3);
620
for (j=0; j < test_bit4; j++)
621
bitmap_clear_bit(map3, j);
622
if (!bitmap_cmp(map, map3))
624
bitmap_clear_all(map);
625
bitmap_clear_all(map2);
626
bitmap_clear_all(map3);
627
test_bit1=get_rand_bit(bitsize);
628
test_bit2=get_rand_bit(bitsize);
629
test_bit3=get_rand_bit(bitsize);
630
bitmap_set_prefix(map, test_bit1);
631
bitmap_set_prefix(map2, test_bit2);
632
bitmap_subtract(map, map2);
633
if (test_bit2 < test_bit1)
635
bitmap_set_prefix(map3, test_bit1);
636
for (j=0; j < test_bit2; j++)
637
bitmap_clear_bit(map3, j);
639
if (!bitmap_cmp(map, map3))
641
bitmap_clear_all(map);
642
bitmap_clear_all(map2);
643
bitmap_clear_all(map3);
644
test_bit1=get_rand_bit(bitsize);
645
bitmap_set_prefix(map, test_bit1);
647
bitmap_set_all(map3);
648
for (j=0; j < test_bit1; j++)
649
bitmap_clear_bit(map3, j);
650
if (!bitmap_cmp(map, map3))
652
bitmap_clear_all(map);
653
bitmap_clear_all(map3);
657
printf("intersect error bitsize=%u,size1=%u,size2=%u", bitsize,
658
test_bit1,test_bit2);
661
printf("union error bitsize=%u,size1=%u,size2=%u", bitsize,
662
test_bit1,test_bit2);
665
printf("xor error bitsize=%u,size1=%u,size2=%u", bitsize,
666
test_bit1,test_bit2);
669
printf("subtract error bitsize=%u,size1=%u,size2=%u", bitsize,
670
test_bit1,test_bit2);
673
printf("invert error bitsize=%u,size=%u", bitsize,
678
bool test_count_bits_set(MY_BITMAP *map, uint32_t bitsize)
680
uint32_t i, bit_count=0, test_bit;
681
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
682
for (i=0; i < no_loops; i++)
684
test_bit=get_rand_bit(bitsize);
685
if (!bitmap_is_set(map, test_bit))
687
bitmap_set_bit(map, test_bit);
691
if (bit_count==0 && bitsize > 0)
693
if (bitmap_bits_set(map) != bit_count)
697
printf("No bits set bitsize = %u", bitsize);
700
printf("Wrong count of bits set, bitsize = %u", bitsize);
704
bool test_get_first_bit(MY_BITMAP *map, uint32_t bitsize)
706
uint32_t i, test_bit;
707
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
708
for (i=0; i < no_loops; i++)
710
test_bit=get_rand_bit(bitsize);
711
bitmap_set_bit(map, test_bit);
712
if (bitmap_get_first_set(map) != test_bit)
715
bitmap_clear_bit(map, test_bit);
716
if (bitmap_get_first(map) != test_bit)
718
bitmap_clear_all(map);
722
printf("get_first_set error bitsize=%u,prefix_size=%u",bitsize,test_bit);
725
printf("get_first error bitsize= %u, prefix_size= %u",bitsize,test_bit);
729
bool test_get_next_bit(MY_BITMAP *map, uint32_t bitsize)
731
uint32_t i, j, test_bit;
732
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
733
for (i=0; i < no_loops; i++)
735
test_bit=get_rand_bit(bitsize);
736
for (j=0; j < test_bit; j++)
737
bitmap_set_next(map);
738
if (!bitmap_is_prefix(map, test_bit))
740
bitmap_clear_all(map);
744
printf("get_next error bitsize= %u, prefix_size= %u", bitsize,test_bit);
748
bool test_prefix(MY_BITMAP *map, uint32_t bitsize)
750
uint32_t i, j, test_bit;
751
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
752
for (i=0; i < no_loops; i++)
754
test_bit=get_rand_bit(bitsize);
755
bitmap_set_prefix(map, test_bit);
756
if (!bitmap_is_prefix(map, test_bit))
758
bitmap_clear_all(map);
759
for (j=0; j < test_bit; j++)
760
bitmap_set_bit(map, j);
761
if (!bitmap_is_prefix(map, test_bit))
764
for (j=bitsize - 1; ~(j-test_bit); j--)
765
bitmap_clear_bit(map, j);
766
if (!bitmap_is_prefix(map, test_bit))
768
bitmap_clear_all(map);
772
printf("prefix1 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
775
printf("prefix2 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
778
printf("prefix3 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
783
bool do_test(uint32_t bitsize)
786
my_bitmap_map buf[1024];
787
if (bitmap_init(&map, buf, bitsize))
789
printf("init error for bitsize %d", bitsize);
792
if (test_set_get_clear_bit(&map,bitsize))
794
bitmap_clear_all(&map);
795
if (test_flip_bit(&map,bitsize))
797
bitmap_clear_all(&map);
798
if (test_operators(&map,bitsize))
800
bitmap_clear_all(&map);
801
if (test_get_all_bits(&map, bitsize))
803
bitmap_clear_all(&map);
804
if (test_compare_operators(&map,bitsize))
806
bitmap_clear_all(&map);
807
if (test_count_bits_set(&map,bitsize))
809
bitmap_clear_all(&map);
810
if (test_get_first_bit(&map,bitsize))
812
bitmap_clear_all(&map);
813
if (test_get_next_bit(&map,bitsize))
815
if (test_prefix(&map,bitsize))
826
for (i= 1; i < 4096; i++)
828
printf("Start test for bitsize=%u\n",i);
839
will build the bitmap tests and ./test_bitmap will execute it