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 */
16
#include "mysys_priv.h"
17
#include <mysys/my_bitmap.h>
18
#include <mystrings/m_string.h>
19
#include <mysys/my_bit.h>
23
void MyBitmap::createLastWordMask()
25
/* Get the number of used bits (1..8) in the last byte */
26
unsigned int const used= 1U + ((n_bits-1U) & 0x7U);
29
Create a mask with the upper 'unused' bits set and the lower 'used'
30
bits clear. The bits within each byte is stored in big-endian order.
32
unsigned char const mask= static_cast<unsigned char const>((~((1 << used) - 1)) & 255);
35
The first bytes are to be set to zero since they represent real bits
36
in the bitvector. The last bytes are set to 0xFF since they represent
37
bytes not used by the bitvector. Finally the last byte contains bits
38
as set by the mask above.
40
unsigned char *ptr= (unsigned char*)&last_word_mask;
42
last_word_ptr= bitmap + numOfWordsInMap()-1;
43
switch (numOfBytesInMap() & 3)
46
last_word_mask= UINT32_MAX;
50
last_word_mask= UINT32_MAX;
67
bool MyBitmap::init(my_bitmap_map *buf, uint32_t num_bits)
71
uint32_t size_in_bytes= bitmap_buffer_size(num_bits);
72
if (! (buf= new(std::nothrow) my_bitmap_map[size_in_bytes]()))
87
bool MyBitmap::testAndSet(const uint32_t bitPos)
89
unsigned char *value= ((unsigned char*) bitmap) + (bitPos / 8);
90
unsigned char bit= static_cast<unsigned char>(1 << ((bitPos) & 7));
91
unsigned char res= static_cast<unsigned char>((*value) & bit);
92
*value= static_cast<unsigned char>(*value | bit);
98
bool MyBitmap::testAndClear(const uint32_t bitPos)
100
unsigned char *byte= (unsigned char*) bitmap + (bitPos / 8);
101
unsigned char bit= static_cast<unsigned char>(1 << ((bitPos) & 7));
102
unsigned char res= static_cast<unsigned char>((*byte) & bit);
103
*byte= static_cast<unsigned char>(*byte & ~bit);
109
uint32_t MyBitmap::setNext()
113
if ((bit_found= getFirst()) != MY_BIT_NONE)
121
void MyBitmap::setPrefix(uint32_t prefix_size)
123
uint32_t prefix_bytes, prefix_bits, d;
124
unsigned char *m= (unsigned char *) bitmap;
127
(prefix_size <= n_bits || prefix_size == UINT32_MAX));
128
set_if_smaller(prefix_size, n_bits);
129
if ((prefix_bytes= prefix_size / 8))
131
memset(m, 0xff, prefix_bytes);
134
if ((prefix_bits= prefix_size & 7))
136
*m++= static_cast<unsigned char>((1 << prefix_bits)-1);
138
if ((d= numOfBytesInMap() - prefix_bytes))
145
bool MyBitmap::isPrefix(const uint32_t prefix_size) const
147
uint32_t prefix_bits= prefix_size & 0x7, res;
148
unsigned char *m= (unsigned char*) bitmap;
149
unsigned char *end_prefix= m + prefix_size/8;
151
assert(m && prefix_size <= n_bits);
152
end= m + numOfBytesInMap();
154
while (m < end_prefix)
162
*last_word_ptr&= ~last_word_mask; /*Clear bits*/
164
if (prefix_bits && *m++ != (1 << prefix_bits)-1)
182
bool MyBitmap::isSetAll() const
184
my_bitmap_map *data_ptr= bitmap;
185
my_bitmap_map *end= last_word_ptr;
186
*last_word_ptr |= last_word_mask;
187
for (; data_ptr <= end; data_ptr++)
189
if (*data_ptr != 0xFFFFFFFF)
198
bool MyBitmap::isClearAll() const
200
my_bitmap_map *data_ptr= bitmap;
202
if (*last_word_ptr & ~last_word_mask)
207
for (; data_ptr < end; data_ptr++)
217
/* Return true if map1 is a subset of map2 */
219
bool bitmap_is_subset(const MyBitmap *map1, const MyBitmap *map2)
221
my_bitmap_map *m1= map1->getBitmap(), *m2= map2->getBitmap(), *end;
223
assert(map1->getBitmap() && map2->getBitmap() &&
224
map1->numOfBitsInMap() == map2->numOfBitsInMap());
226
end= map1->getLastWordPtr();
227
map1->subtractMaskFromLastWord();
228
map2->subtractMaskFromLastWord();
231
if ((*m1++) & ~(*m2++))
239
/* True if bitmaps has any common bits */
241
bool bitmap_is_overlapping(const MyBitmap *map1, const MyBitmap *map2)
243
my_bitmap_map *m1= map1->getBitmap(), *m2= map2->getBitmap(), *end;
245
assert(map1->getBitmap() && map2->getBitmap() &&
246
map1->numOfBitsInMap() == map2->numOfBitsInMap());
248
end= map1->getLastWordPtr();
249
map1->subtractMaskFromLastWord();
250
map2->subtractMaskFromLastWord();
253
if ((*m1++) & (*m2++))
260
void bitmap_intersect(MyBitmap *map, const MyBitmap *map2)
262
my_bitmap_map *to= map->getBitmap(), *from= map2->getBitmap(), *end;
263
uint32_t len= map->numOfWordsInMap(), len2 = map2->numOfWordsInMap();
265
assert(map->getBitmap() && map2->getBitmap());
267
end= to+min(len,len2);
268
map2->subtractMaskFromLastWord(); /* Clear last bits in map2 */
285
void MyBitmap::setAbove(const uint32_t from_byte, const uint32_t use_bit)
287
unsigned char use_byte= static_cast<unsigned char>(use_bit ? 0xff : 0);
288
unsigned char *to= (unsigned char *) bitmap + from_byte;
289
unsigned char *end= (unsigned char *) bitmap + (n_bits+7)/8;
298
void bitmap_subtract(MyBitmap *map, const MyBitmap *map2)
300
my_bitmap_map *to= map->getBitmap(), *from= map2->getBitmap(), *end;
301
assert(map->getBitmap() && map2->getBitmap() &&
302
map->numOfBitsInMap() == map2->numOfBitsInMap());
304
end= map->getLastWordPtr();
313
void bitmap_union(MyBitmap *map, const MyBitmap *map2)
315
my_bitmap_map *to= map->getBitmap(), *from= map2->getBitmap(), *end;
317
assert(map->getBitmap() && map2->getBitmap() &&
318
map->numOfBitsInMap() == map2->numOfBitsInMap());
319
end= map->getLastWordPtr();
328
void bitmap_xor(MyBitmap *map, const MyBitmap *map2)
330
my_bitmap_map *to= map->getBitmap();
331
my_bitmap_map *from= map2->getBitmap();
332
my_bitmap_map *end= map->getLastWordPtr();
333
assert(map->getBitmap() && map2->getBitmap() &&
334
map->numOfBitsInMap() == map2->numOfBitsInMap());
342
void bitmap_invert(MyBitmap *map)
344
my_bitmap_map *to= map->getBitmap(), *end;
346
assert(map->getBitmap());
347
end= map->getLastWordPtr();
356
uint32_t MyBitmap::getBitsSet()
358
unsigned char *m= (unsigned char*) bitmap;
359
unsigned char *end= m + numOfBytesInMap();
363
*last_word_ptr&= ~last_word_mask; /*Reset last bits to zero*/
366
res+= my_count_bits_uint16(*m++);
371
MyBitmap::MyBitmap(const MyBitmap& rhs)
373
my_bitmap_map *to= this->bitmap, *from= rhs.bitmap, *end;
375
if (this->bitmap && rhs.bitmap &&
376
this->n_bits == rhs.n_bits)
378
end= this->last_word_ptr;
386
this->n_bits= rhs.n_bits;
387
this->bitmap= rhs.bitmap;
391
MyBitmap& MyBitmap::operator=(const MyBitmap& rhs)
396
my_bitmap_map *to= this->bitmap, *from= rhs.bitmap, *end;
398
if (this->bitmap && rhs.bitmap &&
399
this->n_bits == rhs.n_bits)
401
end= this->last_word_ptr;
409
this->n_bits= rhs.n_bits;
410
this->bitmap= rhs.bitmap;
416
uint32_t MyBitmap::getFirstSet()
418
unsigned char *byte_ptr;
420
my_bitmap_map *data_ptr, *end= last_word_ptr;
424
*last_word_ptr &= ~last_word_mask;
426
for (i=0; data_ptr <= end; data_ptr++, i++)
430
byte_ptr= (unsigned char*)data_ptr;
431
for (j=0; ; j++, byte_ptr++)
437
if (*byte_ptr & (1 << k))
438
return (i*32) + (j*8) + k;
448
uint32_t MyBitmap::getFirst()
450
unsigned char *byte_ptr;
452
my_bitmap_map *data_ptr, *end= last_word_ptr;
456
*last_word_ptr|= last_word_mask;
458
for (i=0; data_ptr <= end; data_ptr++, i++)
460
if (*data_ptr != 0xFFFFFFFF)
462
byte_ptr= (unsigned char*)data_ptr;
463
for (j=0; ; j++, byte_ptr++)
465
if (*byte_ptr != 0xFF)
469
if (!(*byte_ptr & (1 << k)))
470
return (i*32) + (j*8) + k;
482
uint32_t get_rand_bit(uint32_t bitsize)
484
return (rand() % bitsize);
487
bool test_set_get_clear_bit(MyBitmap *map, uint32_t bitsize)
489
uint32_t i, test_bit;
490
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
491
for (i=0; i < no_loops; i++)
493
test_bit= get_rand_bit(bitsize);
494
map->setBit(test_bit);
495
if (! map->isBitSet(test_bit))
499
map->clearBit(test_bit);
500
if (map->isBitSet(test_bit))
507
printf("Error in set bit, bit %u, bitsize = %u", test_bit, bitsize);
510
printf("Error in clear bit, bit %u, bitsize = %u", test_bit, bitsize);
514
bool test_flip_bit(MyBitmap *map, uint32_t bitsize)
516
uint32_t i, test_bit;
517
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
518
for (i=0; i < no_loops; i++)
520
test_bit= get_rand_bit(bitsize);
521
map->flipBit(test_bit);
522
if (!map->isBitSet(test_bit))
524
map->flipBit(test_bit);
525
if (map->isBitSet(test_bit))
530
printf("Error in flip bit 1, bit %u, bitsize = %u", test_bit, bitsize);
533
printf("Error in flip bit 2, bit %u, bitsize = %u", test_bit, bitsize);
537
bool test_operators(MyBitmap *, uint32_t)
542
bool test_get_all_bits(MyBitmap *map, uint32_t bitsize)
546
if (!map->isSetAll())
548
if (!map->isPrefix(bitsize))
551
if (!map->isClearAll())
553
if (!map->isPrefix(0))
555
for (i=0; i<bitsize;i++)
557
if (!map->isSetAll())
559
for (i=0; i<bitsize;i++)
561
if (!map->isClearAll())
565
printf("Error in set_all, bitsize = %u", bitsize);
568
printf("Error in clear_all, bitsize = %u", bitsize);
571
printf("Error in bitmap_is_set_all, bitsize = %u", bitsize);
574
printf("Error in bitmap_is_clear_all, bitsize = %u", bitsize);
577
printf("Error in set_all through set_prefix, bitsize = %u", bitsize);
580
printf("Error in clear_all through set_prefix, bitsize = %u", bitsize);
584
bool test_compare_operators(MyBitmap *map, uint32_t bitsize)
586
uint32_t i, j, test_bit1, test_bit2, test_bit3,test_bit4;
587
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
588
MyBitmap map2_obj, map3_obj;
589
MyBitmap *map2= &map2_obj, *map3= &map3_obj;
590
my_bitmap_map map2buf[1024];
591
my_bitmap_map map3buf[1024];
592
map2_obj.init(map2buf, bitsize);
593
map3_obj.init(map3buf, bitsize);
596
for (i=0; i < no_loops; i++)
598
test_bit1=get_rand_bit(bitsize);
599
map->setPrefix(test_bit1);
600
test_bit2=get_rand_bit(bitsize);
601
map2->setPrefix(test_bit2);
602
bitmap_intersect(map, map2);
603
test_bit3= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
604
map3->setPrefix(test_bit3);
605
if (!bitmap_cmp(map, map3))
610
test_bit1=get_rand_bit(bitsize);
611
test_bit2=get_rand_bit(bitsize);
612
test_bit3=get_rand_bit(bitsize);
613
map->setPrefix(test_bit1);
614
map2->setPrefix(test_bit2);
615
test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
616
map3->setPrefix(test_bit3);
617
bitmap_union(map, map2);
618
if (!bitmap_cmp(map, map3))
623
test_bit1=get_rand_bit(bitsize);
624
test_bit2=get_rand_bit(bitsize);
625
test_bit3=get_rand_bit(bitsize);
626
map->setPrefix(test_bit1);
627
map2->setPrefix(test_bit2);
628
bitmap_xor(map, map2);
629
test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
630
test_bit4= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
631
map3->setPrefix(test_bit3);
632
for (j=0; j < test_bit4; j++)
634
if (!bitmap_cmp(map, map3))
639
test_bit1=get_rand_bit(bitsize);
640
test_bit2=get_rand_bit(bitsize);
641
test_bit3=get_rand_bit(bitsize);
642
map->setPrefix(test_bit1);
643
map2->setPrefix(test_bit2);
644
bitmap_subtract(map, map2);
645
if (test_bit2 < test_bit1)
647
map3->setPrefix(test_bit1);
648
for (j=0; j < test_bit2; j++)
651
if (!bitmap_cmp(map, map3))
656
test_bit1=get_rand_bit(bitsize);
657
map->setPrefix(test_bit1);
660
for (j=0; j < test_bit1; j++)
662
if (!bitmap_cmp(map, map3))
669
printf("intersect error bitsize=%u,size1=%u,size2=%u", bitsize,
670
test_bit1,test_bit2);
673
printf("union error bitsize=%u,size1=%u,size2=%u", bitsize,
674
test_bit1,test_bit2);
677
printf("xor error bitsize=%u,size1=%u,size2=%u", bitsize,
678
test_bit1,test_bit2);
681
printf("subtract error bitsize=%u,size1=%u,size2=%u", bitsize,
682
test_bit1,test_bit2);
685
printf("invert error bitsize=%u,size=%u", bitsize,
690
bool test_count_bits_set(MyBitmap *map, uint32_t bitsize)
692
uint32_t i, bit_count=0, test_bit;
693
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
694
for (i=0; i < no_loops; i++)
696
test_bit=get_rand_bit(bitsize);
697
if (!map->isBitSet(test_bit))
699
map->setBit(test_bit);
703
if (bit_count==0 && bitsize > 0)
705
if (getBitsSet() != bit_count)
709
printf("No bits set bitsize = %u", bitsize);
712
printf("Wrong count of bits set, bitsize = %u", bitsize);
716
bool test_get_first_bit(MyBitmap *map, uint32_t bitsize)
718
uint32_t i, test_bit;
719
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
720
for (i=0; i < no_loops; i++)
722
test_bit=get_rand_bit(bitsize);
723
map->setBit(test_bit);
724
if (bitmap_get_first_set(map) != test_bit)
727
map->clearBit(test_bit);
728
if (getFirst() != test_bit)
734
printf("get_first_set error bitsize=%u,prefix_size=%u",bitsize,test_bit);
737
printf("get_first error bitsize= %u, prefix_size= %u",bitsize,test_bit);
741
bool test_get_next_bit(MyBitmap *map, uint32_t bitsize)
743
uint32_t i, j, test_bit;
744
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
745
for (i=0; i < no_loops; i++)
747
test_bit=get_rand_bit(bitsize);
748
for (j=0; j < test_bit; j++)
750
if (!map->isPrefix(test_bit))
756
printf("get_next error bitsize= %u, prefix_size= %u", bitsize,test_bit);
760
bool test_prefix(MyBitmap *map, uint32_t bitsize)
762
uint32_t i, j, test_bit;
763
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
764
for (i=0; i < no_loops; i++)
766
test_bit=get_rand_bit(bitsize);
767
map->setPrefix(map, test_bit);
768
if (!map->isPrefix(test_bit))
771
for (j=0; j < test_bit; j++)
773
if (!map->isPrefix(test_bit))
776
for (j=bitsize - 1; ~(j-test_bit); j--)
778
if (!map->isPrefix(test_bit))
784
printf("prefix1 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
787
printf("prefix2 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
790
printf("prefix3 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
795
bool do_test(uint32_t bitsize)
798
my_bitmap_map buf[1024];
799
if (map.init(buf, bitsize))
801
printf("init error for bitsize %d", bitsize);
804
if (test_set_get_clear_bit(&map,bitsize))
807
if (test_flip_bit(&map,bitsize))
810
if (test_operators(&map,bitsize))
813
if (test_get_all_bits(&map, bitsize))
816
if (test_compare_operators(&map,bitsize))
819
if (test_count_bits_set(&map,bitsize))
822
if (test_get_first_bit(&map,bitsize))
825
if (test_get_next_bit(&map,bitsize))
827
if (test_prefix(&map,bitsize))
838
for (i= 1; i < 4096; i++)
840
printf("Start test for bitsize=%u\n",i);
851
will build the bitmap tests and ./test_bitmap will execute it