13
13
along with this program; if not, write to the Free Software
14
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
16
#include "mysys_priv.h"
33
17
#include <mysys/my_bitmap.h>
34
18
#include <mystrings/m_string.h>
35
19
#include <mysys/my_bit.h>
39
21
using namespace std;
41
void create_last_word_mask(MY_BITMAP *map)
23
void MyBitmap::createLastWordMask()
43
25
/* Get the number of used bits (1..8) in the last byte */
44
unsigned int const used= 1U + ((map->n_bits-1U) & 0x7U);
26
unsigned int const used= 1U + ((n_bits-1U) & 0x7U);
47
29
Create a mask with the upper 'unused' bits set and the lower 'used'
55
37
bytes not used by the bitvector. Finally the last byte contains bits
56
38
as set by the mask above.
58
unsigned char *ptr= (unsigned char*)&map->last_word_mask;
40
unsigned char *ptr= (unsigned char*)&last_word_mask;
60
map->last_word_ptr= map->bitmap + no_words_in_map(map)-1;
61
switch (no_bytes_in_map(map) & 3) {
42
last_word_ptr= bitmap + numOfWordsInMap()-1;
43
switch (numOfBytesInMap() & 3)
63
map->last_word_mask= UINT32_MAX;
46
last_word_mask= UINT32_MAX;
67
map->last_word_mask= UINT32_MAX;
50
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);
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= 1 << ((bitPos) & 7);
130
91
unsigned char res= (*value) & bit;
161
uint32_t bitmap_set_next(MY_BITMAP *map)
109
uint32_t MyBitmap::setNext()
163
111
uint32_t bit_found;
165
if ((bit_found= bitmap_get_first(map)) != MY_BIT_NONE)
166
bitmap_set_bit(map, bit_found);
113
if ((bit_found= getFirst()) != MY_BIT_NONE)
167
117
return bit_found;
171
void bitmap_set_prefix(MY_BITMAP *map, uint32_t prefix_size)
121
void MyBitmap::setPrefix(uint32_t prefix_size)
173
123
uint32_t prefix_bytes, prefix_bits, d;
174
unsigned char *m= (unsigned char *)map->bitmap;
124
unsigned char *m= (unsigned char *) bitmap;
176
assert(map->bitmap &&
177
(prefix_size <= map->n_bits || prefix_size == UINT32_MAX));
178
set_if_smaller(prefix_size, map->n_bits);
127
(prefix_size <= n_bits || prefix_size == UINT32_MAX));
128
set_if_smaller(prefix_size, n_bits);
179
129
if ((prefix_bytes= prefix_size / 8))
180
131
memset(m, 0xff, prefix_bytes);
181
133
m+= prefix_bytes;
182
134
if ((prefix_bits= prefix_size & 7))
183
136
*m++= (1 << prefix_bits)-1;
184
if ((d= no_bytes_in_map(map)-prefix_bytes))
138
if ((d= numOfBytesInMap() - prefix_bytes))
189
bool bitmap_is_prefix(const MY_BITMAP *map, uint32_t prefix_size)
145
bool MyBitmap::isPrefix(const uint32_t prefix_size) const
191
147
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;
148
unsigned char *m= (unsigned char*) bitmap;
149
unsigned char *end_prefix= m + prefix_size/8;
194
150
unsigned char *end;
195
assert(m && prefix_size <= map->n_bits);
196
end= m+no_bytes_in_map(map);
151
assert(m && prefix_size <= n_bits);
152
end= m + numOfBytesInMap();
198
154
while (m < end_prefix)
199
156
if (*m++ != 0xff)
202
*map->last_word_ptr&= ~map->last_word_mask; /*Clear bits*/
162
*last_word_ptr&= ~last_word_mask; /*Clear bits*/
204
164
if (prefix_bits && *m++ != (1 << prefix_bits)-1)
216
bool bitmap_is_set_all(const MY_BITMAP *map)
182
bool MyBitmap::isSetAll() const
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;
184
my_bitmap_map *data_ptr= bitmap;
185
my_bitmap_map *end= last_word_ptr;
186
*last_word_ptr |= last_word_mask;
221
187
for (; data_ptr <= end; data_ptr++)
222
189
if (*data_ptr != 0xFFFFFFFF)
228
bool bitmap_is_clear_all(const MY_BITMAP *map)
198
bool MyBitmap::isClearAll() const
230
my_bitmap_map *data_ptr= map->bitmap;
200
my_bitmap_map *data_ptr= bitmap;
231
201
my_bitmap_map *end;
232
if (*map->last_word_ptr & ~map->last_word_mask)
202
if (*last_word_ptr & ~last_word_mask)
234
end= map->last_word_ptr;
235
207
for (; data_ptr < end; data_ptr++)
241
217
/* Return true if map1 is a subset of map2 */
243
bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2)
219
bool bitmap_is_subset(const MyBitmap *map1, const MyBitmap *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;
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();
253
229
while (m1 <= end)
255
231
if ((*m1++) & ~(*m2++))
261
239
/* True if bitmaps has any common bits */
263
bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2)
241
bool bitmap_is_overlapping(const MyBitmap *map1, const MyBitmap *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;
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();
273
251
while (m1 <= end)
275
253
if ((*m1++) & (*m2++))
282
void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
260
void bitmap_intersect(MyBitmap *map, const MyBitmap *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);
262
my_bitmap_map *to= map->getBitmap(), *from= map2->getBitmap(), *end;
263
uint32_t len= map->numOfWordsInMap(), len2 = map2->numOfWordsInMap();
287
assert(map->bitmap && map2->bitmap);
265
assert(map->getBitmap() && map2->getBitmap());
289
267
end= to+min(len,len2);
290
*map2->last_word_ptr&= ~map2->last_word_mask; /*Clear last bits in map2*/
268
map2->subtractMaskFromLastWord(); /* Clear last bits in map2 */
292
271
*to++ &= *from++;
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)
285
void MyBitmap::setAbove(const uint32_t from_byte, const uint32_t use_bit)
325
287
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;
288
unsigned char *to= (unsigned char *) bitmap + from_byte;
289
unsigned char *end= (unsigned char *) bitmap + (n_bits+7)/8;
334
void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
298
void bitmap_subtract(MyBitmap *map, const MyBitmap *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);
300
my_bitmap_map *to= map->getBitmap(), *from= map2->getBitmap(), *end;
301
assert(map->getBitmap() && map2->getBitmap() &&
302
map->numOfBitsInMap() == map2->numOfBitsInMap());
340
end= map->last_word_ptr;
304
end= map->getLastWordPtr();
342
306
while (to <= end)
343
308
*to++ &= ~(*from++);
347
void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
313
void bitmap_union(MyBitmap *map, const MyBitmap *map2)
349
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
315
my_bitmap_map *to= map->getBitmap(), *from= map2->getBitmap(), *end;
351
assert(map->bitmap && map2->bitmap &&
352
map->n_bits==map2->n_bits);
353
end= map->last_word_ptr;
317
assert(map->getBitmap() && map2->getBitmap() &&
318
map->numOfBitsInMap() == map2->numOfBitsInMap());
319
end= map->getLastWordPtr();
355
321
while (to <= end)
356
323
*to++ |= *from++;
360
void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2)
328
void bitmap_xor(MyBitmap *map, const MyBitmap *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);
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());
365
335
while (to <= end)
366
337
*to++ ^= *from++;
370
void bitmap_invert(MY_BITMAP *map)
342
void bitmap_invert(MyBitmap *map)
372
my_bitmap_map *to= map->bitmap, *end;
344
my_bitmap_map *to= map->getBitmap(), *end;
375
end= map->last_word_ptr;
346
assert(map->getBitmap());
347
end= map->getLastWordPtr();
377
349
while (to <= end)
378
351
*to++ ^= 0xFFFFFFFF;
382
uint32_t bitmap_bits_set(const MY_BITMAP *map)
356
uint32_t MyBitmap::getBitsSet()
384
unsigned char *m= (unsigned char*)map->bitmap;
385
unsigned char *end= m + no_bytes_in_map(map);
358
unsigned char *m= (unsigned char*) bitmap;
359
unsigned char *end= m + numOfBytesInMap();
389
*map->last_word_ptr&= ~map->last_word_mask; /*Reset last bits to zero*/
363
*last_word_ptr&= ~last_word_mask; /*Reset last bits to zero*/
391
366
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)
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()
410
418
unsigned char *byte_ptr;
412
my_bitmap_map *data_ptr, *end= map->last_word_ptr;
420
my_bitmap_map *data_ptr, *end= last_word_ptr;
415
data_ptr= map->bitmap;
416
*map->last_word_ptr &= ~map->last_word_mask;
424
*last_word_ptr &= ~last_word_mask;
418
426
for (i=0; data_ptr <= end; data_ptr++, i++)
572
bool test_compare_operators(MY_BITMAP *map, uint32_t bitsize)
584
bool test_compare_operators(MyBitmap *map, uint32_t bitsize)
574
586
uint32_t i, j, test_bit1, test_bit2, test_bit3,test_bit4;
575
587
uint32_t no_loops= bitsize > 128 ? 128 : bitsize;
576
MY_BITMAP map2_obj, map3_obj;
577
MY_BITMAP *map2= &map2_obj, *map3= &map3_obj;
588
MyBitmap map2_obj, map3_obj;
589
MyBitmap *map2= &map2_obj, *map3= &map3_obj;
578
590
my_bitmap_map map2buf[1024];
579
591
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);
592
map2_obj.init(map2buf, bitsize);
593
map3_obj.init(map3buf, bitsize);
584
596
for (i=0; i < no_loops; i++)
586
598
test_bit1=get_rand_bit(bitsize);
587
bitmap_set_prefix(map, test_bit1);
599
map->setPrefix(test_bit1);
588
600
test_bit2=get_rand_bit(bitsize);
589
bitmap_set_prefix(map2, test_bit2);
601
map2->setPrefix(test_bit2);
590
602
bitmap_intersect(map, map2);
591
603
test_bit3= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
592
bitmap_set_prefix(map3, test_bit3);
604
map3->setPrefix(test_bit3);
593
605
if (!bitmap_cmp(map, map3))
595
bitmap_clear_all(map);
596
bitmap_clear_all(map2);
597
bitmap_clear_all(map3);
598
610
test_bit1=get_rand_bit(bitsize);
599
611
test_bit2=get_rand_bit(bitsize);
600
612
test_bit3=get_rand_bit(bitsize);
601
bitmap_set_prefix(map, test_bit1);
602
bitmap_set_prefix(map2, test_bit2);
613
map->setPrefix(test_bit1);
614
map2->setPrefix(test_bit2);
603
615
test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
604
bitmap_set_prefix(map3, test_bit3);
616
map3->setPrefix(test_bit3);
605
617
bitmap_union(map, map2);
606
618
if (!bitmap_cmp(map, map3))
608
bitmap_clear_all(map);
609
bitmap_clear_all(map2);
610
bitmap_clear_all(map3);
611
623
test_bit1=get_rand_bit(bitsize);
612
624
test_bit2=get_rand_bit(bitsize);
613
625
test_bit3=get_rand_bit(bitsize);
614
bitmap_set_prefix(map, test_bit1);
615
bitmap_set_prefix(map2, test_bit2);
626
map->setPrefix(test_bit1);
627
map2->setPrefix(test_bit2);
616
628
bitmap_xor(map, map2);
617
629
test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1;
618
630
test_bit4= test_bit2 < test_bit1 ? test_bit2 : test_bit1;
619
bitmap_set_prefix(map3, test_bit3);
631
map3->setPrefix(test_bit3);
620
632
for (j=0; j < test_bit4; j++)
621
bitmap_clear_bit(map3, j);
622
634
if (!bitmap_cmp(map, map3))
624
bitmap_clear_all(map);
625
bitmap_clear_all(map2);
626
bitmap_clear_all(map3);
627
639
test_bit1=get_rand_bit(bitsize);
628
640
test_bit2=get_rand_bit(bitsize);
629
641
test_bit3=get_rand_bit(bitsize);
630
bitmap_set_prefix(map, test_bit1);
631
bitmap_set_prefix(map2, test_bit2);
642
map->setPrefix(test_bit1);
643
map2->setPrefix(test_bit2);
632
644
bitmap_subtract(map, map2);
633
645
if (test_bit2 < test_bit1)
635
bitmap_set_prefix(map3, test_bit1);
647
map3->setPrefix(test_bit1);
636
648
for (j=0; j < test_bit2; j++)
637
bitmap_clear_bit(map3, j);
639
651
if (!bitmap_cmp(map, map3))
641
bitmap_clear_all(map);
642
bitmap_clear_all(map2);
643
bitmap_clear_all(map3);
644
656
test_bit1=get_rand_bit(bitsize);
645
bitmap_set_prefix(map, test_bit1);
657
map->setPrefix(test_bit1);
646
658
bitmap_invert(map);
647
bitmap_set_all(map3);
648
660
for (j=0; j < test_bit1; j++)
649
bitmap_clear_bit(map3, j);
650
662
if (!bitmap_cmp(map, map3))
652
bitmap_clear_all(map);
653
bitmap_clear_all(map3);