include/util/bitset/bmalgo_impl.h

Go to the documentation of this file.
00001 /*
00002 Copyright(c) 2002-2005 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
00003 
00004 Permission is hereby granted, free of charge, to any person 
00005 obtaining a copy of this software and associated documentation 
00006 files (the "Software"), to deal in the Software without restriction, 
00007 including without limitation the rights to use, copy, modify, merge, 
00008 publish, distribute, sublicense, and/or sell copies of the Software, 
00009 and to permit persons to whom the Software is furnished to do so, 
00010 subject to the following conditions:
00011 
00012 The above copyright notice and this permission notice shall be included 
00013 in all copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
00016 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
00017 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
00018 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
00019 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
00020 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
00021 OTHER DEALINGS IN THE SOFTWARE.
00022 
00023 For more information please visit:  http://bmagic.sourceforge.net
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 /*! \defgroup setalgo Set algorithms 
00039  *  Set algorithms 
00040  *  \ingroup bmagic
00041  */
00042 
00043 /*! \defgroup distance Distance metrics 
00044  *  Algorithms to compute binary distance metrics
00045  *  \ingroup setalgo
00046  */
00047 
00048 
00049 /*! 
00050     \brief    Distance metrics codes defined for vectors A and B
00051     \ingroup  distance
00052 */
00053 enum distance_metric
00054 {
00055     COUNT_AND = set_COUNT_AND,          //!< (A & B).count()
00056     COUNT_XOR = set_COUNT_XOR,          //!< (A ^ B).count()
00057     COUNT_OR  = set_COUNT_OR,           //!< (A | B).count()
00058     COUNT_SUB_AB = set_COUNT_SUB_AB,    //!< (A - B).count()
00059     COUNT_SUB_BA = set_COUNT_SUB_BA,    //!< (B - A).count()
00060     COUNT_A      = set_COUNT_A,         //!< A.count()
00061     COUNT_B      = set_COUNT_B          //!< B.count()
00062 };
00063 
00064 /**
00065     Convert set operation into compatible distance metric
00066     \ingroup  distance
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     // distance metric is created as a set operation sub-class
00074     // simple cast will work to convert
00075     return (distance_metric) op;
00076 }
00077 
00078 /*! 
00079     \brief Distance metric descriptor, holds metric code and result.
00080     \sa distance_operation
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         \brief Sets metric result to 0
00099     */
00100     void reset()
00101     {
00102         result = 0;
00103     }
00104 };
00105 
00106 
00107 /*!
00108     \brief Internal function computes different distance metrics.
00109     \internal 
00110     \ingroup  distance
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) // first block GAP-type
00129      {
00130          if (arg_gap)  // both blocks GAP-type
00131          {
00132              gap_word_t tmp_buf[bm::gap_max_buff_len * 3]; // temporary result
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                  } // switch
00162                  
00163                  if (res)
00164                      dmd.result += gap_bit_count(res);
00165                     
00166              } // for it
00167              
00168              return;
00169 
00170          }
00171          else // first block - GAP, argument - BITSET
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; // recursive call to 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; // restore status quo
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                  } // switch
00226                                      
00227              } // for it
00228              
00229              return;
00230          
00231          }
00232      } 
00233      else // first block is BITSET-type
00234      {     
00235          if (arg_gap) // second argument block is GAP-type
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; // recursive call to 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; // restore status quo
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                  } // switch
00286                                      
00287              } // for it
00288              
00289              return;
00290          }
00291      }
00292 
00293      // --------------------------------------------
00294      //
00295      // Here we combine two plain bitblocks 
00296 
00297      const bm::word_t* blk_end;
00298      //const bm::word_t* arg_end;
00299 
00300      blk_end = blk + (bm::set_block_size);
00301      //arg_end = arg_blk + (bm::set_block_size);
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             case bm::COUNT_AND:
00319                 dmd.result += 
00320                     bit_operation_and_count(blk, blk_end, arg_blk);
00321                 break;
00322             case bm::COUNT_OR:
00323                 dmd.result += 
00324                     bit_operation_or_count(blk, blk_end, arg_blk);
00325                 break;
00326             case bm::COUNT_SUB_AB:
00327                 dmd.result += 
00328                     bit_operation_sub_count(blk, blk_end, arg_blk);
00329                 break;
00330             case bm::COUNT_XOR:
00331                 dmd.result += 
00332                     bit_operation_xor_count(blk, blk_end, arg_blk);
00333                 break;
00334             case bm::COUNT_SUB_BA:
00335                 dmd.result += 
00336                     bit_operation_sub_count(arg_blk, arg_end, blk);
00337                 break;
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             } // switch
00352         }
00353 
00354      } // for it
00355 }
00356 
00357 /*!
00358     \brief Internal function computes different existense of distance metric.
00359     \internal 
00360     \ingroup  distance
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) // first block GAP-type
00378      {
00379          if (arg_gap)  // both blocks GAP-type
00380          {
00381              gap_word_t tmp_buf[bm::gap_max_buff_len * 3]; // temporary result
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                  } // switch
00415                 if (res)
00416                     dmd.result += !gap_is_all_zero(res, bm::gap_max_bits);
00417                                      
00418              } // for it
00419              
00420              return;
00421 
00422          }
00423          else // first block - GAP, argument - BITSET
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; // recursive call to 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; // restore status quo
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                  } // switch
00482                                      
00483              } // for it
00484              
00485              return;
00486          
00487          }
00488      } 
00489      else // first block is BITSET-type
00490      {     
00491          if (arg_gap) // second argument block is GAP-type
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; // recursive call to 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; // restore status quo
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                  } // switch
00545                                      
00546              } // for it
00547              
00548              return;
00549          }
00550      }
00551 
00552      // --------------------------------------------
00553      //
00554      // Here we combine two plain bitblocks 
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         } // switch
00601 
00602      } // for it
00603 }
00604 
00605 
00606 
00607 /*!
00608     Convenience internal function to compute combine count for one metric
00609     \internal
00610     \ingroup  distance
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     Convenience internal function to compute combine any for one metric
00631     \internal
00632     \ingroup  distance
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     \brief Distance computing template function.
00653 
00654     Function receives two bitvectors and an array of distance metrics
00655     (metrics pipeline). Function computes all metrics saves result into
00656     corresponding pipeline results (distance_metric_descriptor::result)
00657     An important detail is that function reuses metric descriptors, 
00658     incrementing received values. It allows you to accumulate results 
00659     from different calls in the pipeline.
00660     
00661     \param bv1      - argument bitvector 1 (A)
00662     \param bv2      - argument bitvector 2 (B)
00663     \param dmit     - pointer to first element of metric descriptors array
00664                       Input-Output parameter, receives metric code as input,
00665                       computation is added to "result" field
00666     \param dmit_end - pointer to (last+1) element of metric descriptors array
00667     \ingroup  distance
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) // not allocated
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             } // for j
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         } // for j
00760 
00761     } // for i
00762     
00763     if (temp_blk)
00764     {
00765         bv1.free_tempblock(temp_blk);
00766     }
00767 
00768 }
00769 
00770 
00771 
00772 /*!
00773     \brief Distance screening template function.
00774 
00775     Function receives two bitvectors and an array of distance metrics
00776     (metrics pipeline). Function computes possybility of a metric(any bit) 
00777     saves result into corresponding pipeline results 
00778     (distance_metric_descriptor::result)
00779     An important detail is that function reuses metric descriptors, 
00780     incrementing received values. It allows you to accumulate results 
00781     from different calls in the pipeline.
00782     
00783     \param bv1      - argument bitvector 1 (A)
00784     \param bv2      - argument bitvector 2 (B)
00785     \param dmit     - pointer to first element of metric descriptors array
00786                       Input-Output parameter, receives metric code as input,
00787                       computation is added to "result" field
00788     \param dmit_end - pointer to (last+1) element of metric descriptors array
00789     \ingroup  distance
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) // not allocated
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                 // check if all distance requests alredy resolved
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             } // for j
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             // check if all distance requests alredy resolved
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         } // for j
00912 
00913     } // for i
00914 return_proc:    
00915     if (temp_blk)
00916     {
00917         bv1.free_tempblock(temp_blk);
00918     }
00919 
00920 }
00921 
00922 
00923 
00924 /*!
00925    \brief Computes bitcount of AND operation of two bitsets
00926    \param bv1 - Argument bit-vector.
00927    \param bv2 - Argument bit-vector.
00928    \return bitcount of the result
00929    \ingroup  distance
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    \brief Computes if there is any bit in AND operation of two bitsets
00942    \param bv1 - Argument bit-vector.
00943    \param bv2 - Argument bit-vector.
00944    \return non zero value if there is any bit
00945    \ingroup  distance
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    \brief Computes bitcount of XOR operation of two bitsets
00960    \param bv1 - Argument bit-vector.
00961    \param bv2 - Argument bit-vector.
00962    \return bitcount of the result
00963    \ingroup  distance
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    \brief Computes if there is any bit in XOR operation of two bitsets
00976    \param bv1 - Argument bit-vector.
00977    \param bv2 - Argument bit-vector.
00978    \return non zero value if there is any bit
00979    \ingroup  distance
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    \brief Computes bitcount of SUB operation of two bitsets
00994    \param bv1 - Argument bit-vector.
00995    \param bv2 - Argument bit-vector.
00996    \return bitcount of the result
00997    \ingroup  distance
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    \brief Computes if there is any bit in SUB operation of two bitsets
01011    \param bv1 - Argument bit-vector.
01012    \param bv2 - Argument bit-vector.
01013    \return non zero value if there is any bit
01014    \ingroup  distance
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    \brief Computes bitcount of OR operation of two bitsets
01028    \param bv1 - Argument bit-vector.
01029    \param bv2 - Argument bit-vector.
01030    \return bitcount of the result
01031    \ingroup  distance
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    \brief Computes if there is any bit in OR operation of two bitsets
01044    \param bv1 - Argument bit-vector.
01045    \param bv2 - Argument bit-vector.
01046    \return non zero value if there is any bit
01047    \ingroup  distance
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     \brief Internal algorithms scans the input for the block range limit
01061     \internal
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     \brief OR Combine bitvector and the iterable sequence 
01082 
01083     Algorithm combines bvector with sequence of integers 
01084     (represents another set). When the agrument set is sorted 
01085     this method can give serious increase in performance.
01086     
01087     \param bv     - destination bitvector
01088     \param first  - first element of the iterated sequence
01089     \param last   - last element of the iterated sequence
01090     
01091     \ingroup setalgo
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         // now we have one in-block array of bits to set
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) // gap
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;  // block pointer changed - goto reset
01140                 }
01141             }
01142         }
01143         else // bit block
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             } // for
01152         }
01153     } // while
01154     
01155     bv.forget_count();
01156 }
01157 
01158 
01159 /**
01160     \brief XOR Combine bitvector and the iterable sequence 
01161 
01162     Algorithm combines bvector with sequence of integers 
01163     (represents another set). When the agrument set is sorted 
01164     this method can give serious increase in performance.
01165     
01166     \param bv     - destination bitvector
01167     \param first  - first element of the iterated sequence
01168     \param last   - last element of the iterated sequence
01169     
01170     \ingroup setalgo
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         // now we have one in-block array of bits to set
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 /* no null return */);
01200         BM_ASSERT(blk); 
01201                         
01202         if (block_type == 1) // gap
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;  // block pointer changed - goto reset
01223                 }
01224             }
01225         }
01226         else // bit block
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             } // for
01235         }
01236     } // while
01237     
01238     bv.forget_count();
01239 }
01240 
01241 
01242 
01243 /**
01244     \brief SUB Combine bitvector and the iterable sequence 
01245 
01246     Algorithm combines bvector with sequence of integers 
01247     (represents another set). When the agrument set is sorted 
01248     this method can give serious increase in performance.
01249     
01250     \param bv     - destination bitvector
01251     \param first  - first element of the iterated sequence
01252     \param last   - last element of the iterated sequence
01253     
01254     \ingroup setalgo
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         // now we have one in-block array of bits to set
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) // gap
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;  // block pointer changed - goto reset
01308                 }
01309             }
01310         }
01311         else // bit block
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             } // for
01320         }
01321     } // while
01322     
01323     bv.forget_count();
01324 }
01325 
01326 /**
01327     \brief AND Combine bitvector and the iterable sequence 
01328 
01329     Algorithm combines bvector with sorted sequence of integers 
01330     (represents another set).
01331     
01332     \param bv     - destination bitvector
01333     \param first  - first element of the iterated sequence
01334     \param last   - last element of the iterated sequence
01335     
01336     \ingroup setalgo
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); // make sure it's sorted
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     \brief AND Combine bitvector and the iterable sequence 
01358 
01359     Algorithm combines bvector with sequence of integers 
01360     (represents another set). When the agrument set is sorted 
01361     this method can give serious increase in performance.
01362     
01363     \param bv     - destination bitvector
01364     \param first  - first element of the iterated sequence
01365     \param last   - last element of the iterated sequence
01366     
01367     \ingroup setalgo
01368     \sa combine_and_sorted
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     \brief Compute number of bit intervals (GAPs) in the bitvector
01380     
01381     Algorithm traverses bit vector and count number of uninterrupted
01382     intervals of 1s and 0s.
01383     <pre>
01384     For example: 
01385       00001111100000 - gives us 3 intervals
01386       10001111100000 - 4 intervals
01387       00000000000000 - 1 interval
01388       11111111111111 - 1 interval
01389     </pre>
01390     \return Number of intervals
01391     \ingroup setalgo
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     \brief Export bitset from an array of binary data representing
01407     the bit vector. 
01408 
01409     Input array can be array of ints, chars or other native C types.
01410     Method works with iterators, which makes it compatible with 
01411     STL containers and C arrays
01412 
01413     \param bv     - destination bitvector
01414     \param first  - first element of the iterated sequence
01415     \param last   - last element of the iterated sequence
01416 
01417     \ingroup setalgo
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 /*no NULL ret*/);
01448                 if (block_type == 1) // gap
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             } // for
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 /*no NULL ret*/);
01502                 if (block_type == 1) // gap
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             } // for
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 /*no NULL ret*/);
01550                 if (block_type == 1) // gap
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             } // for
01574         }
01575         break;
01576     default:
01577         BM_ASSERT(0);
01578     } // switch
01579 
01580 }
01581 
01582 } // namespace bm
01583 
01584 #ifdef _MSC_VER
01585 #pragma warning( default : 4311 4312)
01586 #endif
01587 
01588 #endif
01589 
01590 

Generated on Sun Nov 8 22:18:49 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Mon Nov 09 15:45:16 2009 by modify_doxy.py rev. 173732