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 */
18
#include <drizzled/sql_bitmap.h>
19
#include "drizzled/internal/m_string.h"
20
#include "drizzled/internal/my_bit.h"
26
void MyBitmap::createLastWordMask()
28
/* Get the number of used bits (1..8) in the last byte */
29
unsigned int const used= 1U + ((n_bits-1U) & 0x7U);
32
Create a mask with the upper 'unused' bits set and the lower 'used'
33
bits clear. The bits within each byte is stored in big-endian order.
35
unsigned char const mask= static_cast<unsigned char const>((~((1 << used) - 1)) & 255);
38
The first bytes are to be set to zero since they represent real bits
39
in the bitvector. The last bytes are set to 0xFF since they represent
40
bytes not used by the bitvector. Finally the last byte contains bits
41
as set by the mask above.
43
unsigned char *ptr= (unsigned char*)&last_word_mask;
45
last_word_ptr= bitmap + numOfWordsInMap()-1;
46
switch (numOfBytesInMap() & 3)
49
last_word_mask= UINT32_MAX;
53
last_word_mask= UINT32_MAX;
70
bool MyBitmap::init(my_bitmap_map *buf, uint32_t num_bits)
74
uint32_t size_in_bytes= bitmap_buffer_size(num_bits);
75
if (! (buf= new(nothrow) my_bitmap_map[size_in_bytes]()))
90
bool MyBitmap::testAndSet(const uint32_t bitPos)
92
unsigned char *value= ((unsigned char*) bitmap) + (bitPos / 8);
93
unsigned char bit= static_cast<unsigned char>(1 << ((bitPos) & 7));
94
unsigned char res= static_cast<unsigned char>((*value) & bit);
95
*value= static_cast<unsigned char>(*value | bit);
101
bool MyBitmap::testAndClear(const uint32_t bitPos)
103
unsigned char *byte= (unsigned char*) bitmap + (bitPos / 8);
104
unsigned char bit= static_cast<unsigned char>(1 << ((bitPos) & 7));
105
unsigned char res= static_cast<unsigned char>((*byte) & bit);
106
*byte= static_cast<unsigned char>(*byte & ~bit);
112
uint32_t MyBitmap::setNext()
116
if ((bit_found= getFirst()) != MY_BIT_NONE)
124
void MyBitmap::setPrefix(uint32_t prefix_size)
126
uint32_t prefix_bytes, prefix_bits, d;
127
unsigned char *m= (unsigned char *) bitmap;
130
(prefix_size <= n_bits || prefix_size == UINT32_MAX));
131
set_if_smaller(prefix_size, n_bits);
132
if ((prefix_bytes= prefix_size / 8))
134
memset(m, 0xff, prefix_bytes);
137
if ((prefix_bits= prefix_size & 7))
139
*m++= static_cast<unsigned char>((1 << prefix_bits)-1);
141
if ((d= numOfBytesInMap() - prefix_bytes))
148
bool MyBitmap::isPrefix(const uint32_t prefix_size) const
150
uint32_t prefix_bits= prefix_size & 0x7, res;
151
unsigned char *m= (unsigned char*) bitmap;
152
unsigned char *end_prefix= m + prefix_size/8;
154
assert(m && prefix_size <= n_bits);
155
end= m + numOfBytesInMap();
157
while (m < end_prefix)
165
*last_word_ptr&= ~last_word_mask; /*Clear bits*/
167
if (prefix_bits && *m++ != (1 << prefix_bits)-1)
185
bool MyBitmap::isSetAll() const
187
my_bitmap_map *data_ptr= bitmap;
188
my_bitmap_map *end= last_word_ptr;
189
*last_word_ptr |= last_word_mask;
190
for (; data_ptr <= end; data_ptr++)
192
if (*data_ptr != 0xFFFFFFFF)
201
bool MyBitmap::isClearAll() const
203
my_bitmap_map *data_ptr= bitmap;
205
if (*last_word_ptr & ~last_word_mask)
210
for (; data_ptr < end; data_ptr++)
220
/* Return true if map1 is a subset of map2 */
222
bool bitmap_is_subset(const MyBitmap *map1, const MyBitmap *map2)
224
my_bitmap_map *m1= map1->getBitmap(), *m2= map2->getBitmap(), *end;
226
assert(map1->getBitmap() && map2->getBitmap() &&
227
map1->numOfBitsInMap() == map2->numOfBitsInMap());
229
end= map1->getLastWordPtr();
230
map1->subtractMaskFromLastWord();
231
map2->subtractMaskFromLastWord();
234
if ((*m1++) & ~(*m2++))
242
/* True if bitmaps has any common bits */
244
bool bitmap_is_overlapping(const MyBitmap *map1, const MyBitmap *map2)
246
my_bitmap_map *m1= map1->getBitmap(), *m2= map2->getBitmap(), *end;
248
assert(map1->getBitmap() && map2->getBitmap() &&
249
map1->numOfBitsInMap() == map2->numOfBitsInMap());
251
end= map1->getLastWordPtr();
252
map1->subtractMaskFromLastWord();
253
map2->subtractMaskFromLastWord();
256
if ((*m1++) & (*m2++))
263
void bitmap_intersect(MyBitmap *map, const MyBitmap *map2)
265
my_bitmap_map *to= map->getBitmap(), *from= map2->getBitmap(), *end;
266
uint32_t len= map->numOfWordsInMap(), len2 = map2->numOfWordsInMap();
268
assert(map->getBitmap() && map2->getBitmap());
270
end= to+min(len,len2);
271
map2->subtractMaskFromLastWord(); /* Clear last bits in map2 */
288
void MyBitmap::setAbove(const uint32_t from_byte, const uint32_t use_bit)
290
unsigned char use_byte= static_cast<unsigned char>(use_bit ? 0xff : 0);
291
unsigned char *to= (unsigned char *) bitmap + from_byte;
292
unsigned char *end= (unsigned char *) bitmap + (n_bits+7)/8;
301
void bitmap_subtract(MyBitmap *map, const MyBitmap *map2)
303
my_bitmap_map *to= map->getBitmap(), *from= map2->getBitmap(), *end;
304
assert(map->getBitmap() && map2->getBitmap() &&
305
map->numOfBitsInMap() == map2->numOfBitsInMap());
307
end= map->getLastWordPtr();
316
void bitmap_union(MyBitmap *map, const MyBitmap *map2)
318
my_bitmap_map *to= map->getBitmap(), *from= map2->getBitmap(), *end;
320
assert(map->getBitmap() && map2->getBitmap() &&
321
map->numOfBitsInMap() == map2->numOfBitsInMap());
322
end= map->getLastWordPtr();
331
void bitmap_xor(MyBitmap *map, const MyBitmap *map2)
333
my_bitmap_map *to= map->getBitmap();
334
my_bitmap_map *from= map2->getBitmap();
335
my_bitmap_map *end= map->getLastWordPtr();
336
assert(map->getBitmap() && map2->getBitmap() &&
337
map->numOfBitsInMap() == map2->numOfBitsInMap());
345
void bitmap_invert(MyBitmap *map)
347
my_bitmap_map *to= map->getBitmap(), *end;
349
assert(map->getBitmap());
350
end= map->getLastWordPtr();
359
uint32_t MyBitmap::getBitsSet()
361
unsigned char *m= (unsigned char*) bitmap;
362
unsigned char *end= m + numOfBytesInMap();
366
*last_word_ptr&= ~last_word_mask; /*Reset last bits to zero*/
369
res+= my_count_bits_uint16(*m++);
374
MyBitmap::MyBitmap(const MyBitmap& rhs)
376
my_bitmap_map *to= this->bitmap, *from= rhs.bitmap, *end;
378
if (this->bitmap && rhs.bitmap &&
379
this->n_bits == rhs.n_bits)
381
end= this->last_word_ptr;
389
this->n_bits= rhs.n_bits;
390
this->bitmap= rhs.bitmap;
394
MyBitmap& MyBitmap::operator=(const MyBitmap& rhs)
399
my_bitmap_map *to= this->bitmap, *from= rhs.bitmap, *end;
401
if (this->bitmap && rhs.bitmap &&
402
this->n_bits == rhs.n_bits)
404
end= this->last_word_ptr;
412
this->n_bits= rhs.n_bits;
413
this->bitmap= rhs.bitmap;
419
uint32_t MyBitmap::getFirstSet()
421
unsigned char *byte_ptr;
423
my_bitmap_map *data_ptr, *end= last_word_ptr;
427
*last_word_ptr &= ~last_word_mask;
429
for (i=0; data_ptr <= end; data_ptr++, i++)
433
byte_ptr= (unsigned char*)data_ptr;
434
for (j=0; ; j++, byte_ptr++)
440
if (*byte_ptr & (1 << k))
441
return (i*32) + (j*8) + k;
451
uint32_t MyBitmap::getFirst()
453
unsigned char *byte_ptr;
455
my_bitmap_map *data_ptr, *end= last_word_ptr;
459
*last_word_ptr|= last_word_mask;
461
for (i=0; data_ptr <= end; data_ptr++, i++)
463
if (*data_ptr != 0xFFFFFFFF)
465
byte_ptr= (unsigned char*)data_ptr;
466
for (j=0; ; j++, byte_ptr++)
468
if (*byte_ptr != 0xFF)
472
if (!(*byte_ptr & (1 << k)))
473
return (i*32) + (j*8) + k;
485
uint32_t get_rand_bit(uint32_t bitsize)
487
return (rand() % bitsize);
490
bool test_set_get_clear_bit(MyBitmap *map, uint32_t bitsize)
492
uint32_t i, test_bit;
493
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
494
for (i=0; i < no_loops; i++)
496
test_bit= get_rand_bit(bitsize);
497
map->setBit(test_bit);
498
if (! map->isBitSet(test_bit))
502
map->clearBit(test_bit);
503
if (map->isBitSet(test_bit))
510
printf("Error in set bit, bit %u, bitsize = %u", test_bit, bitsize);
513
printf("Error in clear bit, bit %u, bitsize = %u", test_bit, bitsize);
517
bool test_flip_bit(MyBitmap *map, uint32_t bitsize)
519
uint32_t i, test_bit;
520
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
521
for (i=0; i < no_loops; i++)
523
test_bit= get_rand_bit(bitsize);
524
map->flipBit(test_bit);
525
if (!map->isBitSet(test_bit))
527
map->flipBit(test_bit);
528
if (map->isBitSet(test_bit))
533
printf("Error in flip bit 1, bit %u, bitsize = %u", test_bit, bitsize);
536
printf("Error in flip bit 2, bit %u, bitsize = %u", test_bit, bitsize);
540
bool test_operators(MyBitmap *, uint32_t)
545
bool test_get_all_bits(MyBitmap *map, uint32_t bitsize)
549
if (!map->isSetAll())
551
if (!map->isPrefix(bitsize))
554
if (!map->isClearAll())
556
if (!map->isPrefix(0))
558
for (i=0; i<bitsize;i++)
560
if (!map->isSetAll())
562
for (i=0; i<bitsize;i++)
564
if (!map->isClearAll())
568
printf("Error in set_all, bitsize = %u", bitsize);
571
printf("Error in clear_all, bitsize = %u", bitsize);
574
printf("Error in bitmap_is_set_all, bitsize = %u", bitsize);
577
printf("Error in bitmap_is_clear_all, bitsize = %u", bitsize);
580
printf("Error in set_all through set_prefix, bitsize = %u", bitsize);
583
printf("Error in clear_all through set_prefix, bitsize = %u", bitsize);
587
bool test_compare_operators(MyBitmap *map, uint32_t bitsize)
589
uint32_t i, j, test_bit1, test_bit2, test_bit3,test_bit4;
590
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
591
MyBitmap map2_obj, map3_obj;
592
MyBitmap *map2= &map2_obj, *map3= &map3_obj;
593
my_bitmap_map map2buf[1024];
594
my_bitmap_map map3buf[1024];
595
map2_obj.init(map2buf, bitsize);
596
map3_obj.init(map3buf, bitsize);
599
for (i=0; i < no_loops; i++)
601
test_bit1=get_rand_bit(bitsize);
602
map->setPrefix(test_bit1);
603
test_bit2=get_rand_bit(bitsize);
604
map2->setPrefix(test_bit2);
605
bitmap_intersect(map, map2);
606
test_bit3= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
607
map3->setPrefix(test_bit3);
608
if (!bitmap_cmp(map, map3))
613
test_bit1=get_rand_bit(bitsize);
614
test_bit2=get_rand_bit(bitsize);
615
test_bit3=get_rand_bit(bitsize);
616
map->setPrefix(test_bit1);
617
map2->setPrefix(test_bit2);
618
test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
619
map3->setPrefix(test_bit3);
620
bitmap_union(map, map2);
621
if (!bitmap_cmp(map, map3))
626
test_bit1=get_rand_bit(bitsize);
627
test_bit2=get_rand_bit(bitsize);
628
test_bit3=get_rand_bit(bitsize);
629
map->setPrefix(test_bit1);
630
map2->setPrefix(test_bit2);
631
bitmap_xor(map, map2);
632
test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
633
test_bit4= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
634
map3->setPrefix(test_bit3);
635
for (j=0; j < test_bit4; j++)
637
if (!bitmap_cmp(map, map3))
642
test_bit1=get_rand_bit(bitsize);
643
test_bit2=get_rand_bit(bitsize);
644
test_bit3=get_rand_bit(bitsize);
645
map->setPrefix(test_bit1);
646
map2->setPrefix(test_bit2);
647
bitmap_subtract(map, map2);
648
if (test_bit2 < test_bit1)
650
map3->setPrefix(test_bit1);
651
for (j=0; j < test_bit2; j++)
654
if (!bitmap_cmp(map, map3))
659
test_bit1=get_rand_bit(bitsize);
660
map->setPrefix(test_bit1);
663
for (j=0; j < test_bit1; j++)
665
if (!bitmap_cmp(map, map3))
672
printf("intersect error bitsize=%u,size1=%u,size2=%u", bitsize,
673
test_bit1,test_bit2);
676
printf("union error bitsize=%u,size1=%u,size2=%u", bitsize,
677
test_bit1,test_bit2);
680
printf("xor error bitsize=%u,size1=%u,size2=%u", bitsize,
681
test_bit1,test_bit2);
684
printf("subtract error bitsize=%u,size1=%u,size2=%u", bitsize,
685
test_bit1,test_bit2);
688
printf("invert error bitsize=%u,size=%u", bitsize,
693
bool test_count_bits_set(MyBitmap *map, uint32_t bitsize)
695
uint32_t i, bit_count=0, test_bit;
696
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
697
for (i=0; i < no_loops; i++)
699
test_bit=get_rand_bit(bitsize);
700
if (!map->isBitSet(test_bit))
702
map->setBit(test_bit);
706
if (bit_count==0 && bitsize > 0)
708
if (getBitsSet() != bit_count)
712
printf("No bits set bitsize = %u", bitsize);
715
printf("Wrong count of bits set, bitsize = %u", bitsize);
719
bool test_get_first_bit(MyBitmap *map, uint32_t bitsize)
721
uint32_t i, test_bit;
722
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
723
for (i=0; i < no_loops; i++)
725
test_bit=get_rand_bit(bitsize);
726
map->setBit(test_bit);
727
if (bitmap_get_first_set(map) != test_bit)
730
map->clearBit(test_bit);
731
if (getFirst() != test_bit)
737
printf("get_first_set error bitsize=%u,prefix_size=%u",bitsize,test_bit);
740
printf("get_first error bitsize= %u, prefix_size= %u",bitsize,test_bit);
744
bool test_get_next_bit(MyBitmap *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
for (j=0; j < test_bit; j++)
753
if (!map->isPrefix(test_bit))
759
printf("get_next error bitsize= %u, prefix_size= %u", bitsize,test_bit);
763
bool test_prefix(MyBitmap *map, uint32_t bitsize)
765
uint32_t i, j, test_bit;
766
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
767
for (i=0; i < no_loops; i++)
769
test_bit=get_rand_bit(bitsize);
770
map->setPrefix(map, test_bit);
771
if (!map->isPrefix(test_bit))
774
for (j=0; j < test_bit; j++)
776
if (!map->isPrefix(test_bit))
779
for (j=bitsize - 1; ~(j-test_bit); j--)
781
if (!map->isPrefix(test_bit))
787
printf("prefix1 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
790
printf("prefix2 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
793
printf("prefix3 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
798
bool do_test(uint32_t bitsize)
801
my_bitmap_map buf[1024];
802
if (map.init(buf, bitsize))
804
printf("init error for bitsize %d", bitsize);
807
if (test_set_get_clear_bit(&map,bitsize))
810
if (test_flip_bit(&map,bitsize))
813
if (test_operators(&map,bitsize))
816
if (test_get_all_bits(&map, bitsize))
819
if (test_compare_operators(&map,bitsize))
822
if (test_count_bits_set(&map,bitsize))
825
if (test_get_first_bit(&map,bitsize))
828
if (test_get_next_bit(&map,bitsize))
830
if (test_prefix(&map,bitsize))
841
for (i= 1; i < 4096; i++)
843
printf("Start test for bitsize=%u\n",i);
854
will build the bitmap tests and ./test_bitmap will execute it