bmalgo.h
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:25k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: bmalgo.h,v $
  4.  * PRODUCTION Revision 1000.0  2004/04/21 15:59:59  gouriano
  5.  * PRODUCTION PRODUCTION: IMPORTED [CATCHUP_003] Dev-tree R1.1
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*
  10. Copyright (c) 2003 Anatoliy Kuznetsov.
  11. Permission is hereby granted, free of charge, to any person 
  12. obtaining a copy of this software and associated documentation 
  13. files (the "Software"), to deal in the Software without restriction, 
  14. including without limitation the rights to use, copy, modify, merge, 
  15. publish, distribute, sublicense, and/or sell copies of the Software, 
  16. and to permit persons to whom the Software is furnished to do so, 
  17. subject to the following conditions:
  18. The above copyright notice and this permission notice shall be included 
  19. in all copies or substantial portions of the Software.
  20. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
  21. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
  22. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
  23. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
  24. DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
  25. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
  26. OTHER DEALINGS IN THE SOFTWARE.
  27. */
  28. #ifndef BMALGO__H__INCLUDED__
  29. #define BMALGO__H__INCLUDED__
  30. #include "bm.h"
  31. #include "bmfunc.h"
  32. #include "bmdef.h"
  33. namespace bm
  34. {
  35. /*! defgroup setalgo Set algorithms 
  36.  *  Set algorithms 
  37.  *
  38.  */
  39. /*! defgroup distance Distance metrics 
  40.  *  Algorithms to compute binary distance metrics
  41.  *  ingroup setalgo
  42.  */
  43. /*! 
  44.     brief    Distance metrics codes defined for vectors A and B
  45.     ingroup  distance
  46. */
  47. enum distance_metric
  48. {
  49.     COUNT_AND,       //!< (A & B).count()
  50.     COUNT_XOR,       //!< (A ^ B).count()
  51.     COUNT_OR,        //!< (A | B).count()
  52.     COUNT_SUB_AB,    //!< (A - B).count()
  53.     COUNT_SUB_BA,    //!< (B - A).count()
  54.     COUNT_A,         //!< A.count()
  55.     COUNT_B          //!< B.count()
  56. };
  57. /*! 
  58.     brief Distance metric descriptor, holds metric code and result.
  59.     sa distance_operation
  60. */
  61. struct distance_metric_descriptor
  62. {
  63.      distance_metric   metric;
  64.      bm::id_t          result;
  65.      
  66.      distance_metric_descriptor(distance_metric m)
  67.      : metric(m),
  68.        result(0)
  69.     {}
  70.     distance_metric_descriptor()
  71.     : metric(bm::COUNT_XOR),
  72.       result(0)
  73.     {}
  74.     
  75.     /*! 
  76.         brief Sets metric result to 0
  77.     */
  78.     void reset()
  79.     {
  80.         result = 0;
  81.     }
  82. };
  83. /*!
  84.     brief Internal function computes different distance metrics.
  85.     internal 
  86.     ingroup  distance
  87.      
  88. */
  89. inline
  90. void combine_count_operation_with_block(const bm::word_t* blk,
  91.                                         unsigned gap,
  92.                                         const bm::word_t* arg_blk,
  93.                                         int arg_gap,
  94.                                         bm::word_t* temp_blk,
  95.                                         distance_metric_descriptor* dmit,
  96.                                         distance_metric_descriptor* dmit_end)
  97.                                             
  98. {
  99.      gap_word_t* res=0;
  100.      
  101.      gap_word_t* g1 = BMGAP_PTR(blk);
  102.      gap_word_t* g2 = BMGAP_PTR(arg_blk);
  103.      
  104.      if (gap) // first block GAP-type
  105.      {
  106.          if (arg_gap)  // both blocks GAP-type
  107.          {
  108.              gap_word_t tmp_buf[bm::gap_max_buff_len * 3]; // temporary result
  109.              
  110.              for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
  111.              {
  112.                  distance_metric_descriptor& dmd = *it;
  113.                  
  114.                  switch (dmd.metric)
  115.                  {
  116.                  case bm::COUNT_AND:
  117.                      res = gap_operation_and(g1, g2, tmp_buf);
  118.                      break;
  119.                  case bm::COUNT_OR:
  120.                      res = gap_operation_or(g1, g2, tmp_buf);
  121.                      break;
  122.                  case bm::COUNT_SUB_AB:
  123.                      res = gap_operation_sub(g1, g2, tmp_buf); 
  124.                      break;
  125.                  case bm::COUNT_SUB_BA:
  126.                      res = gap_operation_sub(g2, g1, tmp_buf); 
  127.                      break;
  128.                  case bm::COUNT_XOR:
  129.                      res = gap_operation_xor(g1, g2, tmp_buf); 
  130.                     break;
  131.                  case bm::COUNT_A:
  132.                     res = g1;
  133.                     break;
  134.                  case bm::COUNT_B:
  135.                     res = g2;
  136.                     break;
  137.                  } // switch
  138.                  
  139.                  if (res)
  140.                      dmd.result += gap_bit_count(res);
  141.                     
  142.              } // for it
  143.              
  144.              return;
  145.          }
  146.          else // first block - GAP, argument - BITSET
  147.          {
  148.              for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
  149.              {
  150.                  distance_metric_descriptor& dmd = *it;
  151.                  
  152.                  switch (dmd.metric)
  153.                  {
  154.                  case bm::COUNT_AND:
  155.                      if (arg_blk)
  156.                         dmd.result += gap_bitset_and_count(arg_blk, g1);
  157.                      break;
  158.                  case bm::COUNT_OR:
  159.                      if (!arg_blk)
  160.                         dmd.result += gap_bit_count(g1);
  161.                      else
  162.                         dmd.result += gap_bitset_or_count(arg_blk, g1); 
  163.                      break;
  164.                  case bm::COUNT_SUB_AB:
  165.                      gap_convert_to_bitset((bm::word_t*) temp_blk, 
  166.                                            g1, bm::set_block_size);
  167.                      dmd.result += 
  168.                        bit_operation_sub_count((bm::word_t*)temp_blk, 
  169.                           ((bm::word_t*)temp_blk) + bm::set_block_size,
  170.                            arg_blk);
  171.                  
  172.                      break;
  173.                  case bm::COUNT_SUB_BA:
  174.                      dmd.metric = bm::COUNT_SUB_AB; // recursive call to SUB_AB
  175.                      combine_count_operation_with_block(arg_blk,
  176.                                                         arg_gap,
  177.                                                         blk,
  178.                                                         gap,
  179.                                                         temp_blk,
  180.                                                         it, it+1);
  181.                      dmd.metric = bm::COUNT_SUB_BA; // restore status quo
  182.                      break;
  183.                  case bm::COUNT_XOR:
  184.                      if (!arg_blk)
  185.                         dmd.result += gap_bit_count(g1);
  186.                      else
  187.                         dmd.result += gap_bitset_xor_count(arg_blk, g1);
  188.                      break;
  189.                  case bm::COUNT_A:
  190.                     if (g1)
  191.                         dmd.result += gap_bit_count(g1);
  192.                     break;
  193.                  case bm::COUNT_B:
  194.                     if (arg_blk)
  195.                     {
  196.                         dmd.result += 
  197.                           bit_block_calc_count(arg_blk, 
  198.                                                arg_blk + bm::set_block_size);
  199.                     }
  200.                     break;
  201.                  } // switch
  202.                                      
  203.              } // for it
  204.              
  205.              return;
  206.          
  207.          }
  208.      } 
  209.      else // first block is BITSET-type
  210.      {     
  211.          if (arg_gap) // second argument block is GAP-type
  212.          {
  213.              for (distance_metric_descriptor* it = dmit;it < dmit_end; ++it)
  214.              {
  215.                  distance_metric_descriptor& dmd = *it;
  216.                  
  217.                  switch (dmd.metric)
  218.                  {
  219.                  case bm::COUNT_AND:
  220.                      if (blk) 
  221.                         dmd.result += gap_bitset_and_count(blk, g2);                         
  222.                      break;
  223.                  case bm::COUNT_OR:
  224.                      if (!blk)
  225.                         dmd.result += gap_bit_count(g2);
  226.                      else
  227.                         dmd.result += gap_bitset_or_count(blk, g2);
  228.                      break;
  229.                  case bm::COUNT_SUB_AB:
  230.                      if (blk)
  231.                         dmd.result += gap_bitset_sub_count(blk, g2);
  232.                      break;
  233.                  case bm::COUNT_SUB_BA:
  234.                      dmd.metric = bm::COUNT_SUB_AB; // recursive call to SUB_AB
  235.                      combine_count_operation_with_block(arg_blk,
  236.                                                         arg_gap,
  237.                                                         blk,
  238.                                                         gap,
  239.                                                         temp_blk,
  240.                                                         it, it+1);
  241.                      dmd.metric = bm::COUNT_SUB_BA; // restore status quo
  242.                      break;
  243.                  case bm::COUNT_XOR:
  244.                      if (!blk)
  245.                         dmd.result += gap_bit_count(g2);
  246.                      else
  247.                         dmd.result += gap_bitset_xor_count(blk, g2); 
  248.                     break;
  249.                  case bm::COUNT_A:
  250.                     if (blk)
  251.                     {
  252.                         dmd.result += 
  253.                             bit_block_calc_count(blk, 
  254.                                                  blk + bm::set_block_size);
  255.                     }
  256.                     break;
  257.                  case bm::COUNT_B:
  258.                     if (g2)
  259.                         dmd.result += gap_bit_count(g2);
  260.                     break;
  261.                  } // switch
  262.                                      
  263.              } // for it
  264.              
  265.              return;
  266.          }
  267.      }
  268.      // --------------------------------------------
  269.      //
  270.      // Here we combine two plain bitblocks 
  271.      const bm::word_t* blk_end;
  272.      const bm::word_t* arg_end;
  273.      blk_end = blk + (bm::set_block_size);
  274.      arg_end = arg_blk + (bm::set_block_size);
  275.      for (distance_metric_descriptor* it = dmit; it < dmit_end; ++it)
  276.      {
  277.          distance_metric_descriptor& dmd = *it;
  278.          switch (dmd.metric)
  279.          {
  280.          case bm::COUNT_AND:
  281.              dmd.result += 
  282.                 bit_operation_and_count(blk, blk_end, arg_blk);
  283.              break;
  284.          case bm::COUNT_OR:
  285.              dmd.result += 
  286.                 bit_operation_or_count(blk, blk_end, arg_blk);
  287.              break;
  288.          case bm::COUNT_SUB_AB:
  289.              dmd.result += 
  290.                 bit_operation_sub_count(blk, blk_end, arg_blk);
  291.              break;
  292.          case bm::COUNT_SUB_BA:
  293.              dmd.result += 
  294.                 bit_operation_sub_count(arg_blk, arg_end, blk);
  295.              break;
  296.          case bm::COUNT_XOR:
  297.              dmd.result += 
  298.                 bit_operation_xor_count(blk, blk_end, arg_blk);
  299.              break;
  300.          case bm::COUNT_A:
  301.             if (blk)
  302.                 dmd.result += bit_block_calc_count(blk, blk_end);
  303.             break;
  304.          case bm::COUNT_B:
  305.             if (arg_blk)
  306.                 dmd.result += bit_block_calc_count(arg_blk, arg_end);
  307.             break;
  308.          } // switch
  309.      } // for it
  310.      
  311.      
  312. }
  313. /*!
  314.     brief Distance computing template function.
  315.     Function receives two bitvectors and an array of distance metrics
  316.     (metrics pipeline). Function computes all metrics saves result into
  317.     corresponding pipeline results (distance_metric_descriptor::result)
  318.     An important detail is that function reuses metric descriptors, 
  319.     incrementing received values. It allows you to accumulate results 
  320.     from different calls in the pipeline.
  321.     
  322.     param bv1      - argument bitvector 1 (A)
  323.     param bv2      - argument bitvector 2 (B)
  324.     param dmit     - pointer to first element of metric descriptors array
  325.                       Input-Output parameter, receives metric code as input,
  326.                       computation is added to "result" field
  327.     param dmit_end - pointer to (last+1) element of metric descriptors array
  328.     ingroup  distance
  329.     
  330. */
  331. template<class BV>
  332. void distance_operation(const BV& bv1, 
  333.                         const BV& bv2, 
  334.                         distance_metric_descriptor* dmit,
  335.                         distance_metric_descriptor* dmit_end)
  336. {
  337.     const typename BV::blocks_manager& bman1 = bv1.get_blocks_manager();
  338.     const typename BV::blocks_manager& bman2 = bv2.get_blocks_manager();
  339.     
  340.     bm::word_t* temp_blk = 0;
  341.     
  342.     {
  343.         for (distance_metric_descriptor* it = dmit; it < dmit_end; ++it)
  344.         {
  345.             if (it->metric == bm::COUNT_SUB_AB || 
  346.                 it->metric == bm::COUNT_SUB_BA)
  347.             {
  348.                 temp_blk = BV::allocate_tempblock();
  349.                 break;
  350.             }
  351.         }
  352.     }
  353.     
  354.   
  355.     bm::word_t*** blk_root = bman1.get_rootblock();
  356.     unsigned block_idx = 0;
  357.     unsigned i, j;
  358.     
  359.     const bm::word_t* blk;
  360.     const bm::word_t* arg_blk;
  361.     bool  blk_gap;
  362.     bool  arg_gap;
  363.     BM_SET_MMX_GUARD
  364.     for (i = 0; i < bman1.top_block_size(); ++i)
  365.     {
  366.         bm::word_t** blk_blk = blk_root[i];
  367.         if (blk_blk == 0) // not allocated
  368.         {
  369.             const bm::word_t* const* bvbb = bman2.get_topblock(i);
  370.             if (bvbb == 0) 
  371.             {
  372.                 block_idx += bm::set_array_size;
  373.                 continue;
  374.             }
  375.             blk = 0;
  376.             blk_gap = false;
  377.             for (j = 0; j < bm::set_array_size; ++j,++block_idx)
  378.             {                
  379.                 arg_blk = bman2.get_block(i, j);
  380.                 arg_gap = BM_IS_GAP(bman2, arg_blk, block_idx);
  381.                 if (!arg_blk) 
  382.                     continue;
  383.                 combine_count_operation_with_block(blk, blk_gap,
  384.                                                    arg_blk, arg_gap,
  385.                                                    temp_blk,
  386.                                                    dmit, dmit_end);
  387.             } // for j
  388.             continue;
  389.         }
  390.         for (j = 0; j < bm::set_array_size; ++j, ++block_idx)
  391.         {
  392.             blk = blk_blk[j];
  393.             arg_blk = bman2.get_block(i, j);
  394.             if (blk == 0 && arg_blk == 0)
  395.                 continue;
  396.                 
  397.             arg_gap = BM_IS_GAP(bman2, arg_blk, block_idx);
  398.             blk_gap = BM_IS_GAP(bman1, blk, block_idx);
  399.             
  400.             combine_count_operation_with_block(blk, blk_gap,
  401.                                                arg_blk, arg_gap,
  402.                                                temp_blk,
  403.                                                dmit, dmit_end);
  404.             
  405.         } // for j
  406.     } // for i
  407.     
  408.     if (temp_blk)
  409.     {
  410.         BV::free_tempblock(temp_blk);
  411.     }
  412. }
  413. /*!
  414.    brief Computes bitcount of AND operation of two bitsets
  415.    param bv1 - Argument bit-vector.
  416.    param bv2 - Argument bit-vector.
  417.    return bitcount of the result
  418.    ingroup  distance
  419. */
  420. template<class BV>
  421. bm::id_t count_and(const BV& bv1, const BV& bv2)
  422. {
  423.     distance_metric_descriptor dmd(bm::COUNT_AND);
  424.     
  425.     distance_operation(bv1, bv2, &dmd, &dmd+1);
  426.     return dmd.result;
  427. }
  428. /*!
  429.    brief Computes bitcount of XOR operation of two bitsets
  430.    param bv1 - Argument bit-vector.
  431.    param bv2 - Argument bit-vector.
  432.    return bitcount of the result
  433.    ingroup  distance
  434. */
  435. template<class BV>
  436. bm::id_t count_xor(const BV& bv1, const BV& bv2)
  437. {
  438.     distance_metric_descriptor dmd(bm::COUNT_XOR);
  439.     
  440.     distance_operation(bv1, bv2, &dmd, &dmd+1);
  441.     return dmd.result;
  442. }
  443. /*!
  444.    brief Computes bitcount of SUB operation of two bitsets
  445.    param bv1 - Argument bit-vector.
  446.    param bv2 - Argument bit-vector.
  447.    return bitcount of the result
  448.    ingroup  distance
  449. */
  450. template<class BV>
  451. bm::id_t count_sub(const BV& bv1, const BV& bv2)
  452. {
  453.     distance_metric_descriptor dmd(bm::COUNT_SUB_AB);
  454.     
  455.     distance_operation(bv1, bv2, &dmd, &dmd+1);
  456.     return dmd.result;
  457. }
  458. /*!    
  459.    brief Computes bitcount of OR operation of two bitsets
  460.    param bv1 - Argument bit-vector.
  461.    param bv2 - Argument bit-vector.
  462.    return bitcount of the result
  463.    ingroup  distance
  464. */
  465. template<class BV>
  466. bm::id_t count_or(const BV& bv1, const BV& bv2)
  467. {
  468.     distance_metric_descriptor dmd(bm::COUNT_OR);
  469.     
  470.     distance_operation(bv1, bv2, &dmd, &dmd+1);
  471.     return dmd.result;
  472. }
  473. /**
  474.     brief Internal algorithms scans the input for the block range limit
  475.     internal
  476. */
  477. template<class It>
  478. It block_range_scan(It  first, It last, unsigned nblock)
  479. {
  480.     It right;
  481.     for (right = first; right != last; ++right)
  482.     {
  483.         unsigned nb = unsigned((*right) >> bm::set_block_shift);
  484.         if (nb != nblock)
  485.             break;
  486.     }
  487.     return right;
  488. }
  489. /**
  490.     brief OR Combine bitvector and the iterable sequence 
  491.     Algorithm combines bvector with sequence of integers 
  492.     (represents another set). When the agrument set is sorted 
  493.     this method can give serious increase in performance.
  494.     
  495.     param bv     - destination bitvector
  496.     param first  - first element of the iterated sequence
  497.     param last   - last element of the iterated sequence
  498.     
  499.     ingroup setalgo
  500. */
  501. template<class BV, class It>
  502. void combine_or(BV& bv, It  first, It last)
  503. {
  504.     typename BV::blocks_manager& bman = bv.get_blocks_manager();
  505.     while (first < last)
  506.     {
  507.         unsigned nblock = unsigned((*first) >> bm::set_block_shift);     
  508.         It right = block_range_scan(first, last, nblock);
  509.         // now we have one in-block array of bits to set
  510.         
  511.         label1:
  512.         
  513.         int block_type;
  514.         bm::word_t* blk = 
  515.             bman.check_allocate_block(nblock, 
  516.                                       true, 
  517.                                       bv.get_new_blocks_strat(), 
  518.                                       &block_type);
  519.         if (!blk) 
  520.             continue;
  521.                         
  522.         if (block_type == 1) // gap
  523.         {            
  524.             bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
  525.             unsigned threshold = bm::gap_limit(gap_blk, bman.glen());
  526.             
  527.             for (; first < right; ++first)
  528.             {
  529.                 unsigned is_set;
  530.                 unsigned nbit   = (*first) & bm::set_block_mask; 
  531.                 
  532.                 unsigned new_block_len =
  533.                     gap_set_value(true, gap_blk, nbit, &is_set);
  534.                 if (new_block_len > threshold) 
  535.                 {
  536.                     bman.extend_gap_block(nblock, gap_blk);
  537.                     ++first;
  538.                     goto label1;  // block pointer changed - goto reset
  539.                 }
  540.             }
  541.         }
  542.         else // bit block
  543.         {
  544.             for (; first < right; ++first)
  545.             {
  546.                 unsigned nbit   = unsigned(*first & bm::set_block_mask); 
  547.                 unsigned nword  = unsigned(nbit >> bm::set_word_shift); 
  548.                 nbit &= bm::set_word_mask;
  549.                 blk[nword] |= (bm::word_t)1 << nbit;
  550.             } // for
  551.         }
  552.     } // while
  553.     
  554.     bv.forget_count();
  555. }
  556. /**
  557.     brief XOR Combine bitvector and the iterable sequence 
  558.     Algorithm combines bvector with sequence of integers 
  559.     (represents another set). When the agrument set is sorted 
  560.     this method can give serious increase in performance.
  561.     
  562.     param bv     - destination bitvector
  563.     param first  - first element of the iterated sequence
  564.     param last   - last element of the iterated sequence
  565.     
  566.     ingroup setalgo
  567. */
  568. template<class BV, class It>
  569. void combine_xor(BV& bv, It  first, It last)
  570. {
  571.     typename BV::blocks_manager& bman = bv.get_blocks_manager();
  572.     while (first < last)
  573.     {
  574.         unsigned nblock = unsigned((*first) >> bm::set_block_shift);     
  575.         It right = block_range_scan(first, last, nblock);
  576.         // now we have one in-block array of bits to set
  577.         
  578.         label1:
  579.         
  580.         int block_type;
  581.         bm::word_t* blk = 
  582.             bman.check_allocate_block(nblock, 
  583.                                       true, 
  584.                                       bv.get_new_blocks_strat(), 
  585.                                       &block_type,
  586.                                       false /* no null return */);
  587.         BM_ASSERT(blk); 
  588.                         
  589.         if (block_type == 1) // gap
  590.         {
  591.             bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
  592.             unsigned threshold = bm::gap_limit(gap_blk, bman.glen());
  593.             
  594.             for (; first < right; ++first)
  595.             {
  596.                 unsigned is_set;
  597.                 unsigned nbit   = (*first) & bm::set_block_mask; 
  598.                 
  599.                 is_set = gap_test(gap_blk, nbit);
  600.                 BM_ASSERT(is_set <= 1);
  601.                 is_set ^= 1; 
  602.                 
  603.                 unsigned new_block_len =
  604.                     gap_set_value(is_set, gap_blk, nbit, &is_set);
  605.                 if (new_block_len > threshold) 
  606.                 {
  607.                     bman.extend_gap_block(nblock, gap_blk);
  608.                     ++first;
  609.                     goto label1;  // block pointer changed - goto reset
  610.                 }
  611.             }
  612.         }
  613.         else // bit block
  614.         {
  615.             for (; first < right; ++first)
  616.             {
  617.                 unsigned nbit   = unsigned(*first & bm::set_block_mask); 
  618.                 unsigned nword  = unsigned(nbit >> bm::set_word_shift); 
  619.                 nbit &= bm::set_word_mask;
  620.                 blk[nword] ^= (bm::word_t)1 << nbit;
  621.             } // for
  622.         }
  623.     } // while
  624.     
  625.     bv.forget_count();
  626. }
  627. /**
  628.     brief SUB Combine bitvector and the iterable sequence 
  629.     Algorithm combines bvector with sequence of integers 
  630.     (represents another set). When the agrument set is sorted 
  631.     this method can give serious increase in performance.
  632.     
  633.     param bv     - destination bitvector
  634.     param first  - first element of the iterated sequence
  635.     param last   - last element of the iterated sequence
  636.     
  637.     ingroup setalgo
  638. */
  639. template<class BV, class It>
  640. void combine_sub(BV& bv, It  first, It last)
  641. {
  642.     typename BV::blocks_manager& bman = bv.get_blocks_manager();
  643.     while (first < last)
  644.     {
  645.         unsigned nblock = unsigned((*first) >> bm::set_block_shift);     
  646.         It right = block_range_scan(first, last, nblock);
  647.         // now we have one in-block array of bits to set
  648.         
  649.         label1:
  650.         
  651.         int block_type;
  652.         bm::word_t* blk = 
  653.             bman.check_allocate_block(nblock, 
  654.                                       false, 
  655.                                       bv.get_new_blocks_strat(), 
  656.                                       &block_type);
  657.         if (!blk)
  658.             continue;
  659.                         
  660.         if (block_type == 1) // gap
  661.         {
  662.             bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
  663.             unsigned threshold = bm::gap_limit(gap_blk, bman.glen());
  664.             
  665.             for (; first < right; ++first)
  666.             {
  667.                 unsigned is_set;
  668.                 unsigned nbit   = (*first) & bm::set_block_mask; 
  669.                 
  670.                 is_set = gap_test(gap_blk, nbit);
  671.                 if (!is_set)
  672.                     continue;
  673.                 
  674.                 unsigned new_block_len =
  675.                     gap_set_value(false, gap_blk, nbit, &is_set);
  676.                 if (new_block_len > threshold) 
  677.                 {
  678.                     bman.extend_gap_block(nblock, gap_blk);
  679.                     ++first;
  680.                     goto label1;  // block pointer changed - goto reset
  681.                 }
  682.             }
  683.         }
  684.         else // bit block
  685.         {
  686.             for (; first < right; ++first)
  687.             {
  688.                 unsigned nbit   = unsigned(*first & bm::set_block_mask); 
  689.                 unsigned nword  = unsigned(nbit >> bm::set_word_shift); 
  690.                 nbit &= bm::set_word_mask;
  691.                 blk[nword] &= ~((bm::word_t)1 << nbit);
  692.             } // for
  693.         }
  694.     } // while
  695.     
  696.     bv.forget_count();
  697. }
  698. /**
  699.     brief AND Combine bitvector and the iterable sequence 
  700.     Algorithm combines bvector with sequence of integers 
  701.     (represents another set). When the agrument set is sorted 
  702.     this method can give serious increase in performance.
  703.     
  704.     param bv     - destination bitvector
  705.     param first  - first element of the iterated sequence
  706.     param last   - last element of the iterated sequence
  707.     
  708.     ingroup setalgo
  709. */
  710. template<class BV, class It>
  711. void combine_and(BV& bv, It  first, It last)
  712. {
  713.     BV bv_tmp;
  714.     combine_or(bv_tmp, first, last);
  715.     bv &= bv_tmp;
  716. }
  717. /*!
  718.     brief Compute number of bit intervals (GAPs) in the bitvector
  719.     
  720.     Algorithm traverses bit vector and count number of uninterrupted
  721.     intervals of 1s and 0s.
  722.     <pre>
  723.     For example: 
  724.       00001111100000 - gives us 3 intervals
  725.       10001111100000 - 4 intervals
  726.       00000000000000 - 1 interval
  727.       11111111111111 - 1 interval
  728.     </pre>
  729.     return Number of intervals
  730.     ingroup setalgo
  731. */
  732. template<class BV>
  733. bm::id_t count_intervals(const BV& bv)
  734. {
  735.     const typename BV::blocks_manager& bman = bv.get_blocks_manager();
  736.     bm::word_t*** blk_root = bman.get_rootblock();
  737.     typename BV::blocks_manager::block_count_change_func func(bman);
  738.     for_each_block(blk_root, bman.top_block_size(), bm::set_array_size, func);
  739.     return func.count();        
  740. }
  741. } // namespace bm
  742. #include "bmundef.h"
  743. #endif