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"
29
void MyBitmap::createLastWordMask()
31
/* Get the number of used bits (1..8) in the last byte */
32
unsigned int const used= 1U + ((n_bits-1U) & 0x7U);
35
Create a mask with the upper 'unused' bits set and the lower 'used'
36
bits clear. The bits within each byte is stored in big-endian order.
38
unsigned char const mask= static_cast<unsigned char const>((~((1 << used) - 1)) & 255);
41
The first bytes are to be set to zero since they represent real bits
42
in the bitvector. The last bytes are set to 0xFF since they represent
43
bytes not used by the bitvector. Finally the last byte contains bits
44
as set by the mask above.
46
unsigned char *ptr= (unsigned char*)&last_word_mask;
48
last_word_ptr= bitmap + numOfWordsInMap()-1;
49
switch (numOfBytesInMap() & 3)
52
last_word_mask= UINT32_MAX;
56
last_word_mask= UINT32_MAX;
73
bool MyBitmap::init(my_bitmap_map *buf, uint32_t num_bits)
77
uint32_t size_in_bytes= bitmap_buffer_size(num_bits);
78
if (! (buf= new(nothrow) my_bitmap_map[size_in_bytes]()))
93
bool MyBitmap::testAndSet(const uint32_t bitPos)
95
unsigned char *value= ((unsigned char*) bitmap) + (bitPos / 8);
96
unsigned char bit= static_cast<unsigned char>(1 << ((bitPos) & 7));
97
unsigned char res= static_cast<unsigned char>((*value) & bit);
98
*value= static_cast<unsigned char>(*value | bit);
104
bool MyBitmap::testAndClear(const uint32_t bitPos)
106
unsigned char *byte= (unsigned char*) bitmap + (bitPos / 8);
107
unsigned char bit= static_cast<unsigned char>(1 << ((bitPos) & 7));
108
unsigned char res= static_cast<unsigned char>((*byte) & bit);
109
*byte= static_cast<unsigned char>(*byte & ~bit);
115
uint32_t MyBitmap::setNext()
119
if ((bit_found= getFirst()) != MY_BIT_NONE)
127
void MyBitmap::setPrefix(uint32_t prefix_size)
129
uint32_t prefix_bytes, prefix_bits, d;
130
unsigned char *m= (unsigned char *) bitmap;
133
(prefix_size <= n_bits || prefix_size == UINT32_MAX));
134
set_if_smaller(prefix_size, n_bits);
135
if ((prefix_bytes= prefix_size / 8))
137
memset(m, 0xff, prefix_bytes);
140
if ((prefix_bits= prefix_size & 7))
142
*m++= static_cast<unsigned char>((1 << prefix_bits)-1);
144
if ((d= numOfBytesInMap() - prefix_bytes))
151
bool MyBitmap::isPrefix(const uint32_t prefix_size) const
153
uint32_t prefix_bits= prefix_size & 0x7, res;
154
unsigned char *m= (unsigned char*) bitmap;
155
unsigned char *end_prefix= m + prefix_size/8;
157
assert(m && prefix_size <= n_bits);
158
end= m + numOfBytesInMap();
160
while (m < end_prefix)
168
*last_word_ptr&= ~last_word_mask; /*Clear bits*/
170
if (prefix_bits && *m++ != (1 << prefix_bits)-1)
188
bool MyBitmap::isSetAll() const
190
my_bitmap_map *data_ptr= bitmap;
191
my_bitmap_map *end= last_word_ptr;
192
*last_word_ptr |= last_word_mask;
193
for (; data_ptr <= end; data_ptr++)
195
if (*data_ptr != 0xFFFFFFFF)
204
bool MyBitmap::isClearAll() const
206
my_bitmap_map *data_ptr= bitmap;
208
if (*last_word_ptr & ~last_word_mask)
213
for (; data_ptr < end; data_ptr++)
223
/* Return true if map1 is a subset of map2 */
225
bool bitmap_is_subset(const MyBitmap *map1, const MyBitmap *map2)
227
my_bitmap_map *m1= map1->getBitmap(), *m2= map2->getBitmap(), *end;
229
assert(map1->getBitmap() && map2->getBitmap() &&
230
map1->numOfBitsInMap() == map2->numOfBitsInMap());
232
end= map1->getLastWordPtr();
233
map1->subtractMaskFromLastWord();
234
map2->subtractMaskFromLastWord();
237
if ((*m1++) & ~(*m2++))
245
/* True if bitmaps has any common bits */
247
bool bitmap_is_overlapping(const MyBitmap *map1, const MyBitmap *map2)
249
my_bitmap_map *m1= map1->getBitmap(), *m2= map2->getBitmap(), *end;
251
assert(map1->getBitmap() && map2->getBitmap() &&
252
map1->numOfBitsInMap() == map2->numOfBitsInMap());
254
end= map1->getLastWordPtr();
255
map1->subtractMaskFromLastWord();
256
map2->subtractMaskFromLastWord();
259
if ((*m1++) & (*m2++))
266
void bitmap_intersect(MyBitmap *map, const MyBitmap *map2)
268
my_bitmap_map *to= map->getBitmap(), *from= map2->getBitmap(), *end;
269
uint32_t len= map->numOfWordsInMap(), len2 = map2->numOfWordsInMap();
271
assert(map->getBitmap() && map2->getBitmap());
273
end= to+min(len,len2);
274
map2->subtractMaskFromLastWord(); /* Clear last bits in map2 */
291
void MyBitmap::setAbove(const uint32_t from_byte, const uint32_t use_bit)
293
unsigned char use_byte= static_cast<unsigned char>(use_bit ? 0xff : 0);
294
unsigned char *to= (unsigned char *) bitmap + from_byte;
295
unsigned char *end= (unsigned char *) bitmap + (n_bits+7)/8;
304
void bitmap_subtract(MyBitmap *map, const MyBitmap *map2)
306
my_bitmap_map *to= map->getBitmap(), *from= map2->getBitmap(), *end;
307
assert(map->getBitmap() && map2->getBitmap() &&
308
map->numOfBitsInMap() == map2->numOfBitsInMap());
310
end= map->getLastWordPtr();
319
void bitmap_union(MyBitmap *map, const MyBitmap *map2)
321
my_bitmap_map *to= map->getBitmap(), *from= map2->getBitmap(), *end;
323
assert(map->getBitmap() && map2->getBitmap() &&
324
map->numOfBitsInMap() == map2->numOfBitsInMap());
325
end= map->getLastWordPtr();
334
void bitmap_xor(MyBitmap *map, const MyBitmap *map2)
336
my_bitmap_map *to= map->getBitmap();
337
my_bitmap_map *from= map2->getBitmap();
338
my_bitmap_map *end= map->getLastWordPtr();
339
assert(map->getBitmap() && map2->getBitmap() &&
340
map->numOfBitsInMap() == map2->numOfBitsInMap());
348
void bitmap_invert(MyBitmap *map)
350
my_bitmap_map *to= map->getBitmap(), *end;
352
assert(map->getBitmap());
353
end= map->getLastWordPtr();
362
uint32_t MyBitmap::getBitsSet()
364
unsigned char *m= (unsigned char*) bitmap;
365
unsigned char *end= m + numOfBytesInMap();
369
*last_word_ptr&= ~last_word_mask; /*Reset last bits to zero*/
372
res+= internal::my_count_bits_uint16(*m++);
377
MyBitmap::MyBitmap(const MyBitmap& rhs)
379
my_bitmap_map *to= this->bitmap, *from= rhs.bitmap, *end;
381
if (this->bitmap && rhs.bitmap &&
382
this->n_bits == rhs.n_bits)
384
end= this->last_word_ptr;
392
this->n_bits= rhs.n_bits;
393
this->bitmap= rhs.bitmap;
397
MyBitmap& MyBitmap::operator=(const MyBitmap& rhs)
402
my_bitmap_map *to= this->bitmap, *from= rhs.bitmap, *end;
404
if (this->bitmap && rhs.bitmap &&
405
this->n_bits == rhs.n_bits)
407
end= this->last_word_ptr;
415
this->n_bits= rhs.n_bits;
416
this->bitmap= rhs.bitmap;
422
uint32_t MyBitmap::getFirstSet()
424
unsigned char *byte_ptr;
426
my_bitmap_map *data_ptr, *end= last_word_ptr;
430
*last_word_ptr &= ~last_word_mask;
432
for (i=0; data_ptr <= end; data_ptr++, i++)
436
byte_ptr= (unsigned char*)data_ptr;
437
for (j=0; ; j++, byte_ptr++)
443
if (*byte_ptr & (1 << k))
444
return (i*32) + (j*8) + k;
454
uint32_t MyBitmap::getFirst()
456
unsigned char *byte_ptr;
458
my_bitmap_map *data_ptr, *end= last_word_ptr;
462
*last_word_ptr|= last_word_mask;
464
for (i=0; data_ptr <= end; data_ptr++, i++)
466
if (*data_ptr != 0xFFFFFFFF)
468
byte_ptr= (unsigned char*)data_ptr;
469
for (j=0; ; j++, byte_ptr++)
471
if (*byte_ptr != 0xFF)
475
if (!(*byte_ptr & (1 << k)))
476
return (i*32) + (j*8) + k;
488
uint32_t get_rand_bit(uint32_t bitsize)
490
return (rand() % bitsize);
493
bool test_set_get_clear_bit(MyBitmap *map, uint32_t bitsize)
495
uint32_t i, test_bit;
496
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
497
for (i=0; i < no_loops; i++)
499
test_bit= get_rand_bit(bitsize);
500
map->setBit(test_bit);
501
if (! map->isBitSet(test_bit))
505
map->clearBit(test_bit);
506
if (map->isBitSet(test_bit))
513
printf("Error in set bit, bit %u, bitsize = %u", test_bit, bitsize);
516
printf("Error in clear bit, bit %u, bitsize = %u", test_bit, bitsize);
520
bool test_flip_bit(MyBitmap *map, uint32_t bitsize)
522
uint32_t i, test_bit;
523
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
524
for (i=0; i < no_loops; i++)
526
test_bit= get_rand_bit(bitsize);
527
map->flipBit(test_bit);
528
if (!map->isBitSet(test_bit))
530
map->flipBit(test_bit);
531
if (map->isBitSet(test_bit))
536
printf("Error in flip bit 1, bit %u, bitsize = %u", test_bit, bitsize);
539
printf("Error in flip bit 2, bit %u, bitsize = %u", test_bit, bitsize);
543
bool test_operators(MyBitmap *, uint32_t)
548
bool test_get_all_bits(MyBitmap *map, uint32_t bitsize)
552
if (!map->isSetAll())
554
if (!map->isPrefix(bitsize))
557
if (!map->isClearAll())
559
if (!map->isPrefix(0))
561
for (i=0; i<bitsize;i++)
563
if (!map->isSetAll())
565
for (i=0; i<bitsize;i++)
567
if (!map->isClearAll())
571
printf("Error in set_all, bitsize = %u", bitsize);
574
printf("Error in clear_all, bitsize = %u", bitsize);
577
printf("Error in bitmap_is_set_all, bitsize = %u", bitsize);
580
printf("Error in bitmap_is_clear_all, bitsize = %u", bitsize);
583
printf("Error in set_all through set_prefix, bitsize = %u", bitsize);
586
printf("Error in clear_all through set_prefix, bitsize = %u", bitsize);
590
bool test_compare_operators(MyBitmap *map, uint32_t bitsize)
592
uint32_t i, j, test_bit1, test_bit2, test_bit3,test_bit4;
593
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
594
MyBitmap map2_obj, map3_obj;
595
MyBitmap *map2= &map2_obj, *map3= &map3_obj;
596
my_bitmap_map map2buf[1024];
597
my_bitmap_map map3buf[1024];
598
map2_obj.init(map2buf, bitsize);
599
map3_obj.init(map3buf, bitsize);
602
for (i=0; i < no_loops; i++)
604
test_bit1=get_rand_bit(bitsize);
605
map->setPrefix(test_bit1);
606
test_bit2=get_rand_bit(bitsize);
607
map2->setPrefix(test_bit2);
608
bitmap_intersect(map, map2);
609
test_bit3= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
610
map3->setPrefix(test_bit3);
611
if (!bitmap_cmp(map, map3))
616
test_bit1=get_rand_bit(bitsize);
617
test_bit2=get_rand_bit(bitsize);
618
test_bit3=get_rand_bit(bitsize);
619
map->setPrefix(test_bit1);
620
map2->setPrefix(test_bit2);
621
test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
622
map3->setPrefix(test_bit3);
623
bitmap_union(map, map2);
624
if (!bitmap_cmp(map, map3))
629
test_bit1=get_rand_bit(bitsize);
630
test_bit2=get_rand_bit(bitsize);
631
test_bit3=get_rand_bit(bitsize);
632
map->setPrefix(test_bit1);
633
map2->setPrefix(test_bit2);
634
bitmap_xor(map, map2);
635
test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
636
test_bit4= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
637
map3->setPrefix(test_bit3);
638
for (j=0; j < test_bit4; j++)
640
if (!bitmap_cmp(map, map3))
645
test_bit1=get_rand_bit(bitsize);
646
test_bit2=get_rand_bit(bitsize);
647
test_bit3=get_rand_bit(bitsize);
648
map->setPrefix(test_bit1);
649
map2->setPrefix(test_bit2);
650
bitmap_subtract(map, map2);
651
if (test_bit2 < test_bit1)
653
map3->setPrefix(test_bit1);
654
for (j=0; j < test_bit2; j++)
657
if (!bitmap_cmp(map, map3))
662
test_bit1=get_rand_bit(bitsize);
663
map->setPrefix(test_bit1);
666
for (j=0; j < test_bit1; j++)
668
if (!bitmap_cmp(map, map3))
675
printf("intersect error bitsize=%u,size1=%u,size2=%u", bitsize,
676
test_bit1,test_bit2);
679
printf("union error bitsize=%u,size1=%u,size2=%u", bitsize,
680
test_bit1,test_bit2);
683
printf("xor error bitsize=%u,size1=%u,size2=%u", bitsize,
684
test_bit1,test_bit2);
687
printf("subtract error bitsize=%u,size1=%u,size2=%u", bitsize,
688
test_bit1,test_bit2);
691
printf("invert error bitsize=%u,size=%u", bitsize,
696
bool test_count_bits_set(MyBitmap *map, uint32_t bitsize)
698
uint32_t i, bit_count=0, test_bit;
699
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
700
for (i=0; i < no_loops; i++)
702
test_bit=get_rand_bit(bitsize);
703
if (!map->isBitSet(test_bit))
705
map->setBit(test_bit);
709
if (bit_count==0 && bitsize > 0)
711
if (getBitsSet() != bit_count)
715
printf("No bits set bitsize = %u", bitsize);
718
printf("Wrong count of bits set, bitsize = %u", bitsize);
722
bool test_get_first_bit(MyBitmap *map, uint32_t bitsize)
724
uint32_t i, test_bit;
725
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
726
for (i=0; i < no_loops; i++)
728
test_bit=get_rand_bit(bitsize);
729
map->setBit(test_bit);
730
if (bitmap_get_first_set(map) != test_bit)
733
map->clearBit(test_bit);
734
if (getFirst() != test_bit)
740
printf("get_first_set error bitsize=%u,prefix_size=%u",bitsize,test_bit);
743
printf("get_first error bitsize= %u, prefix_size= %u",bitsize,test_bit);
747
bool test_get_next_bit(MyBitmap *map, uint32_t bitsize)
749
uint32_t i, j, test_bit;
750
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
751
for (i=0; i < no_loops; i++)
753
test_bit=get_rand_bit(bitsize);
754
for (j=0; j < test_bit; j++)
756
if (!map->isPrefix(test_bit))
762
printf("get_next error bitsize= %u, prefix_size= %u", bitsize,test_bit);
766
bool test_prefix(MyBitmap *map, uint32_t bitsize)
768
uint32_t i, j, test_bit;
769
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
770
for (i=0; i < no_loops; i++)
772
test_bit=get_rand_bit(bitsize);
773
map->setPrefix(map, test_bit);
774
if (!map->isPrefix(test_bit))
777
for (j=0; j < test_bit; j++)
779
if (!map->isPrefix(test_bit))
782
for (j=bitsize - 1; ~(j-test_bit); j--)
784
if (!map->isPrefix(test_bit))
790
printf("prefix1 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
793
printf("prefix2 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
796
printf("prefix3 error bitsize = %u, prefix_size = %u", bitsize,test_bit);
801
bool do_test(uint32_t bitsize)
804
my_bitmap_map buf[1024];
805
if (map.init(buf, bitsize))
807
printf("init error for bitsize %d", bitsize);
810
if (test_set_get_clear_bit(&map,bitsize))
813
if (test_flip_bit(&map,bitsize))
816
if (test_operators(&map,bitsize))
819
if (test_get_all_bits(&map, bitsize))
822
if (test_compare_operators(&map,bitsize))
825
if (test_count_bits_set(&map,bitsize))
828
if (test_get_first_bit(&map,bitsize))
831
if (test_get_next_bit(&map,bitsize))
833
if (test_prefix(&map,bitsize))
844
for (i= 1; i < 4096; i++)
846
printf("Start test for bitsize=%u\n",i);
857
will build the bitmap tests and ./test_bitmap will execute it
863
} /* namespace drizzled */