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>
37
void create_last_word_mask(MY_BITMAP *map)
39
/* Get the number of used bits (1..8) in the last byte */
40
unsigned int const used= 1U + ((map->n_bits-1U) & 0x7U);
43
Create a mask with the upper 'unused' bits set and the lower 'used'
44
bits clear. The bits within each byte is stored in big-endian order.
46
unsigned char const mask= (~((1 << used) - 1)) & 255;
49
The first bytes are to be set to zero since they represent real bits
50
in the bitvector. The last bytes are set to 0xFF since they represent
51
bytes not used by the bitvector. Finally the last byte contains bits
52
as set by the mask above.
54
unsigned char *ptr= (unsigned char*)&map->last_word_mask;
56
map->last_word_ptr= map->bitmap + no_words_in_map(map)-1;
57
switch (no_bytes_in_map(map) & 3) {
59
map->last_word_mask= UINT32_MAX;
63
map->last_word_mask= UINT32_MAX;
68
map->last_word_mask= 0;
73
map->last_word_mask= 0U;
80
bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint32_t n_bits)
84
uint32_t size_in_bytes= bitmap_buffer_size(n_bits);
85
size_in_bytes= ALIGN_SIZE(size_in_bytes);
86
if (!(buf= (my_bitmap_map*) malloc(size_in_bytes)))
92
create_last_word_mask(map);
93
bitmap_clear_all(map);
98
void bitmap_free(MY_BITMAP *map)
102
free((char*) map->bitmap);
110
test if bit already set and set it if it was not
113
bitmap_test_and_set()
122
bool bitmap_test_and_set(MY_BITMAP *map, uint32_t bitmap_bit)
124
unsigned char *value= ((unsigned char*) map->bitmap) + (bitmap_bit / 8);
125
unsigned char bit= 1 << ((bitmap_bit) & 7);
126
unsigned char res= (*value) & bit;
134
test if bit already set and clear it if it was set
137
bitmap_test_and_set()
146
bool bitmap_test_and_clear(MY_BITMAP *map, uint32_t bitmap_bit)
148
unsigned char *byte= (unsigned char*) map->bitmap + (bitmap_bit / 8);
149
unsigned char bit= 1 << ((bitmap_bit) & 7);
150
unsigned char res= (*byte) & bit;
157
uint32_t bitmap_set_next(MY_BITMAP *map)
161
if ((bit_found= bitmap_get_first(map)) != MY_BIT_NONE)
162
bitmap_set_bit(map, bit_found);
167
void bitmap_set_prefix(MY_BITMAP *map, uint32_t prefix_size)
169
uint32_t prefix_bytes, prefix_bits, d;
170
unsigned char *m= (unsigned char *)map->bitmap;
172
assert(map->bitmap &&
173
(prefix_size <= map->n_bits || prefix_size == UINT32_MAX));
174
set_if_smaller(prefix_size, map->n_bits);
175
if ((prefix_bytes= prefix_size / 8))
176
memset(m, 0xff, prefix_bytes);
178
if ((prefix_bits= prefix_size & 7))
179
*m++= (1 << prefix_bits)-1;
180
if ((d= no_bytes_in_map(map)-prefix_bytes))
185
bool bitmap_is_prefix(const MY_BITMAP *map, uint32_t prefix_size)
187
uint32_t prefix_bits= prefix_size & 0x7, res;
188
unsigned char *m= (unsigned char*)map->bitmap;
189
unsigned char *end_prefix= m+prefix_size/8;
191
assert(m && prefix_size <= map->n_bits);
192
end= m+no_bytes_in_map(map);
194
while (m < end_prefix)
198
*map->last_word_ptr&= ~map->last_word_mask; /*Clear bits*/
200
if (prefix_bits && *m++ != (1 << prefix_bits)-1)
212
bool bitmap_is_set_all(const MY_BITMAP *map)
214
my_bitmap_map *data_ptr= map->bitmap;
215
my_bitmap_map *end= map->last_word_ptr;
216
*map->last_word_ptr |= map->last_word_mask;
217
for (; data_ptr <= end; data_ptr++)
218
if (*data_ptr != 0xFFFFFFFF)
224
bool bitmap_is_clear_all(const MY_BITMAP *map)
226
my_bitmap_map *data_ptr= map->bitmap;
228
if (*map->last_word_ptr & ~map->last_word_mask)
230
end= map->last_word_ptr;
231
for (; data_ptr < end; data_ptr++)
237
/* Return true if map1 is a subset of map2 */
239
bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2)
241
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
243
assert(map1->bitmap && map2->bitmap &&
244
map1->n_bits==map2->n_bits);
246
end= map1->last_word_ptr;
247
*map1->last_word_ptr &= ~map1->last_word_mask;
248
*map2->last_word_ptr &= ~map2->last_word_mask;
251
if ((*m1++) & ~(*m2++))
257
/* True if bitmaps has any common bits */
259
bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2)
261
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
263
assert(map1->bitmap && map2->bitmap &&
264
map1->n_bits==map2->n_bits);
266
end= map1->last_word_ptr;
267
*map1->last_word_ptr &= ~map1->last_word_mask;
268
*map2->last_word_ptr &= ~map2->last_word_mask;
271
if ((*m1++) & (*m2++))
278
void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
280
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
281
uint32_t len= no_words_in_map(map), len2 = no_words_in_map(map2);
283
assert(map->bitmap && map2->bitmap);
285
end= to+cmin(len,len2);
286
*map2->last_word_ptr&= ~map2->last_word_mask; /*Clear last bits in map2*/
300
Set/clear all bits above a bit.
304
map RETURN The bitmap to change.
305
from_byte The bitmap buffer byte offset to start with.
306
use_bit The bit value (1/0) to use for all upper bits.
309
You can only set/clear full bytes.
310
The function is meant for the situation that you copy a smaller bitmap
311
to a bigger bitmap. Bitmap lengths are always multiple of eigth (the
312
size of a byte). Using 'from_byte' saves multiplication and division
313
by eight during parameter passing.
319
void bitmap_set_above(MY_BITMAP *map, uint32_t from_byte, uint32_t use_bit)
321
unsigned char use_byte= use_bit ? 0xff : 0;
322
unsigned char *to= (unsigned char *)map->bitmap + from_byte;
323
unsigned char *end= (unsigned char *)map->bitmap + (map->n_bits+7)/8;
330
void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
332
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
333
assert(map->bitmap && map2->bitmap &&
334
map->n_bits==map2->n_bits);
336
end= map->last_word_ptr;
343
void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
345
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
347
assert(map->bitmap && map2->bitmap &&
348
map->n_bits==map2->n_bits);
349
end= map->last_word_ptr;
356
void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2)
358
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr;
359
assert(map->bitmap && map2->bitmap &&
360
map->n_bits==map2->n_bits);
366
void bitmap_invert(MY_BITMAP *map)
368
my_bitmap_map *to= map->bitmap, *end;
371
end= map->last_word_ptr;
378
uint32_t bitmap_bits_set(const MY_BITMAP *map)
380
unsigned char *m= (unsigned char*)map->bitmap;
381
unsigned char *end= m + no_bytes_in_map(map);
385
*map->last_word_ptr&= ~map->last_word_mask; /*Reset last bits to zero*/
387
res+= my_count_bits_uint16(*m++);
392
void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2)
394
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
396
assert(map->bitmap && map2->bitmap &&
397
map->n_bits==map2->n_bits);
398
end= map->last_word_ptr;
404
uint32_t bitmap_get_first_set(const MY_BITMAP *map)
406
unsigned char *byte_ptr;
408
my_bitmap_map *data_ptr, *end= map->last_word_ptr;
411
data_ptr= map->bitmap;
412
*map->last_word_ptr &= ~map->last_word_mask;
414
for (i=0; data_ptr <= end; data_ptr++, i++)
418
byte_ptr= (unsigned char*)data_ptr;
419
for (j=0; ; j++, byte_ptr++)
425
if (*byte_ptr & (1 << k))
426
return (i*32) + (j*8) + k;
436
uint32_t bitmap_get_first(const MY_BITMAP *map)
438
unsigned char *byte_ptr;
440
my_bitmap_map *data_ptr, *end= map->last_word_ptr;
443
data_ptr= map->bitmap;
444
*map->last_word_ptr|= map->last_word_mask;
446
for (i=0; data_ptr <= end; data_ptr++, i++)
448
if (*data_ptr != 0xFFFFFFFF)
450
byte_ptr= (unsigned char*)data_ptr;
451
for (j=0; ; j++, byte_ptr++)
453
if (*byte_ptr != 0xFF)
457
if (!(*byte_ptr & (1 << k)))
458
return (i*32) + (j*8) + k;
470
uint32_t get_rand_bit(uint32_t bitsize)
472
return (rand() % bitsize);
475
bool test_set_get_clear_bit(MY_BITMAP *map, uint32_t bitsize)
477
uint32_t i, test_bit;
478
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
479
for (i=0; i < no_loops; i++)
481
test_bit= get_rand_bit(bitsize);
482
bitmap_set_bit(map, test_bit);
483
if (!bitmap_is_set(map, test_bit))
485
bitmap_clear_bit(map, test_bit);
486
if (bitmap_is_set(map, test_bit))
491
printf("Error in set bit, bit %u, bitsize = %u", test_bit, bitsize);
494
printf("Error in clear bit, bit %u, bitsize = %u", test_bit, bitsize);
498
bool test_flip_bit(MY_BITMAP *map, uint32_t bitsize)
500
uint32_t i, test_bit;
501
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
502
for (i=0; i < no_loops; i++)
504
test_bit= get_rand_bit(bitsize);
505
bitmap_flip_bit(map, test_bit);
506
if (!bitmap_is_set(map, test_bit))
508
bitmap_flip_bit(map, test_bit);
509
if (bitmap_is_set(map, test_bit))
514
printf("Error in flip bit 1, bit %u, bitsize = %u", test_bit, bitsize);
517
printf("Error in flip bit 2, bit %u, bitsize = %u", test_bit, bitsize);
521
bool test_operators(MY_BITMAP *, uint32_t)
526
bool test_get_all_bits(MY_BITMAP *map, uint32_t bitsize)
530
if (!bitmap_is_set_all(map))
532
if (!bitmap_is_prefix(map, bitsize))
534
bitmap_clear_all(map);
535
if (!bitmap_is_clear_all(map))
537
if (!bitmap_is_prefix(map, 0))
539
for (i=0; i<bitsize;i++)
540
bitmap_set_bit(map, i);
541
if (!bitmap_is_set_all(map))
543
for (i=0; i<bitsize;i++)
544
bitmap_clear_bit(map, i);
545
if (!bitmap_is_clear_all(map))
549
printf("Error in set_all, bitsize = %u", bitsize);
552
printf("Error in clear_all, bitsize = %u", bitsize);
555
printf("Error in bitmap_is_set_all, bitsize = %u", bitsize);
558
printf("Error in bitmap_is_clear_all, bitsize = %u", bitsize);
561
printf("Error in set_all through set_prefix, bitsize = %u", bitsize);
564
printf("Error in clear_all through set_prefix, bitsize = %u", bitsize);
568
bool test_compare_operators(MY_BITMAP *map, uint32_t bitsize)
570
uint32_t i, j, test_bit1, test_bit2, test_bit3,test_bit4;
571
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
572
MY_BITMAP map2_obj, map3_obj;
573
MY_BITMAP *map2= &map2_obj, *map3= &map3_obj;
574
my_bitmap_map map2buf[1024];
575
my_bitmap_map map3buf[1024];
576
bitmap_init(&map2_obj, map2buf, bitsize);
577
bitmap_init(&map3_obj, map3buf, bitsize);
578
bitmap_clear_all(map2);
579
bitmap_clear_all(map3);
580
for (i=0; i < no_loops; i++)
582
test_bit1=get_rand_bit(bitsize);
583
bitmap_set_prefix(map, test_bit1);
584
test_bit2=get_rand_bit(bitsize);
585
bitmap_set_prefix(map2, test_bit2);
586
bitmap_intersect(map, map2);
587
test_bit3= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
588
bitmap_set_prefix(map3, test_bit3);
589
if (!bitmap_cmp(map, map3))
591
bitmap_clear_all(map);
592
bitmap_clear_all(map2);
593
bitmap_clear_all(map3);
594
test_bit1=get_rand_bit(bitsize);
595
test_bit2=get_rand_bit(bitsize);
596
test_bit3=get_rand_bit(bitsize);
597
bitmap_set_prefix(map, test_bit1);
598
bitmap_set_prefix(map2, test_bit2);
599
test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
600
bitmap_set_prefix(map3, test_bit3);
601
bitmap_union(map, map2);
602
if (!bitmap_cmp(map, map3))
604
bitmap_clear_all(map);
605
bitmap_clear_all(map2);
606
bitmap_clear_all(map3);
607
test_bit1=get_rand_bit(bitsize);
608
test_bit2=get_rand_bit(bitsize);
609
test_bit3=get_rand_bit(bitsize);
610
bitmap_set_prefix(map, test_bit1);
611
bitmap_set_prefix(map2, test_bit2);
612
bitmap_xor(map, map2);
613
test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
614
test_bit4= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
615
bitmap_set_prefix(map3, test_bit3);
616
for (j=0; j < test_bit4; j++)
617
bitmap_clear_bit(map3, j);
618
if (!bitmap_cmp(map, map3))
620
bitmap_clear_all(map);
621
bitmap_clear_all(map2);
622
bitmap_clear_all(map3);
623
test_bit1=get_rand_bit(bitsize);
624
test_bit2=get_rand_bit(bitsize);
625
test_bit3=get_rand_bit(bitsize);
626
bitmap_set_prefix(map, test_bit1);
627
bitmap_set_prefix(map2, test_bit2);
628
bitmap_subtract(map, map2);
629
if (test_bit2 < test_bit1)
631
bitmap_set_prefix(map3, test_bit1);
632
for (j=0; j < test_bit2; j++)
633
bitmap_clear_bit(map3, j);
635
if (!bitmap_cmp(map, map3))
637
bitmap_clear_all(map);
638
bitmap_clear_all(map2);
639
bitmap_clear_all(map3);
640
test_bit1=get_rand_bit(bitsize);
641
bitmap_set_prefix(map, test_bit1);
643
bitmap_set_all(map3);
644
for (j=0; j < test_bit1; j++)
645
bitmap_clear_bit(map3, j);
646
if (!bitmap_cmp(map, map3))
648
bitmap_clear_all(map);
649
bitmap_clear_all(map3);
653
printf("intersect error bitsize=%u,size1=%u,size2=%u", bitsize,
654
test_bit1,test_bit2);
657
printf("union error bitsize=%u,size1=%u,size2=%u", bitsize,
658
test_bit1,test_bit2);
661
printf("xor error bitsize=%u,size1=%u,size2=%u", bitsize,
662
test_bit1,test_bit2);
665
printf("subtract error bitsize=%u,size1=%u,size2=%u", bitsize,
666
test_bit1,test_bit2);
669
printf("invert error bitsize=%u,size=%u", bitsize,
674
bool test_count_bits_set(MY_BITMAP *map, uint32_t bitsize)
676
uint32_t i, bit_count=0, test_bit;
677
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
678
for (i=0; i < no_loops; i++)
680
test_bit=get_rand_bit(bitsize);
681
if (!bitmap_is_set(map, test_bit))
683
bitmap_set_bit(map, test_bit);
687
if (bit_count==0 && bitsize > 0)
689
if (bitmap_bits_set(map) != bit_count)
693
printf("No bits set bitsize = %u", bitsize);
696
printf("Wrong count of bits set, bitsize = %u", bitsize);
700
bool test_get_first_bit(MY_BITMAP *map, uint32_t bitsize)
702
uint32_t i, test_bit;
703
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
704
for (i=0; i < no_loops; i++)
706
test_bit=get_rand_bit(bitsize);
707
bitmap_set_bit(map, test_bit);
708
if (bitmap_get_first_set(map) != test_bit)
711
bitmap_clear_bit(map, test_bit);
712
if (bitmap_get_first(map) != test_bit)
714
bitmap_clear_all(map);
718
printf("get_first_set error bitsize=%u,prefix_size=%u",bitsize,test_bit);
721
printf("get_first error bitsize= %u, prefix_size= %u",bitsize,test_bit);
725
bool test_get_next_bit(MY_BITMAP *map, uint32_t bitsize)
727
uint32_t i, j, test_bit;
728
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
729
for (i=0; i < no_loops; i++)
731
test_bit=get_rand_bit(bitsize);
732
for (j=0; j < test_bit; j++)
733
bitmap_set_next(map);
734
if (!bitmap_is_prefix(map, test_bit))
736
bitmap_clear_all(map);
740
printf("get_next error bitsize= %u, prefix_size= %u", bitsize,test_bit);
744
bool test_prefix(MY_BITMAP *map, uint32_t bitsize)
746
uint32_t i, j, test_bit;
747
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
748
for (i=0; i < no_loops; i++)
750
test_bit=get_rand_bit(bitsize);
751
bitmap_set_prefix(map, test_bit);
752
if (!bitmap_is_prefix(map, test_bit))
754
bitmap_clear_all(map);
755
for (j=0; j < test_bit; j++)
756
bitmap_set_bit(map, j);
757
if (!bitmap_is_prefix(map, test_bit))
760
for (j=bitsize - 1; ~(j-test_bit); j--)
761
bitmap_clear_bit(map, j);
762
if (!bitmap_is_prefix(map, test_bit))
764
bitmap_clear_all(map);
768
printf("prefix1 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
771
printf("prefix2 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
774
printf("prefix3 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
779
bool do_test(uint32_t bitsize)
782
my_bitmap_map buf[1024];
783
if (bitmap_init(&map, buf, bitsize))
785
printf("init error for bitsize %d", bitsize);
788
if (test_set_get_clear_bit(&map,bitsize))
790
bitmap_clear_all(&map);
791
if (test_flip_bit(&map,bitsize))
793
bitmap_clear_all(&map);
794
if (test_operators(&map,bitsize))
796
bitmap_clear_all(&map);
797
if (test_get_all_bits(&map, bitsize))
799
bitmap_clear_all(&map);
800
if (test_compare_operators(&map,bitsize))
802
bitmap_clear_all(&map);
803
if (test_count_bits_set(&map,bitsize))
805
bitmap_clear_all(&map);
806
if (test_get_first_bit(&map,bitsize))
808
bitmap_clear_all(&map);
809
if (test_get_next_bit(&map,bitsize))
811
if (test_prefix(&map,bitsize))
822
for (i= 1; i < 4096; i++)
824
printf("Start test for bitsize=%u\n",i);
835
will build the bitmap tests and ./test_bitmap will execute it