00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef BMALGO_IMPL__H__INCLUDED__
00028 #define BMALGO_IMPL__H__INCLUDED__
00029
00030 #ifdef _MSC_VER
00031 #pragma warning( disable : 4311 4312)
00032 #endif
00033
00034
00035 namespace bm
00036 {
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 enum distance_metric
00054 {
00055 COUNT_AND = set_COUNT_AND,
00056 COUNT_XOR = set_COUNT_XOR,
00057 COUNT_OR = set_COUNT_OR,
00058 COUNT_SUB_AB = set_COUNT_SUB_AB,
00059 COUNT_SUB_BA = set_COUNT_SUB_BA,
00060 COUNT_A = set_COUNT_A,
00061 COUNT_B = set_COUNT_B
00062 };
00063
00064
00065
00066
00067
00068 inline
00069 distance_metric operation2metric(set_operation op)
00070 {
00071 BM_ASSERT(is_const_set_operation(op));
00072 if (op == set_COUNT) op = set_COUNT_B;
00073
00074
00075 return (distance_metric) op;
00076 }
00077
00078
00079
00080
00081
00082
00083 struct distance_metric_descriptor
00084 {
00085 distance_metric metric;
00086 bm::id_t result;
00087
00088 distance_metric_descriptor(distance_metric m)
00089 : metric(m),
00090 result(0)
00091 {}
00092 distance_metric_descriptor()
00093 : metric(bm::COUNT_XOR),
00094 result(0)
00095 {}
00096
00097
00098
00099
00100 void reset()
00101 {
00102 result = 0;
00103 }
00104 };
00105
00106
00107
00108
00109
00110
00111
00112
00113 inline
00114 void combine_count_operation_with_block(const bm::word_t* blk,
00115 unsigned gap,
00116 const bm::word_t* arg_blk,
00117 int arg_gap,
00118 bm::word_t* temp_blk,
00119 distance_metric_descriptor* dmit,
00120 distance_metric_descriptor* dmit_end)
00121
00122 {
00123 gap_word_t* res=0;
00124
00125 gap_word_t* g1 = BMGAP_PTR(blk);
00126 gap_word_t* g2 = BMGAP_PTR(arg_blk);
00127
00128 if (gap)
00129 {
00130 if (arg_gap)
00131 {
00132 gap_word_t tmp_buf[bm::gap_max_buff_len * 3];
00133
00134 for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
00135 {
00136 distance_metric_descriptor& dmd = *it;
00137
00138 switch (dmd.metric)
00139 {
00140 case bm::COUNT_AND:
00141 res = gap_operation_and(g1, g2, tmp_buf);
00142 break;
00143 case bm::COUNT_OR:
00144 res = gap_operation_or(g1, g2, tmp_buf);
00145 break;
00146 case bm::COUNT_SUB_AB:
00147 res = gap_operation_sub(g1, g2, tmp_buf);
00148 break;
00149 case bm::COUNT_SUB_BA:
00150 res = gap_operation_sub(g2, g1, tmp_buf);
00151 break;
00152 case bm::COUNT_XOR:
00153 res = gap_operation_xor(g1, g2, tmp_buf);
00154 break;
00155 case bm::COUNT_A:
00156 res = g1;
00157 break;
00158 case bm::COUNT_B:
00159 res = g2;
00160 break;
00161 }
00162
00163 if (res)
00164 dmd.result += gap_bit_count(res);
00165
00166 }
00167
00168 return;
00169
00170 }
00171 else
00172 {
00173 for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
00174 {
00175 distance_metric_descriptor& dmd = *it;
00176
00177 switch (dmd.metric)
00178 {
00179 case bm::COUNT_AND:
00180 if (arg_blk)
00181 dmd.result += gap_bitset_and_count(arg_blk, g1);
00182 break;
00183 case bm::COUNT_OR:
00184 if (!arg_blk)
00185 dmd.result += gap_bit_count(g1);
00186 else
00187 dmd.result += gap_bitset_or_count(arg_blk, g1);
00188 break;
00189 case bm::COUNT_SUB_AB:
00190 gap_convert_to_bitset((bm::word_t*) temp_blk, g1);
00191 dmd.result +=
00192 bit_operation_sub_count((bm::word_t*)temp_blk,
00193 ((bm::word_t*)temp_blk) + bm::set_block_size,
00194 arg_blk);
00195
00196 break;
00197 case bm::COUNT_SUB_BA:
00198 dmd.metric = bm::COUNT_SUB_AB;
00199 combine_count_operation_with_block(arg_blk,
00200 arg_gap,
00201 blk,
00202 gap,
00203 temp_blk,
00204 it, it+1);
00205 dmd.metric = bm::COUNT_SUB_BA;
00206 break;
00207 case bm::COUNT_XOR:
00208 if (!arg_blk)
00209 dmd.result += gap_bit_count(g1);
00210 else
00211 dmd.result += gap_bitset_xor_count(arg_blk, g1);
00212 break;
00213 case bm::COUNT_A:
00214 if (g1)
00215 dmd.result += gap_bit_count(g1);
00216 break;
00217 case bm::COUNT_B:
00218 if (arg_blk)
00219 {
00220 dmd.result +=
00221 bit_block_calc_count(arg_blk,
00222 arg_blk + bm::set_block_size);
00223 }
00224 break;
00225 }
00226
00227 }
00228
00229 return;
00230
00231 }
00232 }
00233 else
00234 {
00235 if (arg_gap)
00236 {
00237 for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
00238 {
00239 distance_metric_descriptor& dmd = *it;
00240
00241 switch (dmd.metric)
00242 {
00243 case bm::COUNT_AND:
00244 if (blk)
00245 dmd.result += gap_bitset_and_count(blk, g2);
00246 break;
00247 case bm::COUNT_OR:
00248 if (!blk)
00249 dmd.result += gap_bit_count(g2);
00250 else
00251 dmd.result += gap_bitset_or_count(blk, g2);
00252 break;
00253 case bm::COUNT_SUB_AB:
00254 if (blk)
00255 dmd.result += gap_bitset_sub_count(blk, g2);
00256 break;
00257 case bm::COUNT_SUB_BA:
00258 dmd.metric = bm::COUNT_SUB_AB;
00259 combine_count_operation_with_block(arg_blk,
00260 arg_gap,
00261 blk,
00262 gap,
00263 temp_blk,
00264 it, it+1);
00265 dmd.metric = bm::COUNT_SUB_BA;
00266 break;
00267 case bm::COUNT_XOR:
00268 if (!blk)
00269 dmd.result += gap_bit_count(g2);
00270 else
00271 dmd.result += gap_bitset_xor_count(blk, g2);
00272 break;
00273 case bm::COUNT_A:
00274 if (blk)
00275 {
00276 dmd.result +=
00277 bit_block_calc_count(blk,
00278 blk + bm::set_block_size);
00279 }
00280 break;
00281 case bm::COUNT_B:
00282 if (g2)
00283 dmd.result += gap_bit_count(g2);
00284 break;
00285 }
00286
00287 }
00288
00289 return;
00290 }
00291 }
00292
00293
00294
00295
00296
00297 const bm::word_t* blk_end;
00298
00299
00300 blk_end = blk + (bm::set_block_size);
00301
00302
00303
00304 for (distance_metric_descriptor* it = dmit; it < dmit_end; ++it)
00305 {
00306 distance_metric_descriptor& dmd = *it;
00307 bit_operation_count_func_type gfunc =
00308 operation_functions<true>::bit_operation_count(dmd.metric);
00309 if (gfunc)
00310 {
00311 dmd.result += (*gfunc)(blk, blk_end, arg_blk);
00312 }
00313 else
00314 {
00315 switch (dmd.metric)
00316 {
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 case bm::COUNT_A:
00340 if (blk)
00341 dmd.result += bit_block_calc_count(blk, blk_end);
00342 break;
00343 case bm::COUNT_B:
00344 if (arg_blk)
00345 dmd.result +=
00346 bit_block_calc_count(arg_blk,
00347 arg_blk + bm::set_block_size);
00348 break;
00349 default:
00350 BM_ASSERT(0);
00351 }
00352 }
00353
00354 }
00355 }
00356
00357
00358
00359
00360
00361
00362 inline
00363 void combine_any_operation_with_block(const bm::word_t* blk,
00364 unsigned gap,
00365 const bm::word_t* arg_blk,
00366 int arg_gap,
00367 bm::word_t* temp_blk,
00368 distance_metric_descriptor* dmit,
00369 distance_metric_descriptor* dmit_end)
00370
00371 {
00372 gap_word_t* res=0;
00373
00374 gap_word_t* g1 = BMGAP_PTR(blk);
00375 gap_word_t* g2 = BMGAP_PTR(arg_blk);
00376
00377 if (gap)
00378 {
00379 if (arg_gap)
00380 {
00381 gap_word_t tmp_buf[bm::gap_max_buff_len * 3];
00382
00383 for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
00384 {
00385 distance_metric_descriptor& dmd = *it;
00386 if (dmd.result)
00387 {
00388 continue;
00389 }
00390 res = 0;
00391 switch (dmd.metric)
00392 {
00393 case bm::COUNT_AND:
00394 dmd.result += gap_operation_any_and(g1, g2);
00395 break;
00396 case bm::COUNT_OR:
00397 res = gap_operation_or(g1, g2, tmp_buf);
00398 break;
00399 case bm::COUNT_SUB_AB:
00400 dmd.result += gap_operation_any_sub(g1, g2);
00401 break;
00402 case bm::COUNT_SUB_BA:
00403 dmd.result += gap_operation_any_sub(g2, g1);
00404 break;
00405 case bm::COUNT_XOR:
00406 dmd.result += gap_operation_any_xor(g1, g2);
00407 break;
00408 case bm::COUNT_A:
00409 res = g1;
00410 break;
00411 case bm::COUNT_B:
00412 res = g2;
00413 break;
00414 }
00415 if (res)
00416 dmd.result += !gap_is_all_zero(res, bm::gap_max_bits);
00417
00418 }
00419
00420 return;
00421
00422 }
00423 else
00424 {
00425 for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
00426 {
00427 distance_metric_descriptor& dmd = *it;
00428 if (dmd.result)
00429 {
00430 continue;
00431 }
00432
00433 switch (dmd.metric)
00434 {
00435 case bm::COUNT_AND:
00436 if (arg_blk)
00437 dmd.result += gap_bitset_and_any(arg_blk, g1);
00438 break;
00439 case bm::COUNT_OR:
00440 if (!arg_blk)
00441 dmd.result += !gap_is_all_zero(g1, bm::gap_max_bits);
00442 else
00443 dmd.result += gap_bitset_or_any(arg_blk, g1);
00444 break;
00445 case bm::COUNT_SUB_AB:
00446 gap_convert_to_bitset((bm::word_t*) temp_blk, g1);
00447 dmd.result +=
00448 bit_operation_sub_any((bm::word_t*)temp_blk,
00449 ((bm::word_t*)temp_blk) + bm::set_block_size,
00450 arg_blk);
00451
00452 break;
00453 case bm::COUNT_SUB_BA:
00454 dmd.metric = bm::COUNT_SUB_AB;
00455 combine_any_operation_with_block(arg_blk,
00456 arg_gap,
00457 blk,
00458 gap,
00459 temp_blk,
00460 it, it+1);
00461 dmd.metric = bm::COUNT_SUB_BA;
00462 break;
00463 case bm::COUNT_XOR:
00464 if (!arg_blk)
00465 dmd.result += !gap_is_all_zero(g1, bm::gap_max_bits);
00466 else
00467 dmd.result += gap_bitset_xor_any(arg_blk, g1);
00468 break;
00469 case bm::COUNT_A:
00470 if (g1)
00471 dmd.result += !gap_is_all_zero(g1, bm::gap_max_bits);
00472 break;
00473 case bm::COUNT_B:
00474 if (arg_blk)
00475 {
00476 dmd.result +=
00477 !bit_is_all_zero(arg_blk,
00478 arg_blk + bm::set_block_size);
00479 }
00480 break;
00481 }
00482
00483 }
00484
00485 return;
00486
00487 }
00488 }
00489 else
00490 {
00491 if (arg_gap)
00492 {
00493 for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
00494 {
00495 distance_metric_descriptor& dmd = *it;
00496 if (dmd.result)
00497 {
00498 continue;
00499 }
00500
00501 switch (dmd.metric)
00502 {
00503 case bm::COUNT_AND:
00504 if (blk)
00505 dmd.result += gap_bitset_and_any(blk, g2);
00506 break;
00507 case bm::COUNT_OR:
00508 if (!blk)
00509 dmd.result += !gap_is_all_zero(g2, bm::gap_max_bits);
00510 else
00511 dmd.result += gap_bitset_or_any(blk, g2);
00512 break;
00513 case bm::COUNT_SUB_AB:
00514 if (blk)
00515 dmd.result += gap_bitset_sub_any(blk, g2);
00516 break;
00517 case bm::COUNT_SUB_BA:
00518 dmd.metric = bm::COUNT_SUB_AB;
00519 combine_any_operation_with_block(arg_blk,
00520 arg_gap,
00521 blk,
00522 gap,
00523 temp_blk,
00524 it, it+1);
00525 dmd.metric = bm::COUNT_SUB_BA;
00526 break;
00527 case bm::COUNT_XOR:
00528 if (!blk)
00529 dmd.result += !gap_is_all_zero(g2, bm::gap_max_bits);
00530 else
00531 dmd.result += gap_bitset_xor_any(blk, g2);
00532 break;
00533 case bm::COUNT_A:
00534 if (blk)
00535 {
00536 dmd.result+=
00537 !bit_is_all_zero(blk, blk + bm::set_block_size);
00538 }
00539 break;
00540 case bm::COUNT_B:
00541 if (g2)
00542 dmd.result += !gap_is_all_zero(g2, bm::gap_max_bits);
00543 break;
00544 }
00545
00546 }
00547
00548 return;
00549 }
00550 }
00551
00552
00553
00554
00555
00556 const bm::word_t* blk_end;
00557 const bm::word_t* arg_end;
00558
00559 blk_end = blk + (bm::set_block_size);
00560 arg_end = arg_blk + (bm::set_block_size);
00561
00562 for (distance_metric_descriptor* it = dmit; it < dmit_end; ++it)
00563 {
00564 distance_metric_descriptor& dmd = *it;
00565 if (dmd.result)
00566 {
00567 continue;
00568 }
00569
00570 switch (dmd.metric)
00571 {
00572 case bm::COUNT_AND:
00573 dmd.result +=
00574 bit_operation_and_any(blk, blk_end, arg_blk);
00575 break;
00576 case bm::COUNT_OR:
00577 dmd.result +=
00578 bit_operation_or_any(blk, blk_end, arg_blk);
00579 break;
00580 case bm::COUNT_SUB_AB:
00581 dmd.result +=
00582 bit_operation_sub_any(blk, blk_end, arg_blk);
00583 break;
00584 case bm::COUNT_SUB_BA:
00585 dmd.result +=
00586 bit_operation_sub_any(arg_blk, arg_end, blk);
00587 break;
00588 case bm::COUNT_XOR:
00589 dmd.result +=
00590 bit_operation_xor_any(blk, blk_end, arg_blk);
00591 break;
00592 case bm::COUNT_A:
00593 if (blk)
00594 dmd.result += !bit_is_all_zero(blk, blk_end);
00595 break;
00596 case bm::COUNT_B:
00597 if (arg_blk)
00598 dmd.result += !bit_is_all_zero(arg_blk, arg_end);
00599 break;
00600 }
00601
00602 }
00603 }
00604
00605
00606
00607
00608
00609
00610
00611
00612 inline
00613 unsigned combine_count_operation_with_block(const bm::word_t* blk,
00614 unsigned gap,
00615 const bm::word_t* arg_blk,
00616 int arg_gap,
00617 bm::word_t* temp_blk,
00618 distance_metric metric)
00619 {
00620 distance_metric_descriptor dmd(metric);
00621 combine_count_operation_with_block(blk, gap,
00622 arg_blk, arg_gap,
00623 temp_blk,
00624 &dmd, &dmd+1);
00625 return dmd.result;
00626 }
00627
00628
00629
00630
00631
00632
00633
00634 inline
00635 unsigned combine_any_operation_with_block(const bm::word_t* blk,
00636 unsigned gap,
00637 const bm::word_t* arg_blk,
00638 int arg_gap,
00639 bm::word_t* temp_blk,
00640 distance_metric metric)
00641 {
00642 distance_metric_descriptor dmd(metric);
00643 combine_any_operation_with_block(blk, gap,
00644 arg_blk, arg_gap,
00645 temp_blk,
00646 &dmd, &dmd+1);
00647 return dmd.result;
00648 }
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671 template<class BV>
00672 void distance_operation(const BV& bv1,
00673 const BV& bv2,
00674 distance_metric_descriptor* dmit,
00675 distance_metric_descriptor* dmit_end)
00676 {
00677 const typename BV::blocks_manager_type& bman1 = bv1.get_blocks_manager();
00678 const typename BV::blocks_manager_type& bman2 = bv2.get_blocks_manager();
00679
00680 bm::word_t* temp_blk = 0;
00681
00682 {
00683 for (distance_metric_descriptor* it = dmit; it < dmit_end; ++it)
00684 {
00685 if (it->metric == bm::COUNT_SUB_AB ||
00686 it->metric == bm::COUNT_SUB_BA)
00687 {
00688 temp_blk = bv1.allocate_tempblock();
00689 break;
00690 }
00691 }
00692 }
00693
00694
00695 bm::word_t*** blk_root = bman1.get_rootblock();
00696 unsigned block_idx = 0;
00697 unsigned i, j;
00698
00699 const bm::word_t* blk;
00700 const bm::word_t* arg_blk;
00701 bool blk_gap;
00702 bool arg_gap;
00703
00704 BM_SET_MMX_GUARD
00705
00706 unsigned effective_top_block_size = bman1.effective_top_block_size();
00707 unsigned ebs2 = bman2.effective_top_block_size();
00708 if (ebs2 > effective_top_block_size)
00709 effective_top_block_size = ebs2;
00710
00711 for (i = 0; i < effective_top_block_size; ++i)
00712 {
00713 bm::word_t** blk_blk = blk_root[i];
00714
00715 if (blk_blk == 0)
00716 {
00717 const bm::word_t* const* bvbb = bman2.get_topblock(i);
00718 if (bvbb == 0)
00719 {
00720 block_idx += bm::set_array_size;
00721 continue;
00722 }
00723
00724 blk = 0;
00725 blk_gap = false;
00726
00727 for (j = 0; j < bm::set_array_size; ++j,++block_idx)
00728 {
00729 arg_blk = bman2.get_block(i, j);
00730 arg_gap = BM_IS_GAP(bman2, arg_blk, block_idx);
00731
00732 if (!arg_blk)
00733 continue;
00734 combine_count_operation_with_block(blk, blk_gap,
00735 arg_blk, arg_gap,
00736 temp_blk,
00737 dmit, dmit_end);
00738 }
00739 continue;
00740 }
00741
00742 for (j = 0; j < bm::set_array_size; ++j, ++block_idx)
00743 {
00744 blk = blk_blk[j];
00745 arg_blk = bman2.get_block(i, j);
00746
00747 if (blk == 0 && arg_blk == 0)
00748 continue;
00749
00750 arg_gap = BM_IS_GAP(bman2, arg_blk, block_idx);
00751 blk_gap = BM_IS_GAP(bman1, blk, block_idx);
00752
00753 combine_count_operation_with_block(blk, blk_gap,
00754 arg_blk, arg_gap,
00755 temp_blk,
00756 dmit, dmit_end);
00757
00758
00759 }
00760
00761 }
00762
00763 if (temp_blk)
00764 {
00765 bv1.free_tempblock(temp_blk);
00766 }
00767
00768 }
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 template<class BV>
00794 void distance_operation_any(const BV& bv1,
00795 const BV& bv2,
00796 distance_metric_descriptor* dmit,
00797 distance_metric_descriptor* dmit_end)
00798 {
00799 const typename BV::blocks_manager_type& bman1 = bv1.get_blocks_manager();
00800 const typename BV::blocks_manager_type& bman2 = bv2.get_blocks_manager();
00801
00802 bm::word_t* temp_blk = 0;
00803
00804 {
00805 for (distance_metric_descriptor* it = dmit; it < dmit_end; ++it)
00806 {
00807 if (it->metric == bm::COUNT_SUB_AB ||
00808 it->metric == bm::COUNT_SUB_BA)
00809 {
00810 temp_blk = bv1.allocate_tempblock();
00811 break;
00812 }
00813 }
00814 }
00815
00816
00817 bm::word_t*** blk_root = bman1.get_rootblock();
00818 unsigned block_idx = 0;
00819 unsigned i, j;
00820
00821 const bm::word_t* blk;
00822 const bm::word_t* arg_blk;
00823 bool blk_gap;
00824 bool arg_gap;
00825
00826 BM_SET_MMX_GUARD
00827
00828 unsigned effective_top_block_size = bman1.effective_top_block_size();
00829 unsigned ebs2 = bman2.effective_top_block_size();
00830 if (ebs2 > effective_top_block_size)
00831 effective_top_block_size = ebs2;
00832
00833 for (i = 0; i < effective_top_block_size; ++i)
00834 {
00835 bm::word_t** blk_blk = blk_root[i];
00836
00837 if (blk_blk == 0)
00838 {
00839 const bm::word_t* const* bvbb = bman2.get_topblock(i);
00840 if (bvbb == 0)
00841 {
00842 block_idx += bm::set_array_size;
00843 continue;
00844 }
00845
00846 blk = 0;
00847 blk_gap = false;
00848
00849 for (j = 0; j < bm::set_array_size; ++j,++block_idx)
00850 {
00851 arg_blk = bman2.get_block(i, j);
00852 arg_gap = BM_IS_GAP(bman2, arg_blk, block_idx);
00853
00854 if (!arg_blk)
00855 continue;
00856 combine_any_operation_with_block(blk, blk_gap,
00857 arg_blk, arg_gap,
00858 temp_blk,
00859 dmit, dmit_end);
00860
00861
00862 bool all_resolved = false;
00863 distance_metric_descriptor* it=dmit;
00864 do
00865 {
00866 if (!it->result)
00867 {
00868 all_resolved = false;
00869 break;
00870 }
00871 ++it;
00872 } while (it < dmit_end);
00873 if (all_resolved)
00874 goto return_proc;
00875 }
00876
00877 continue;
00878 }
00879
00880 for (j = 0; j < bm::set_array_size; ++j, ++block_idx)
00881 {
00882 blk = blk_blk[j];
00883 arg_blk = bman2.get_block(i, j);
00884
00885 if (blk == 0 && arg_blk == 0)
00886 continue;
00887
00888 arg_gap = BM_IS_GAP(bman2, arg_blk, block_idx);
00889 blk_gap = BM_IS_GAP(bman1, blk, block_idx);
00890
00891 combine_any_operation_with_block(blk, blk_gap,
00892 arg_blk, arg_gap,
00893 temp_blk,
00894 dmit, dmit_end);
00895
00896
00897 bool all_resolved = false;
00898 distance_metric_descriptor* it=dmit;
00899 do
00900 {
00901 if (!it->result)
00902 {
00903 all_resolved = false;
00904 break;
00905 }
00906 ++it;
00907 } while (it < dmit_end);
00908 if (all_resolved)
00909 goto return_proc;
00910
00911 }
00912
00913 }
00914 return_proc:
00915 if (temp_blk)
00916 {
00917 bv1.free_tempblock(temp_blk);
00918 }
00919
00920 }
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931 template<class BV>
00932 bm::id_t count_and(const BV& bv1, const BV& bv2)
00933 {
00934 distance_metric_descriptor dmd(bm::COUNT_AND);
00935
00936 distance_operation(bv1, bv2, &dmd, &dmd+1);
00937 return dmd.result;
00938 }
00939
00940
00941
00942
00943
00944
00945
00946
00947 template<class BV>
00948 bm::id_t any_and(const BV& bv1, const BV& bv2)
00949 {
00950 distance_metric_descriptor dmd(bm::COUNT_AND);
00951
00952 distance_operation_any(bv1, bv2, &dmd, &dmd+1);
00953 return dmd.result;
00954 }
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965 template<class BV>
00966 bm::id_t count_xor(const BV& bv1, const BV& bv2)
00967 {
00968 distance_metric_descriptor dmd(bm::COUNT_XOR);
00969
00970 distance_operation(bv1, bv2, &dmd, &dmd+1);
00971 return dmd.result;
00972 }
00973
00974
00975
00976
00977
00978
00979
00980
00981 template<class BV>
00982 bm::id_t any_xor(const BV& bv1, const BV& bv2)
00983 {
00984 distance_metric_descriptor dmd(bm::COUNT_XOR);
00985
00986 distance_operation_any(bv1, bv2, &dmd, &dmd+1);
00987 return dmd.result;
00988 }
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999 template<class BV>
01000 bm::id_t count_sub(const BV& bv1, const BV& bv2)
01001 {
01002 distance_metric_descriptor dmd(bm::COUNT_SUB_AB);
01003
01004 distance_operation(bv1, bv2, &dmd, &dmd+1);
01005 return dmd.result;
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016 template<class BV>
01017 bm::id_t any_sub(const BV& bv1, const BV& bv2)
01018 {
01019 distance_metric_descriptor dmd(bm::COUNT_SUB_AB);
01020
01021 distance_operation_any(bv1, bv2, &dmd, &dmd+1);
01022 return dmd.result;
01023 }
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033 template<class BV>
01034 bm::id_t count_or(const BV& bv1, const BV& bv2)
01035 {
01036 distance_metric_descriptor dmd(bm::COUNT_OR);
01037
01038 distance_operation(bv1, bv2, &dmd, &dmd+1);
01039 return dmd.result;
01040 }
01041
01042
01043
01044
01045
01046
01047
01048
01049 template<class BV>
01050 bm::id_t any_or(const BV& bv1, const BV& bv2)
01051 {
01052 distance_metric_descriptor dmd(bm::COUNT_OR);
01053
01054 distance_operation_any(bv1, bv2, &dmd, &dmd+1);
01055 return dmd.result;
01056 }
01057
01058
01059
01060
01061
01062
01063 template<class It>
01064 It block_range_scan(It first, It last, unsigned nblock, unsigned* max_id)
01065 {
01066 It right;
01067 for (right = first; right != last; ++right)
01068 {
01069 unsigned v = unsigned(*right);
01070 BM_ASSERT(v < bm::id_max);
01071 if (v >= *max_id)
01072 *max_id = v;
01073 unsigned nb = v >> bm::set_block_shift;
01074 if (nb != nblock)
01075 break;
01076 }
01077 return right;
01078 }
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093 template<class BV, class It>
01094 void combine_or(BV& bv, It first, It last)
01095 {
01096 typename BV::blocks_manager_type& bman = bv.get_blocks_manager();
01097 unsigned max_id = 0;
01098
01099 while (first < last)
01100 {
01101 unsigned nblock = unsigned((*first) >> bm::set_block_shift);
01102 It right = block_range_scan(first, last, nblock, &max_id);
01103
01104 if (max_id >= bv.size())
01105 {
01106 BM_ASSERT(max_id < bm::id_max);
01107 bv.resize(max_id + 1);
01108 }
01109
01110
01111
01112 label1:
01113
01114 int block_type;
01115 bm::word_t* blk =
01116 bman.check_allocate_block(nblock,
01117 true,
01118 bv.get_new_blocks_strat(),
01119 &block_type);
01120 if (!blk)
01121 continue;
01122
01123 if (block_type == 1)
01124 {
01125 bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
01126 unsigned threshold = bm::gap_limit(gap_blk, bman.glen());
01127
01128 for (; first < right; ++first)
01129 {
01130 unsigned is_set;
01131 unsigned nbit = (*first) & bm::set_block_mask;
01132
01133 unsigned new_block_len =
01134 gap_set_value(true, gap_blk, nbit, &is_set);
01135 if (new_block_len > threshold)
01136 {
01137 bman.extend_gap_block(nblock, gap_blk);
01138 ++first;
01139 goto label1;
01140 }
01141 }
01142 }
01143 else
01144 {
01145 for (; first < right; ++first)
01146 {
01147 unsigned nbit = unsigned(*first & bm::set_block_mask);
01148 unsigned nword = unsigned(nbit >> bm::set_word_shift);
01149 nbit &= bm::set_word_mask;
01150 blk[nword] |= (bm::word_t)1 << nbit;
01151 }
01152 }
01153 }
01154
01155 bv.forget_count();
01156 }
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172 template<class BV, class It>
01173 void combine_xor(BV& bv, It first, It last)
01174 {
01175 typename BV::blocks_manager_type& bman = bv.get_blocks_manager();
01176 unsigned max_id = 0;
01177
01178 while (first < last)
01179 {
01180 unsigned nblock = unsigned((*first) >> bm::set_block_shift);
01181 It right = block_range_scan(first, last, nblock, &max_id);
01182
01183 if (max_id >= bv.size())
01184 {
01185 BM_ASSERT(max_id < bm::id_max);
01186 bv.resize(max_id + 1);
01187 }
01188
01189
01190
01191 label1:
01192
01193 int block_type;
01194 bm::word_t* blk =
01195 bman.check_allocate_block(nblock,
01196 true,
01197 bv.get_new_blocks_strat(),
01198 &block_type,
01199 false );
01200 BM_ASSERT(blk);
01201
01202 if (block_type == 1)
01203 {
01204 bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
01205 unsigned threshold = bm::gap_limit(gap_blk, bman.glen());
01206
01207 for (; first < right; ++first)
01208 {
01209 unsigned is_set;
01210 unsigned nbit = (*first) & bm::set_block_mask;
01211
01212 is_set = gap_test(gap_blk, nbit);
01213 BM_ASSERT(is_set <= 1);
01214 is_set ^= 1;
01215
01216 unsigned new_block_len =
01217 gap_set_value(is_set, gap_blk, nbit, &is_set);
01218 if (new_block_len > threshold)
01219 {
01220 bman.extend_gap_block(nblock, gap_blk);
01221 ++first;
01222 goto label1;
01223 }
01224 }
01225 }
01226 else
01227 {
01228 for (; first < right; ++first)
01229 {
01230 unsigned nbit = unsigned(*first & bm::set_block_mask);
01231 unsigned nword = unsigned(nbit >> bm::set_word_shift);
01232 nbit &= bm::set_word_mask;
01233 blk[nword] ^= (bm::word_t)1 << nbit;
01234 }
01235 }
01236 }
01237
01238 bv.forget_count();
01239 }
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 template<class BV, class It>
01257 void combine_sub(BV& bv, It first, It last)
01258 {
01259 typename BV::blocks_manager_type& bman = bv.get_blocks_manager();
01260 unsigned max_id = 0;
01261
01262 while (first < last)
01263 {
01264 unsigned nblock = unsigned((*first) >> bm::set_block_shift);
01265 It right = block_range_scan(first, last, nblock, &max_id);
01266
01267 if (max_id >= bv.size())
01268 {
01269 BM_ASSERT(max_id < bm::id_max);
01270 bv.resize(max_id + 1);
01271 }
01272
01273
01274
01275 label1:
01276
01277 int block_type;
01278 bm::word_t* blk =
01279 bman.check_allocate_block(nblock,
01280 false,
01281 bv.get_new_blocks_strat(),
01282 &block_type);
01283
01284 if (!blk)
01285 continue;
01286
01287 if (block_type == 1)
01288 {
01289 bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
01290 unsigned threshold = bm::gap_limit(gap_blk, bman.glen());
01291
01292 for (; first < right; ++first)
01293 {
01294 unsigned is_set;
01295 unsigned nbit = (*first) & bm::set_block_mask;
01296
01297 is_set = gap_test(gap_blk, nbit);
01298 if (!is_set)
01299 continue;
01300
01301 unsigned new_block_len =
01302 gap_set_value(false, gap_blk, nbit, &is_set);
01303 if (new_block_len > threshold)
01304 {
01305 bman.extend_gap_block(nblock, gap_blk);
01306 ++first;
01307 goto label1;
01308 }
01309 }
01310 }
01311 else
01312 {
01313 for (; first < right; ++first)
01314 {
01315 unsigned nbit = unsigned(*first & bm::set_block_mask);
01316 unsigned nword = unsigned(nbit >> bm::set_word_shift);
01317 nbit &= bm::set_word_mask;
01318 blk[nword] &= ~((bm::word_t)1 << nbit);
01319 }
01320 }
01321 }
01322
01323 bv.forget_count();
01324 }
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338 template<class BV, class It>
01339 void combine_and_sorted(BV& bv, It first, It last)
01340 {
01341 bm::id_t prev = 0;
01342 for ( ;first < last; ++first)
01343 {
01344 bm::id_t id = *first;
01345 BM_ASSERT(id >= prev);
01346 bv.set_bit_and(id, true);
01347 if (++prev < id)
01348 {
01349 bv.set_range(prev, id-1, false);
01350 }
01351 prev = id;
01352 }
01353 }
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370 template<class BV, class It>
01371 void combine_and(BV& bv, It first, It last)
01372 {
01373 BV bv_tmp;
01374 combine_or(bv_tmp, first, last);
01375 bv &= bv_tmp;
01376 }
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393 template<class BV>
01394 bm::id_t count_intervals(const BV& bv)
01395 {
01396 const typename BV::blocks_manager_type& bman = bv.get_blocks_manager();
01397
01398 bm::word_t*** blk_root = bman.get_rootblock();
01399 typename BV::blocks_manager_type::block_count_change_func func(bman);
01400 for_each_block(blk_root, bman.top_block_size(), bm::set_array_size, func);
01401
01402 return func.count();
01403 }
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419 template<class BV, class It>
01420 void export_array(BV& bv, It first, It last)
01421 {
01422 typename BV::blocks_manager_type& bman = bv.get_blocks_manager();
01423 unsigned inp_word_size = sizeof(*first);
01424 size_t array_size = last - first;
01425 size_t bit_cnt = array_size * inp_word_size * 8;
01426 int block_type;
01427 bm::word_t tmp;
01428 unsigned b1, b2, b3, b4;
01429
01430 if (bit_cnt >= bv.size())
01431 bv.resize((bm::id_t)bit_cnt + 1);
01432 else
01433 bv.set_range((bm::id_t)bit_cnt, bv.size() - 1, false);
01434
01435 switch (inp_word_size)
01436 {
01437 case 1:
01438 {
01439 size_t word_cnt = array_size / 4;
01440 for (unsigned i = 0; i < bm::set_total_blocks; ++i)
01441 {
01442 bm::word_t* blk =
01443 bman.check_allocate_block(i,
01444 false,
01445 BM_BIT,
01446 &block_type,
01447 false );
01448 if (block_type == 1)
01449 {
01450 blk = bman.convert_gap2bitset(i, BMGAP_PTR(blk));
01451 }
01452
01453 bm::word_t* wrd_ptr = blk;
01454 if (word_cnt >= bm::set_block_size) {
01455 bm::word_t* wrd_end = blk + bm::set_block_size;
01456 do {
01457 b1 = *first++; b2 = *first++;
01458 b3 = *first++; b4 = *first++;
01459 tmp = b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
01460 *wrd_ptr++ = tmp;
01461 } while (wrd_ptr < wrd_end);
01462 word_cnt -= bm::set_block_size;
01463 }
01464 else
01465 {
01466 size_t to_convert = last - first;
01467 for (size_t j = 0; j < to_convert / 4; ++j)
01468 {
01469 b1 = *first++; b2 = *first++;
01470 b3 = *first++; b4 = *first++;
01471 tmp = b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
01472 *wrd_ptr++ = tmp;
01473 }
01474 while (1)
01475 {
01476 if (first == last) break;
01477 *wrd_ptr = *first++;
01478 if (first == last) break;
01479 *wrd_ptr |= (*first++) << 8;
01480 if (first == last) break;
01481 *wrd_ptr |= (*first++) << 16;
01482 if (first == last) break;
01483 *wrd_ptr |= (*first++) << 24;
01484 ++wrd_ptr;
01485 }
01486 }
01487 if (first == last) break;
01488 }
01489 }
01490 break;
01491 case 2:
01492 {
01493 size_t word_cnt = array_size / 2;
01494 for (unsigned i = 0; i < bm::set_total_blocks; ++i)
01495 {
01496 bm::word_t* blk =
01497 bman.check_allocate_block(i,
01498 false,
01499 BM_BIT,
01500 &block_type,
01501 false );
01502 if (block_type == 1)
01503 {
01504 blk = bman.convert_gap2bitset(i, BMGAP_PTR(blk));
01505 }
01506
01507 bm::word_t* wrd_ptr = blk;
01508 if (word_cnt >= bm::set_block_size) {
01509 bm::word_t* wrd_end = blk + bm::set_block_size;
01510 do {
01511 b1 = *first++; b2 = *first++;
01512 tmp = b1 | (b2 << 16);
01513 *wrd_ptr++ = tmp;
01514 } while (wrd_ptr < wrd_end);
01515 word_cnt -= bm::set_block_size;
01516 }
01517 else
01518 {
01519 size_t to_convert = last - first;
01520 for (unsigned j = 0; j < to_convert / 2; ++j)
01521 {
01522 b1 = *first++; b2 = *first++;
01523 tmp = b1 | (b2 << 16);
01524 *wrd_ptr++ = tmp;
01525 }
01526 while (1)
01527 {
01528 if (first == last) break;
01529 *wrd_ptr = *first++;
01530 if (first == last) break;
01531 *wrd_ptr |= (*first++) << 16;
01532 ++wrd_ptr;
01533 }
01534 }
01535 if (first == last) break;
01536 }
01537 }
01538 break;
01539 case 4:
01540 {
01541 size_t word_cnt = array_size;
01542 for (unsigned i = 0; i < bm::set_total_blocks; ++i)
01543 {
01544 bm::word_t* blk =
01545 bman.check_allocate_block(i,
01546 false,
01547 BM_BIT,
01548 &block_type,
01549 false );
01550 if (block_type == 1)
01551 {
01552 blk = bman.convert_gap2bitset(i, BMGAP_PTR(blk));
01553 }
01554
01555 bm::word_t* wrd_ptr = blk;
01556 if (word_cnt >= bm::set_block_size) {
01557 bm::word_t* wrd_end = blk + bm::set_block_size;
01558 do {
01559 *wrd_ptr++ = *first++;
01560 } while (wrd_ptr < wrd_end);
01561 word_cnt -= bm::set_block_size;
01562 }
01563 else
01564 {
01565 while (1)
01566 {
01567 if (first == last) break;
01568 *wrd_ptr = *first++;
01569 ++wrd_ptr;
01570 }
01571 }
01572 if (first == last) break;
01573 }
01574 }
01575 break;
01576 default:
01577 BM_ASSERT(0);
01578 }
01579
01580 }
01581
01582 }
01583
01584 #ifdef _MSC_VER
01585 #pragma warning( default : 4311 4312)
01586 #endif
01587
01588 #endif
01589
01590