00001 /* Copyright (C) 2000 MySQL AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 /* 00018 Handling of uchar arrays as large bitmaps. 00019 00020 API limitations (or, rather asserted safety assumptions, 00021 to encourage correct programming) 00022 00023 * the internal size is a set of 32 bit words 00024 * the number of bits specified in creation can be any number > 0 00025 * there are THREAD safe versions of most calls called bitmap_lock_* 00026 many of those are not used and not compiled normally but the code 00027 already exist for them in an #ifdef:ed part. These can only be used 00028 if THREAD was specified in bitmap_init 00029 00030 TODO: 00031 Make assembler THREAD safe versions of these using test-and-set instructions 00032 00033 Original version created by Sergei Golubchik 2001 - 2004. 00034 New version written and test program added and some changes to the interface 00035 was made by Mikael Ronström 2005, with assistance of Tomas Ulin and Mats 00036 Kindahl. 00037 */ 00038 00039 #include "mysys_priv.h" 00040 #include <my_bitmap.h> 00041 #include <m_string.h> 00042 00043 void create_last_word_mask(MY_BITMAP *map) 00044 { 00045 /* Get the number of used bits (1..8) in the last byte */ 00046 unsigned int const used= 1U + ((map->n_bits-1U) & 0x7U); 00047 00048 /* 00049 Create a mask with the upper 'unused' bits set and the lower 'used' 00050 bits clear. The bits within each byte is stored in big-endian order. 00051 */ 00052 unsigned char const mask= (~((1 << used) - 1)) & 255; 00053 00054 /* 00055 The first bytes are to be set to zero since they represent real bits 00056 in the bitvector. The last bytes are set to 0xFF since they represent 00057 bytes not used by the bitvector. Finally the last byte contains bits 00058 as set by the mask above. 00059 */ 00060 unsigned char *ptr= (unsigned char*)&map->last_word_mask; 00061 00062 map->last_word_ptr= map->bitmap + no_words_in_map(map)-1; 00063 switch (no_bytes_in_map(map) & 3) { 00064 case 1: 00065 map->last_word_mask= ~0U; 00066 ptr[0]= mask; 00067 return; 00068 case 2: 00069 map->last_word_mask= ~0U; 00070 ptr[0]= 0; 00071 ptr[1]= mask; 00072 return; 00073 case 3: 00074 map->last_word_mask= 0U; 00075 ptr[2]= mask; 00076 ptr[3]= 0xFFU; 00077 return; 00078 case 0: 00079 map->last_word_mask= 0U; 00080 ptr[3]= mask; 00081 return; 00082 } 00083 } 00084 00085 00086 static inline void bitmap_lock(MY_BITMAP *map __attribute__((unused))) 00087 { 00088 #ifdef THREAD 00089 if (map->mutex) 00090 pthread_mutex_lock(map->mutex); 00091 #endif 00092 } 00093 00094 static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused))) 00095 { 00096 #ifdef THREAD 00097 if (map->mutex) 00098 pthread_mutex_unlock(map->mutex); 00099 #endif 00100 } 00101 00102 00103 my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, 00104 my_bool thread_safe __attribute__((unused))) 00105 { 00106 DBUG_ENTER("bitmap_init"); 00107 if (!buf) 00108 { 00109 uint size_in_bytes= bitmap_buffer_size(n_bits); 00110 uint extra= 0; 00111 #ifdef THREAD 00112 if (thread_safe) 00113 { 00114 size_in_bytes= ALIGN_SIZE(size_in_bytes); 00115 extra= sizeof(pthread_mutex_t); 00116 } 00117 map->mutex= 0; 00118 #endif 00119 if (!(buf= (my_bitmap_map*) my_malloc(size_in_bytes+extra, MYF(MY_WME)))) 00120 DBUG_RETURN(1); 00121 #ifdef THREAD 00122 if (thread_safe) 00123 { 00124 map->mutex= (pthread_mutex_t *) ((char*) buf + size_in_bytes); 00125 pthread_mutex_init(map->mutex, MY_MUTEX_INIT_FAST); 00126 } 00127 #endif 00128 } 00129 #ifdef THREAD 00130 else 00131 { 00132 DBUG_ASSERT(thread_safe == 0); 00133 } 00134 #endif 00135 00136 map->bitmap= buf; 00137 map->n_bits= n_bits; 00138 create_last_word_mask(map); 00139 bitmap_clear_all(map); 00140 DBUG_RETURN(0); 00141 } 00142 00143 00144 void bitmap_free(MY_BITMAP *map) 00145 { 00146 DBUG_ENTER("bitmap_free"); 00147 if (map->bitmap) 00148 { 00149 #ifdef THREAD 00150 if (map->mutex) 00151 pthread_mutex_destroy(map->mutex); 00152 #endif 00153 my_free((char*) map->bitmap, MYF(0)); 00154 map->bitmap=0; 00155 } 00156 DBUG_VOID_RETURN; 00157 } 00158 00159 00160 /* 00161 test if bit already set and set it if it was not (thread unsafe method) 00162 00163 SYNOPSIS 00164 bitmap_fast_test_and_set() 00165 MAP bit map struct 00166 BIT bit number 00167 00168 RETURN 00169 0 bit was not set 00170 !=0 bit was set 00171 */ 00172 00173 my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) 00174 { 00175 uchar *byte= (uchar*)map->bitmap + (bitmap_bit / 8); 00176 uchar bit= 1 << ((bitmap_bit) & 7); 00177 uchar res= (*byte) & bit; 00178 *byte|= bit; 00179 return res; 00180 } 00181 00182 00183 /* 00184 test if bit already set and set it if it was not (thread safe method) 00185 00186 SYNOPSIS 00187 bitmap_fast_test_and_set() 00188 map bit map struct 00189 bitmap_bit bit number 00190 00191 RETURN 00192 0 bit was not set 00193 !=0 bit was set 00194 */ 00195 00196 my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit) 00197 { 00198 my_bool res; 00199 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); 00200 bitmap_lock(map); 00201 res= bitmap_fast_test_and_set(map, bitmap_bit); 00202 bitmap_unlock(map); 00203 return res; 00204 } 00205 00206 /* 00207 test if bit already set and clear it if it was set(thread unsafe method) 00208 00209 SYNOPSIS 00210 bitmap_fast_test_and_set() 00211 MAP bit map struct 00212 BIT bit number 00213 00214 RETURN 00215 0 bit was not set 00216 !=0 bit was set 00217 */ 00218 00219 my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit) 00220 { 00221 uchar *byte= (uchar*) map->bitmap + (bitmap_bit / 8); 00222 uchar bit= 1 << ((bitmap_bit) & 7); 00223 uchar res= (*byte) & bit; 00224 *byte&= ~bit; 00225 return res; 00226 } 00227 00228 00229 my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit) 00230 { 00231 my_bool res; 00232 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); 00233 bitmap_lock(map); 00234 res= bitmap_fast_test_and_clear(map, bitmap_bit); 00235 bitmap_unlock(map); 00236 return res; 00237 } 00238 00239 00240 uint bitmap_set_next(MY_BITMAP *map) 00241 { 00242 uint bit_found; 00243 DBUG_ASSERT(map->bitmap); 00244 if ((bit_found= bitmap_get_first(map)) != MY_BIT_NONE) 00245 bitmap_set_bit(map, bit_found); 00246 return bit_found; 00247 } 00248 00249 00250 void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) 00251 { 00252 uint prefix_bytes, prefix_bits, d; 00253 uchar *m= (uchar *)map->bitmap; 00254 00255 DBUG_ASSERT(map->bitmap && 00256 (prefix_size <= map->n_bits || prefix_size == (uint) ~0)); 00257 set_if_smaller(prefix_size, map->n_bits); 00258 if ((prefix_bytes= prefix_size / 8)) 00259 memset(m, 0xff, prefix_bytes); 00260 m+= prefix_bytes; 00261 if ((prefix_bits= prefix_size & 7)) 00262 *m++= (1 << prefix_bits)-1; 00263 if ((d= no_bytes_in_map(map)-prefix_bytes)) 00264 bzero(m, d); 00265 } 00266 00267 00268 my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) 00269 { 00270 uint prefix_bits= prefix_size & 0x7, res; 00271 uchar *m= (uchar*)map->bitmap; 00272 uchar *end_prefix= m+prefix_size/8; 00273 uchar *end; 00274 DBUG_ASSERT(m && prefix_size <= map->n_bits); 00275 end= m+no_bytes_in_map(map); 00276 00277 while (m < end_prefix) 00278 if (*m++ != 0xff) 00279 return 0; 00280 00281 *map->last_word_ptr&= ~map->last_word_mask; /*Clear bits*/ 00282 res= 0; 00283 if (prefix_bits && *m++ != (1 << prefix_bits)-1) 00284 goto ret; 00285 00286 while (m < end) 00287 if (*m++ != 0) 00288 goto ret; 00289 res= 1; 00290 ret: 00291 return res; 00292 } 00293 00294 00295 my_bool bitmap_is_set_all(const MY_BITMAP *map) 00296 { 00297 my_bitmap_map *data_ptr= map->bitmap; 00298 my_bitmap_map *end= map->last_word_ptr; 00299 *map->last_word_ptr |= map->last_word_mask; 00300 for (; data_ptr <= end; data_ptr++) 00301 if (*data_ptr != 0xFFFFFFFF) 00302 return FALSE; 00303 return TRUE; 00304 } 00305 00306 00307 my_bool bitmap_is_clear_all(const MY_BITMAP *map) 00308 { 00309 my_bitmap_map *data_ptr= map->bitmap; 00310 my_bitmap_map *end; 00311 if (*map->last_word_ptr & ~map->last_word_mask) 00312 return FALSE; 00313 end= map->last_word_ptr; 00314 for (; data_ptr < end; data_ptr++) 00315 if (*data_ptr) 00316 return FALSE; 00317 return TRUE; 00318 } 00319 00320 /* Return TRUE if map1 is a subset of map2 */ 00321 00322 my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) 00323 { 00324 my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; 00325 00326 DBUG_ASSERT(map1->bitmap && map2->bitmap && 00327 map1->n_bits==map2->n_bits); 00328 00329 end= map1->last_word_ptr; 00330 *map1->last_word_ptr &= ~map1->last_word_mask; 00331 *map2->last_word_ptr &= ~map2->last_word_mask; 00332 while (m1 <= end) 00333 { 00334 if ((*m1++) & ~(*m2++)) 00335 return 0; 00336 } 00337 return 1; 00338 } 00339 00340 /* True if bitmaps has any common bits */ 00341 00342 my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2) 00343 { 00344 my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end; 00345 00346 DBUG_ASSERT(map1->bitmap && map2->bitmap && 00347 map1->n_bits==map2->n_bits); 00348 00349 end= map1->last_word_ptr; 00350 *map1->last_word_ptr &= ~map1->last_word_mask; 00351 *map2->last_word_ptr &= ~map2->last_word_mask; 00352 while (m1 <= end) 00353 { 00354 if ((*m1++) & (*m2++)) 00355 return 1; 00356 } 00357 return 0; 00358 } 00359 00360 00361 void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2) 00362 { 00363 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; 00364 uint len= no_words_in_map(map), len2 = no_words_in_map(map2); 00365 00366 DBUG_ASSERT(map->bitmap && map2->bitmap); 00367 00368 end= to+min(len,len2); 00369 *map2->last_word_ptr&= ~map2->last_word_mask; /*Clear last bits in map2*/ 00370 while (to < end) 00371 *to++ &= *from++; 00372 00373 if (len2 < len) 00374 { 00375 end+=len-len2; 00376 while (to < end) 00377 *to++=0; 00378 } 00379 } 00380 00381 00382 /* 00383 Set/clear all bits above a bit. 00384 00385 SYNOPSIS 00386 bitmap_set_above() 00387 map RETURN The bitmap to change. 00388 from_byte The bitmap buffer byte offset to start with. 00389 use_bit The bit value (1/0) to use for all upper bits. 00390 00391 NOTE 00392 You can only set/clear full bytes. 00393 The function is meant for the situation that you copy a smaller bitmap 00394 to a bigger bitmap. Bitmap lengths are always multiple of eigth (the 00395 size of a byte). Using 'from_byte' saves multiplication and division 00396 by eight during parameter passing. 00397 00398 RETURN 00399 void 00400 */ 00401 00402 void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit) 00403 { 00404 uchar use_byte= use_bit ? 0xff : 0; 00405 uchar *to= (uchar *)map->bitmap + from_byte; 00406 uchar *end= (uchar *)map->bitmap + (map->n_bits+7)/8; 00407 00408 while (to < end) 00409 *to++= use_byte; 00410 } 00411 00412 00413 void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2) 00414 { 00415 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; 00416 DBUG_ASSERT(map->bitmap && map2->bitmap && 00417 map->n_bits==map2->n_bits); 00418 00419 end= map->last_word_ptr; 00420 00421 while (to <= end) 00422 *to++ &= ~(*from++); 00423 } 00424 00425 00426 void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) 00427 { 00428 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; 00429 00430 DBUG_ASSERT(map->bitmap && map2->bitmap && 00431 map->n_bits==map2->n_bits); 00432 end= map->last_word_ptr; 00433 00434 while (to <= end) 00435 *to++ |= *from++; 00436 } 00437 00438 00439 void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2) 00440 { 00441 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr; 00442 DBUG_ASSERT(map->bitmap && map2->bitmap && 00443 map->n_bits==map2->n_bits); 00444 while (to <= end) 00445 *to++ ^= *from++; 00446 } 00447 00448 00449 void bitmap_invert(MY_BITMAP *map) 00450 { 00451 my_bitmap_map *to= map->bitmap, *end; 00452 00453 DBUG_ASSERT(map->bitmap); 00454 end= map->last_word_ptr; 00455 00456 while (to <= end) 00457 *to++ ^= 0xFFFFFFFF; 00458 } 00459 00460 00461 uint bitmap_bits_set(const MY_BITMAP *map) 00462 { 00463 uchar *m= (uchar*)map->bitmap; 00464 uchar *end= m + no_bytes_in_map(map); 00465 uint res= 0; 00466 00467 DBUG_ASSERT(map->bitmap); 00468 *map->last_word_ptr&= ~map->last_word_mask; /*Reset last bits to zero*/ 00469 while (m < end) 00470 res+= my_count_bits_ushort(*m++); 00471 return res; 00472 } 00473 00474 00475 void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2) 00476 { 00477 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; 00478 00479 DBUG_ASSERT(map->bitmap && map2->bitmap && 00480 map->n_bits==map2->n_bits); 00481 end= map->last_word_ptr; 00482 while (to <= end) 00483 *to++ = *from++; 00484 } 00485 00486 00487 uint bitmap_get_first_set(const MY_BITMAP *map) 00488 { 00489 uchar *byte_ptr; 00490 uint i,j,k; 00491 my_bitmap_map *data_ptr, *end= map->last_word_ptr; 00492 00493 DBUG_ASSERT(map->bitmap); 00494 data_ptr= map->bitmap; 00495 *map->last_word_ptr &= ~map->last_word_mask; 00496 00497 for (i=0; data_ptr <= end; data_ptr++, i++) 00498 { 00499 if (*data_ptr) 00500 { 00501 byte_ptr= (uchar*)data_ptr; 00502 for (j=0; ; j++, byte_ptr++) 00503 { 00504 if (*byte_ptr) 00505 { 00506 for (k=0; ; k++) 00507 { 00508 if (*byte_ptr & (1 << k)) 00509 return (i*32) + (j*8) + k; 00510 } 00511 DBUG_ASSERT(0); 00512 } 00513 } 00514 DBUG_ASSERT(0); 00515 } 00516 } 00517 return MY_BIT_NONE; 00518 } 00519 00520 00521 uint bitmap_get_first(const MY_BITMAP *map) 00522 { 00523 uchar *byte_ptr; 00524 uint i,j,k; 00525 my_bitmap_map *data_ptr, *end= map->last_word_ptr; 00526 00527 DBUG_ASSERT(map->bitmap); 00528 data_ptr= map->bitmap; 00529 *map->last_word_ptr|= map->last_word_mask; 00530 00531 for (i=0; data_ptr <= end; data_ptr++, i++) 00532 { 00533 if (*data_ptr != 0xFFFFFFFF) 00534 { 00535 byte_ptr= (uchar*)data_ptr; 00536 for (j=0; ; j++, byte_ptr++) 00537 { 00538 if (*byte_ptr != 0xFF) 00539 { 00540 for (k=0; ; k++) 00541 { 00542 if (!(*byte_ptr & (1 << k))) 00543 return (i*32) + (j*8) + k; 00544 } 00545 DBUG_ASSERT(0); 00546 } 00547 } 00548 DBUG_ASSERT(0); 00549 } 00550 } 00551 return MY_BIT_NONE; 00552 } 00553 00554 00555 uint bitmap_lock_set_next(MY_BITMAP *map) 00556 { 00557 uint bit_found; 00558 bitmap_lock(map); 00559 bit_found= bitmap_set_next(map); 00560 bitmap_unlock(map); 00561 return bit_found; 00562 } 00563 00564 00565 void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit) 00566 { 00567 bitmap_lock(map); 00568 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); 00569 bitmap_clear_bit(map, bitmap_bit); 00570 bitmap_unlock(map); 00571 } 00572 00573 00574 #ifdef NOT_USED 00575 my_bool bitmap_lock_is_prefix(const MY_BITMAP *map, uint prefix_size) 00576 { 00577 my_bool res; 00578 bitmap_lock((MY_BITMAP *)map); 00579 res= bitmap_is_prefix(map, prefix_size); 00580 bitmap_unlock((MY_BITMAP *)map); 00581 return res; 00582 } 00583 00584 00585 void bitmap_lock_set_all(MY_BITMAP *map) 00586 { 00587 bitmap_lock(map); 00588 bitmap_set_all(map); 00589 bitmap_unlock(map); 00590 } 00591 00592 00593 void bitmap_lock_clear_all(MY_BITMAP *map) 00594 { 00595 bitmap_lock(map); 00596 bitmap_clear_all(map); 00597 bitmap_unlock(map); 00598 } 00599 00600 00601 void bitmap_lock_set_prefix(MY_BITMAP *map, uint prefix_size) 00602 { 00603 bitmap_lock(map); 00604 bitmap_set_prefix(map, prefix_size); 00605 bitmap_unlock(map); 00606 } 00607 00608 00609 my_bool bitmap_lock_is_clear_all(const MY_BITMAP *map) 00610 { 00611 uint res; 00612 bitmap_lock((MY_BITMAP *)map); 00613 res= bitmap_is_clear_all(map); 00614 bitmap_unlock((MY_BITMAP *)map); 00615 return res; 00616 } 00617 00618 00619 my_bool bitmap_lock_is_set_all(const MY_BITMAP *map) 00620 { 00621 uint res; 00622 bitmap_lock((MY_BITMAP *)map); 00623 res= bitmap_is_set_all(map); 00624 bitmap_unlock((MY_BITMAP *)map); 00625 return res; 00626 } 00627 00628 00629 my_bool bitmap_lock_is_set(const MY_BITMAP *map, uint bitmap_bit) 00630 { 00631 my_bool res; 00632 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); 00633 bitmap_lock((MY_BITMAP *)map); 00634 res= bitmap_is_set(map, bitmap_bit); 00635 bitmap_unlock((MY_BITMAP *)map); 00636 return res; 00637 } 00638 00639 00640 my_bool bitmap_lock_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2) 00641 { 00642 uint res; 00643 bitmap_lock((MY_BITMAP *)map1); 00644 bitmap_lock((MY_BITMAP *)map2); 00645 res= bitmap_is_subset(map1, map2); 00646 bitmap_unlock((MY_BITMAP *)map2); 00647 bitmap_unlock((MY_BITMAP *)map1); 00648 return res; 00649 } 00650 00651 00652 my_bool bitmap_lock_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) 00653 { 00654 uint res; 00655 00656 DBUG_ASSERT(map1->bitmap && map2->bitmap && 00657 map1->n_bits==map2->n_bits); 00658 bitmap_lock((MY_BITMAP *)map1); 00659 bitmap_lock((MY_BITMAP *)map2); 00660 res= bitmap_cmp(map1, map2); 00661 bitmap_unlock((MY_BITMAP *)map2); 00662 bitmap_unlock((MY_BITMAP *)map1); 00663 return res; 00664 } 00665 00666 00667 void bitmap_lock_intersect(MY_BITMAP *map, const MY_BITMAP *map2) 00668 { 00669 bitmap_lock(map); 00670 bitmap_lock((MY_BITMAP *)map2); 00671 bitmap_intersect(map, map2); 00672 bitmap_unlock((MY_BITMAP *)map2); 00673 bitmap_unlock(map); 00674 } 00675 00676 00677 void bitmap_lock_subtract(MY_BITMAP *map, const MY_BITMAP *map2) 00678 { 00679 bitmap_lock(map); 00680 bitmap_lock((MY_BITMAP *)map2); 00681 bitmap_subtract(map, map2); 00682 bitmap_unlock((MY_BITMAP *)map2); 00683 bitmap_unlock(map); 00684 } 00685 00686 00687 void bitmap_lock_union(MY_BITMAP *map, const MY_BITMAP *map2) 00688 { 00689 bitmap_lock(map); 00690 bitmap_lock((MY_BITMAP *)map2); 00691 bitmap_union(map, map2); 00692 bitmap_unlock((MY_BITMAP *)map2); 00693 bitmap_unlock(map); 00694 } 00695 00696 00697 /* 00698 SYNOPSIS 00699 bitmap_bits_set() 00700 map 00701 RETURN 00702 Number of set bits in the bitmap. 00703 */ 00704 uint bitmap_lock_bits_set(const MY_BITMAP *map) 00705 { 00706 uint res; 00707 bitmap_lock((MY_BITMAP *)map); 00708 DBUG_ASSERT(map->bitmap); 00709 res= bitmap_bits_set(map); 00710 bitmap_unlock((MY_BITMAP *)map); 00711 return res; 00712 } 00713 00714 00715 /* 00716 SYNOPSIS 00717 bitmap_get_first() 00718 map 00719 RETURN 00720 Number of first unset bit in the bitmap or MY_BIT_NONE if all bits are set. 00721 */ 00722 uint bitmap_lock_get_first(const MY_BITMAP *map) 00723 { 00724 uint res; 00725 bitmap_lock((MY_BITMAP*)map); 00726 res= bitmap_get_first(map); 00727 bitmap_unlock((MY_BITMAP*)map); 00728 return res; 00729 } 00730 00731 00732 uint bitmap_lock_get_first_set(const MY_BITMAP *map) 00733 { 00734 uint res; 00735 bitmap_lock((MY_BITMAP*)map); 00736 res= bitmap_get_first_set(map); 00737 bitmap_unlock((MY_BITMAP*)map); 00738 return res; 00739 } 00740 00741 00742 void bitmap_lock_set_bit(MY_BITMAP *map, uint bitmap_bit) 00743 { 00744 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); 00745 bitmap_lock(map); 00746 bitmap_set_bit(map, bitmap_bit); 00747 bitmap_unlock(map); 00748 } 00749 00750 00751 void bitmap_lock_flip_bit(MY_BITMAP *map, uint bitmap_bit) 00752 { 00753 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits); 00754 bitmap_lock(map); 00755 bitmap_flip_bit(map, bitmap_bit); 00756 bitmap_unlock(map); 00757 } 00758 #endif 00759 #ifdef MAIN 00760 00761 uint get_rand_bit(uint bitsize) 00762 { 00763 return (rand() % bitsize); 00764 } 00765 00766 bool test_set_get_clear_bit(MY_BITMAP *map, uint bitsize) 00767 { 00768 uint i, test_bit; 00769 uint no_loops= bitsize > 128 ? 128 : bitsize; 00770 for (i=0; i < no_loops; i++) 00771 { 00772 test_bit= get_rand_bit(bitsize); 00773 bitmap_set_bit(map, test_bit); 00774 if (!bitmap_is_set(map, test_bit)) 00775 goto error1; 00776 bitmap_clear_bit(map, test_bit); 00777 if (bitmap_is_set(map, test_bit)) 00778 goto error2; 00779 } 00780 return FALSE; 00781 error1: 00782 printf("Error in set bit, bit %u, bitsize = %u", test_bit, bitsize); 00783 return TRUE; 00784 error2: 00785 printf("Error in clear bit, bit %u, bitsize = %u", test_bit, bitsize); 00786 return TRUE; 00787 } 00788 00789 bool test_flip_bit(MY_BITMAP *map, uint bitsize) 00790 { 00791 uint i, test_bit; 00792 uint no_loops= bitsize > 128 ? 128 : bitsize; 00793 for (i=0; i < no_loops; i++) 00794 { 00795 test_bit= get_rand_bit(bitsize); 00796 bitmap_flip_bit(map, test_bit); 00797 if (!bitmap_is_set(map, test_bit)) 00798 goto error1; 00799 bitmap_flip_bit(map, test_bit); 00800 if (bitmap_is_set(map, test_bit)) 00801 goto error2; 00802 } 00803 return FALSE; 00804 error1: 00805 printf("Error in flip bit 1, bit %u, bitsize = %u", test_bit, bitsize); 00806 return TRUE; 00807 error2: 00808 printf("Error in flip bit 2, bit %u, bitsize = %u", test_bit, bitsize); 00809 return TRUE; 00810 } 00811 00812 bool test_operators(MY_BITMAP *map __attribute__((unused)), 00813 uint bitsize __attribute__((unused))) 00814 { 00815 return FALSE; 00816 } 00817 00818 bool test_get_all_bits(MY_BITMAP *map, uint bitsize) 00819 { 00820 uint i; 00821 bitmap_set_all(map); 00822 if (!bitmap_is_set_all(map)) 00823 goto error1; 00824 if (!bitmap_is_prefix(map, bitsize)) 00825 goto error5; 00826 bitmap_clear_all(map); 00827 if (!bitmap_is_clear_all(map)) 00828 goto error2; 00829 if (!bitmap_is_prefix(map, 0)) 00830 goto error6; 00831 for (i=0; i<bitsize;i++) 00832 bitmap_set_bit(map, i); 00833 if (!bitmap_is_set_all(map)) 00834 goto error3; 00835 for (i=0; i<bitsize;i++) 00836 bitmap_clear_bit(map, i); 00837 if (!bitmap_is_clear_all(map)) 00838 goto error4; 00839 return FALSE; 00840 error1: 00841 printf("Error in set_all, bitsize = %u", bitsize); 00842 return TRUE; 00843 error2: 00844 printf("Error in clear_all, bitsize = %u", bitsize); 00845 return TRUE; 00846 error3: 00847 printf("Error in bitmap_is_set_all, bitsize = %u", bitsize); 00848 return TRUE; 00849 error4: 00850 printf("Error in bitmap_is_clear_all, bitsize = %u", bitsize); 00851 return TRUE; 00852 error5: 00853 printf("Error in set_all through set_prefix, bitsize = %u", bitsize); 00854 return TRUE; 00855 error6: 00856 printf("Error in clear_all through set_prefix, bitsize = %u", bitsize); 00857 return TRUE; 00858 } 00859 00860 bool test_compare_operators(MY_BITMAP *map, uint bitsize) 00861 { 00862 uint i, j, test_bit1, test_bit2, test_bit3,test_bit4; 00863 uint no_loops= bitsize > 128 ? 128 : bitsize; 00864 MY_BITMAP map2_obj, map3_obj; 00865 MY_BITMAP *map2= &map2_obj, *map3= &map3_obj; 00866 my_bitmap_map map2buf[1024]; 00867 my_bitmap_map map3buf[1024]; 00868 bitmap_init(&map2_obj, map2buf, bitsize, FALSE); 00869 bitmap_init(&map3_obj, map3buf, bitsize, FALSE); 00870 bitmap_clear_all(map2); 00871 bitmap_clear_all(map3); 00872 for (i=0; i < no_loops; i++) 00873 { 00874 test_bit1=get_rand_bit(bitsize); 00875 bitmap_set_prefix(map, test_bit1); 00876 test_bit2=get_rand_bit(bitsize); 00877 bitmap_set_prefix(map2, test_bit2); 00878 bitmap_intersect(map, map2); 00879 test_bit3= test_bit2 < test_bit1 ? test_bit2 : test_bit1; 00880 bitmap_set_prefix(map3, test_bit3); 00881 if (!bitmap_cmp(map, map3)) 00882 goto error1; 00883 bitmap_clear_all(map); 00884 bitmap_clear_all(map2); 00885 bitmap_clear_all(map3); 00886 test_bit1=get_rand_bit(bitsize); 00887 test_bit2=get_rand_bit(bitsize); 00888 test_bit3=get_rand_bit(bitsize); 00889 bitmap_set_prefix(map, test_bit1); 00890 bitmap_set_prefix(map2, test_bit2); 00891 test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1; 00892 bitmap_set_prefix(map3, test_bit3); 00893 bitmap_union(map, map2); 00894 if (!bitmap_cmp(map, map3)) 00895 goto error2; 00896 bitmap_clear_all(map); 00897 bitmap_clear_all(map2); 00898 bitmap_clear_all(map3); 00899 test_bit1=get_rand_bit(bitsize); 00900 test_bit2=get_rand_bit(bitsize); 00901 test_bit3=get_rand_bit(bitsize); 00902 bitmap_set_prefix(map, test_bit1); 00903 bitmap_set_prefix(map2, test_bit2); 00904 bitmap_xor(map, map2); 00905 test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1; 00906 test_bit4= test_bit2 < test_bit1 ? test_bit2 : test_bit1; 00907 bitmap_set_prefix(map3, test_bit3); 00908 for (j=0; j < test_bit4; j++) 00909 bitmap_clear_bit(map3, j); 00910 if (!bitmap_cmp(map, map3)) 00911 goto error3; 00912 bitmap_clear_all(map); 00913 bitmap_clear_all(map2); 00914 bitmap_clear_all(map3); 00915 test_bit1=get_rand_bit(bitsize); 00916 test_bit2=get_rand_bit(bitsize); 00917 test_bit3=get_rand_bit(bitsize); 00918 bitmap_set_prefix(map, test_bit1); 00919 bitmap_set_prefix(map2, test_bit2); 00920 bitmap_subtract(map, map2); 00921 if (test_bit2 < test_bit1) 00922 { 00923 bitmap_set_prefix(map3, test_bit1); 00924 for (j=0; j < test_bit2; j++) 00925 bitmap_clear_bit(map3, j); 00926 } 00927 if (!bitmap_cmp(map, map3)) 00928 goto error4; 00929 bitmap_clear_all(map); 00930 bitmap_clear_all(map2); 00931 bitmap_clear_all(map3); 00932 test_bit1=get_rand_bit(bitsize); 00933 bitmap_set_prefix(map, test_bit1); 00934 bitmap_invert(map); 00935 bitmap_set_all(map3); 00936 for (j=0; j < test_bit1; j++) 00937 bitmap_clear_bit(map3, j); 00938 if (!bitmap_cmp(map, map3)) 00939 goto error5; 00940 bitmap_clear_all(map); 00941 bitmap_clear_all(map3); 00942 } 00943 return FALSE; 00944 error1: 00945 printf("intersect error bitsize=%u,size1=%u,size2=%u", bitsize, 00946 test_bit1,test_bit2); 00947 return TRUE; 00948 error2: 00949 printf("union error bitsize=%u,size1=%u,size2=%u", bitsize, 00950 test_bit1,test_bit2); 00951 return TRUE; 00952 error3: 00953 printf("xor error bitsize=%u,size1=%u,size2=%u", bitsize, 00954 test_bit1,test_bit2); 00955 return TRUE; 00956 error4: 00957 printf("subtract error bitsize=%u,size1=%u,size2=%u", bitsize, 00958 test_bit1,test_bit2); 00959 return TRUE; 00960 error5: 00961 printf("invert error bitsize=%u,size=%u", bitsize, 00962 test_bit1); 00963 return TRUE; 00964 } 00965 00966 bool test_count_bits_set(MY_BITMAP *map, uint bitsize) 00967 { 00968 uint i, bit_count=0, test_bit; 00969 uint no_loops= bitsize > 128 ? 128 : bitsize; 00970 for (i=0; i < no_loops; i++) 00971 { 00972 test_bit=get_rand_bit(bitsize); 00973 if (!bitmap_is_set(map, test_bit)) 00974 { 00975 bitmap_set_bit(map, test_bit); 00976 bit_count++; 00977 } 00978 } 00979 if (bit_count==0 && bitsize > 0) 00980 goto error1; 00981 if (bitmap_bits_set(map) != bit_count) 00982 goto error2; 00983 return FALSE; 00984 error1: 00985 printf("No bits set bitsize = %u", bitsize); 00986 return TRUE; 00987 error2: 00988 printf("Wrong count of bits set, bitsize = %u", bitsize); 00989 return TRUE; 00990 } 00991 00992 bool test_get_first_bit(MY_BITMAP *map, uint bitsize) 00993 { 00994 uint i, test_bit; 00995 uint no_loops= bitsize > 128 ? 128 : bitsize; 00996 for (i=0; i < no_loops; i++) 00997 { 00998 test_bit=get_rand_bit(bitsize); 00999 bitmap_set_bit(map, test_bit); 01000 if (bitmap_get_first_set(map) != test_bit) 01001 goto error1; 01002 bitmap_set_all(map); 01003 bitmap_clear_bit(map, test_bit); 01004 if (bitmap_get_first(map) != test_bit) 01005 goto error2; 01006 bitmap_clear_all(map); 01007 } 01008 return FALSE; 01009 error1: 01010 printf("get_first_set error bitsize=%u,prefix_size=%u",bitsize,test_bit); 01011 return TRUE; 01012 error2: 01013 printf("get_first error bitsize= %u, prefix_size= %u",bitsize,test_bit); 01014 return TRUE; 01015 } 01016 01017 bool test_get_next_bit(MY_BITMAP *map, uint bitsize) 01018 { 01019 uint i, j, test_bit; 01020 uint no_loops= bitsize > 128 ? 128 : bitsize; 01021 for (i=0; i < no_loops; i++) 01022 { 01023 test_bit=get_rand_bit(bitsize); 01024 for (j=0; j < test_bit; j++) 01025 bitmap_set_next(map); 01026 if (!bitmap_is_prefix(map, test_bit)) 01027 goto error1; 01028 bitmap_clear_all(map); 01029 } 01030 return FALSE; 01031 error1: 01032 printf("get_next error bitsize= %u, prefix_size= %u", bitsize,test_bit); 01033 return TRUE; 01034 } 01035 01036 bool test_prefix(MY_BITMAP *map, uint bitsize) 01037 { 01038 uint i, j, test_bit; 01039 uint no_loops= bitsize > 128 ? 128 : bitsize; 01040 for (i=0; i < no_loops; i++) 01041 { 01042 test_bit=get_rand_bit(bitsize); 01043 bitmap_set_prefix(map, test_bit); 01044 if (!bitmap_is_prefix(map, test_bit)) 01045 goto error1; 01046 bitmap_clear_all(map); 01047 for (j=0; j < test_bit; j++) 01048 bitmap_set_bit(map, j); 01049 if (!bitmap_is_prefix(map, test_bit)) 01050 goto error2; 01051 bitmap_set_all(map); 01052 for (j=bitsize - 1; ~(j-test_bit); j--) 01053 bitmap_clear_bit(map, j); 01054 if (!bitmap_is_prefix(map, test_bit)) 01055 goto error3; 01056 bitmap_clear_all(map); 01057 } 01058 return FALSE; 01059 error1: 01060 printf("prefix1 error bitsize = %u, prefix_size = %u", bitsize,test_bit); 01061 return TRUE; 01062 error2: 01063 printf("prefix2 error bitsize = %u, prefix_size = %u", bitsize,test_bit); 01064 return TRUE; 01065 error3: 01066 printf("prefix3 error bitsize = %u, prefix_size = %u", bitsize,test_bit); 01067 return TRUE; 01068 } 01069 01070 01071 bool do_test(uint bitsize) 01072 { 01073 MY_BITMAP map; 01074 my_bitmap_map buf[1024]; 01075 if (bitmap_init(&map, buf, bitsize, FALSE)) 01076 { 01077 printf("init error for bitsize %d", bitsize); 01078 goto error; 01079 } 01080 if (test_set_get_clear_bit(&map,bitsize)) 01081 goto error; 01082 bitmap_clear_all(&map); 01083 if (test_flip_bit(&map,bitsize)) 01084 goto error; 01085 bitmap_clear_all(&map); 01086 if (test_operators(&map,bitsize)) 01087 goto error; 01088 bitmap_clear_all(&map); 01089 if (test_get_all_bits(&map, bitsize)) 01090 goto error; 01091 bitmap_clear_all(&map); 01092 if (test_compare_operators(&map,bitsize)) 01093 goto error; 01094 bitmap_clear_all(&map); 01095 if (test_count_bits_set(&map,bitsize)) 01096 goto error; 01097 bitmap_clear_all(&map); 01098 if (test_get_first_bit(&map,bitsize)) 01099 goto error; 01100 bitmap_clear_all(&map); 01101 if (test_get_next_bit(&map,bitsize)) 01102 goto error; 01103 if (test_prefix(&map,bitsize)) 01104 goto error; 01105 return FALSE; 01106 error: 01107 printf("\n"); 01108 return TRUE; 01109 } 01110 01111 int main() 01112 { 01113 int i; 01114 for (i= 1; i < 4096; i++) 01115 { 01116 printf("Start test for bitsize=%u\n",i); 01117 if (do_test(i)) 01118 return -1; 01119 } 01120 printf("OK\n"); 01121 return 0; 01122 } 01123 01124 /* 01125 In directory mysys: 01126 make test_bitmap 01127 will build the bitmap tests and ./test_bitmap will execute it 01128 */ 01129 01130 #endif
1.4.7

