dlvhex  2.5.0
vs10/bm/bm.h
Go to the documentation of this file.
00001 #ifndef BM__H__INCLUDED__
00002 #define BM__H__INCLUDED__
00003 /*
00004 Copyright(c) 2002-2010 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
00005 
00006 Permission is hereby granted, free of charge, to any person 
00007 obtaining a copy of this software and associated documentation 
00008 files (the "Software"), to deal in the Software without restriction, 
00009 including without limitation the rights to use, copy, modify, merge, 
00010 publish, distribute, sublicense, and/or sell copies of the Software, 
00011 and to permit persons to whom the Software is furnished to do so, 
00012 subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included 
00015 in all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
00018 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
00019 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
00020 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
00021 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
00022 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
00023 OTHER DEALINGS IN THE SOFTWARE.
00024 
00025 For more information please visit:  http://bmagic.sourceforge.net
00026 
00027 */
00028 
00029 
00030 // define BM_NO_STL if you use BM in "STL free" environment and want
00031 // to disable any references to STL headers
00032 #ifndef BM_NO_STL
00033 # include <iterator>
00034 #endif
00035 
00036 #ifdef _MSC_VER
00037 #pragma warning( push )
00038 #pragma warning( disable : 4311 4312 4127)
00039 #endif
00040 
00041 
00042 #ifdef BMSSE42OPT
00043 # ifdef BM64OPT
00044 #   undef BM64OPT
00045 #   define BM64_SSE4
00046 # endif
00047 # undef BMSSE2OPT
00048 #endif
00049 
00050 
00051 #include "bmconst.h"
00052 #include "bmdef.h"
00053 
00054 
00055 #ifdef BMSSE42OPT
00056 # define BMVECTOPT
00057 # include "bmsse4.h"
00058 #endif
00059 
00060 #ifdef BMSSE2OPT
00061 # undef BM64OPT
00062 # define BMVECTOPT
00063 # include "bmsse2.h"
00064 #endif
00065 
00066 
00067 #include "bmfwd.h"
00068 #include "bmfunc.h"
00069 #include "encoding.h"
00070 #include "bmalloc.h"
00071 #include "bmblocks.h"
00072 
00073 namespace bm
00074 {
00075 
00076 
00077 #ifdef BMCOUNTOPT
00078 
00079 # define BMCOUNT_INC ++count_;
00080 # define BMCOUNT_DEC --count_;
00081 # define BMCOUNT_VALID(x) count_is_valid_ = x;
00082 # define BMCOUNT_SET(x) count_ = x; count_is_valid_ = true;
00083 # define BMCOUNT_ADJ(x) if (x) ++count_; else --count_;
00084 
00085 #else
00086 
00087 # define BMCOUNT_INC
00088 # define BMCOUNT_DEC
00089 # define BMCOUNT_VALID(x)
00090 # define BMCOUNT_SET(x)
00091 # define BMCOUNT_ADJ(x)
00092 
00093 #endif
00094 
00095 
00096 
00097 //typedef bm::miniset<bm::block_allocator, bm::set_total_blocks> mem_save_set;
00098 
00099 
00119 template<class Alloc> 
00120 class bvector
00121 {
00122 public:
00123 
00124     typedef Alloc  allocator_type;
00125     typedef blocks_manager<Alloc>      blocks_manager_type;
00127     typedef bm::id_t                   size_type; 
00128 
00130     struct statistics : public bv_statistics
00131     {};
00132 
00140     class reference
00141     {
00142     public:
00143         reference(bvector<Alloc>& bv, bm::id_t position) 
00144         : bv_(bv),
00145           position_(position)
00146         {}
00147 
00148         reference(const reference& ref)
00149         : bv_(ref.bv_), 
00150           position_(ref.position_)
00151         {
00152             bv_.set(position_, ref.bv_.get_bit(position_));
00153         }
00154         
00155         operator bool() const
00156         {
00157             return bv_.get_bit(position_);
00158         }
00159 
00160         const reference& operator=(const reference& ref) const
00161         {
00162             bv_.set(position_, (bool)ref);
00163             return *this;
00164         }
00165 
00166         const reference& operator=(bool value) const
00167         {
00168             bv_.set(position_, value);
00169             return *this;
00170         }
00171 
00172         bool operator==(const reference& ref) const
00173         {
00174             return bool(*this) == bool(ref);
00175         }
00176 
00178         const reference& operator&=(bool value) const
00179         {
00180             bv_.set_bit_and(position_, value);
00181             return *this;
00182         }
00183 
00185         const reference& operator|=(bool value) const
00186         {
00187             if (value != bv_.get_bit(position_))
00188             {
00189                 bv_.set_bit(position_);
00190             }
00191             return *this;
00192         }
00193 
00195         const reference& operator^=(bool value) const
00196         {
00197             bv_.set(position_, value != bv_.get_bit(position_));
00198             return *this;
00199         }
00200 
00202         bool operator!() const
00203         {
00204             return !bv_.get_bit(position_);
00205         }
00206 
00208         bool operator~() const
00209         {
00210             return !bv_.get_bit(position_);
00211         }
00212 
00214         reference& flip()
00215         {
00216             bv_.flip(position_);
00217             return *this;
00218         }
00219 
00220     private:
00221         bvector<Alloc>&   bv_;       
00222         bm::id_t          position_; 
00223     };
00224 
00225     typedef bool const_reference;
00226 
00231     class iterator_base
00232     {
00233     friend class bvector;
00234     public:
00235         iterator_base() : bv_(0), position_(bm::id_max), block_(0) {}
00236 
00237         bool operator==(const iterator_base& it) const
00238         {
00239             return (position_ == it.position_) && (bv_ == it.bv_);
00240         }
00241 
00242         bool operator!=(const iterator_base& it) const
00243         {
00244             return ! operator==(it);
00245         }
00246 
00247         bool operator < (const iterator_base& it) const
00248         {
00249             return position_ < it.position_;
00250         }
00251 
00252         bool operator <= (const iterator_base& it) const
00253         {
00254             return position_ <= it.position_;
00255         }
00256 
00257         bool operator > (const iterator_base& it) const
00258         {
00259             return position_ > it.position_;
00260         }
00261 
00262         bool operator >= (const iterator_base& it) const
00263         {
00264             return position_ >= it.position_;
00265         }
00266 
00272         bool valid() const
00273         {
00274             return position_ != bm::id_max;
00275         }
00276 
00281         void invalidate()
00282         {
00283             position_ = bm::id_max;
00284         }
00285 
00286     public:
00287 
00289         struct bitblock_descr
00290         {
00291             const bm::word_t*   ptr;      
00292             unsigned            bits[32]; 
00293             unsigned            idx;      
00294             unsigned            cnt;      
00295             bm::id_t            pos;      
00296         };
00297 
00299         struct dgap_descr
00300         {
00301             const gap_word_t*   ptr;       
00302             gap_word_t          gap_len;   
00303         };
00304 
00305     protected:
00306         bm::bvector<Alloc>*     bv_;         
00307         bm::id_t                position_;   
00308         const bm::word_t*       block_;      
00309         unsigned                block_type_; 
00310         unsigned                block_idx_;  
00311 
00313         union block_descr
00314         {
00315             bitblock_descr   bit_;  
00316             dgap_descr       gap_;  
00317         } bdescr_;
00318     };
00319 
00335     class insert_iterator
00336     {
00337     public:
00338 #ifndef BM_NO_STL
00339         typedef std::output_iterator_tag  iterator_category;
00340 #endif
00341         typedef unsigned value_type;
00342         typedef void difference_type;
00343         typedef void pointer;
00344         typedef void reference;
00345 
00346         insert_iterator(bvector<Alloc>& bvect)
00347             : bvect_(bvect), 
00348               max_bit_(bvect.size())
00349         {
00350         }
00351         
00352         insert_iterator& operator=(bm::id_t n)
00353         {
00354             BM_ASSERT(n < bm::id_max);
00355 
00356             if (n >= max_bit_) 
00357             {
00358                 max_bit_ = n;
00359                 if (n >= bvect_.size()) 
00360                 {
00361                     bvect_.resize(n + 1);
00362                 }
00363             }
00364 
00365             bvect_.set(n);
00366             return *this;
00367         }
00368         
00370         insert_iterator& operator*() { return *this; }
00372         insert_iterator& operator++() { return *this; }
00374         insert_iterator& operator++(int) { return *this; }
00375         
00376     protected:
00377         bm::bvector<Alloc>&   bvect_;
00378         bm::id_t              max_bit_;
00379     };
00380 
00385     class enumerator : public iterator_base
00386     {
00387     public:
00388 #ifndef BM_NO_STL
00389         typedef std::input_iterator_tag  iterator_category;
00390 #endif
00391         typedef unsigned   value_type;
00392         typedef unsigned   difference_type;
00393         typedef unsigned*  pointer;
00394         typedef unsigned&  reference;
00395 
00396     public:
00397         enumerator() : iterator_base() {}
00398         enumerator(const bvector<Alloc>* bvect, int position)
00399             : iterator_base()
00400         { 
00401             this->bv_ = const_cast<bvector<Alloc>*>(bvect);
00402             if (position == 0)
00403             {
00404                 go_first();
00405             }
00406             else
00407             {
00408                 this->invalidate();
00409             }
00410         }
00411 
00412         bm::id_t operator*() const
00413         { 
00414             return this->position_; 
00415         }
00416 
00417         bm::id_t value() const
00418         {
00419             return this->position_;
00420         }
00421 
00422         enumerator& operator++()
00423         {
00424             return this->go_up();
00425         }
00426 
00427         enumerator operator++(int)
00428         {
00429             enumerator tmp = *this;
00430             this->go_up();
00431             return tmp;
00432         }
00433 
00434 
00435         void go_first()
00436         {
00437             BM_ASSERT(this->bv_);
00438 
00439         #ifdef BMCOUNTOPT
00440             if (this->bv_->count_is_valid_ && 
00441                 this->bv_->count_ == 0)
00442             {
00443                 this->invalidate();
00444                 return;
00445             }
00446         #endif
00447 
00448             blocks_manager_type* bman = &(this->bv_->blockman_);
00449             bm::word_t*** blk_root = bman->blocks_root();
00450 
00451             this->block_idx_ = this->position_= 0;
00452             unsigned i, j;
00453 
00454             for (i = 0; i < bman->top_block_size(); ++i)
00455             {
00456                 bm::word_t** blk_blk = blk_root[i];
00457 
00458                 if (blk_blk == 0) // not allocated
00459                 {
00460                     this->block_idx_ += bm::set_array_size;
00461                     this->position_ += bm::bits_in_array;
00462                     continue;
00463                 }
00464 
00465 
00466                 for (j = 0; j < bm::set_array_size; ++j,++(this->block_idx_))
00467                 {
00468                     this->block_ = blk_blk[j];
00469 
00470                     if (this->block_ == 0)
00471                     {
00472                         this->position_ += bits_in_block;
00473                         continue;
00474                     }
00475 
00476                     if (BM_IS_GAP(this->block_))
00477                     {
00478                         this->block_type_ = 1;
00479                         if (search_in_gapblock())
00480                         {
00481                             return;
00482                         }
00483                     }
00484                     else
00485                     {
00486                         this->block_type_ = 0;
00487                         if (search_in_bitblock())
00488                         {
00489                             return;
00490                         }
00491                     }
00492             
00493                 } // for j
00494 
00495             } // for i
00496 
00497             this->invalidate();
00498         }
00499 
00500         enumerator& go_up()
00501         {
00502             // Current block search.
00503             ++this->position_;
00504             typedef typename iterator_base::block_descr block_descr_type;
00505             
00506             block_descr_type* bdescr = &(this->bdescr_);
00507 
00508             switch (this->block_type_)
00509             {
00510             case 0:   //  BitBlock
00511                 {
00512 
00513                 // check if we can get the value from the 
00514                 // bits cache
00515 
00516                 unsigned idx = ++(bdescr->bit_.idx);
00517                 if (idx < bdescr->bit_.cnt)
00518                 {
00519                     this->position_ = bdescr->bit_.pos + 
00520                                       bdescr->bit_.bits[idx];
00521                     return *this; 
00522                 }
00523                 this->position_ += 31 - bdescr->bit_.bits[--idx];
00524 
00525                 const bm::word_t* pend = this->block_ + bm::set_block_size;
00526 
00527                 while (++(bdescr->bit_.ptr) < pend)
00528                 {
00529                     bm::word_t w = *(bdescr->bit_.ptr);
00530                     if (w)
00531                     {
00532                         bdescr->bit_.idx = 0;
00533                         bdescr->bit_.pos = this->position_;
00534                         bdescr->bit_.cnt = bm::bit_list_4(w, bdescr->bit_.bits); 
00535                         this->position_ += bdescr->bit_.bits[0];
00536                         return *this;
00537                     }
00538                     else
00539                     {
00540                         this->position_ += 32;
00541                     }
00542                 }
00543     
00544                 }
00545                 break;
00546 
00547             case 1:   // DGAP Block
00548                 {
00549                     if (--(bdescr->gap_.gap_len))
00550                     {
00551                         return *this;
00552                     }
00553 
00554                     // next gap is "OFF" by definition.
00555                     if (*(bdescr->gap_.ptr) == bm::gap_max_bits - 1)
00556                     {
00557                         break;
00558                     }
00559                     gap_word_t prev = *(bdescr->gap_.ptr);
00560                     unsigned int val = *(++(bdescr->gap_.ptr));
00561 
00562                     this->position_ += val - prev;
00563                     // next gap is now "ON"
00564 
00565                     if (*(bdescr->gap_.ptr) == bm::gap_max_bits - 1)
00566                     {
00567                         break;
00568                     }
00569                     prev = *(bdescr->gap_.ptr);
00570                     val = *(++(bdescr->gap_.ptr));
00571                     bdescr->gap_.gap_len = (gap_word_t)val - prev;
00572                     return *this;  // next "ON" found;
00573                 }
00574 
00575             default:
00576                 BM_ASSERT(0);
00577 
00578             } // switch
00579 
00580 
00581             // next bit not present in the current block
00582             // keep looking in the next blocks.
00583             ++(this->block_idx_);
00584             unsigned i = this->block_idx_ >> bm::set_array_shift;
00585             unsigned top_block_size = this->bv_->blockman_.top_block_size();
00586             for (; i < top_block_size; ++i)
00587             {
00588                 bm::word_t** blk_blk = this->bv_->blockman_.blocks_root()[i];
00589                 if (blk_blk == 0)
00590                 {
00591                     this->block_idx_ += bm::set_array_size;
00592                     this->position_ += bm::bits_in_array;
00593                     continue;
00594                 }
00595 
00596                 unsigned j = this->block_idx_ & bm::set_array_mask;
00597 
00598                 for(; j < bm::set_array_size; ++j, ++(this->block_idx_))
00599                 {
00600                     this->block_ = blk_blk[j];
00601 
00602                     if (this->block_ == 0)
00603                     {
00604                         this->position_ += bm::bits_in_block;
00605                         continue;
00606                     }
00607 
00608                     if (BM_IS_GAP(this->block_))
00609                     {
00610                         this->block_type_ = 1;
00611                         if (search_in_gapblock())
00612                         {
00613                             return *this;
00614                         }
00615                     }
00616                     else
00617                     {
00618                         this->block_type_ = 0;
00619                         if (search_in_bitblock())
00620                         {
00621                             return *this;
00622                         }
00623                     }
00624 
00625             
00626                 } // for j
00627 
00628             } // for i
00629 
00630 
00631             this->invalidate();
00632             return *this;
00633         }
00634 
00635 
00636     private:
00637         bool search_in_bitblock()
00638         {
00639             BM_ASSERT(this->block_type_ == 0);
00640             
00641             typedef typename iterator_base::block_descr block_descr_type;
00642             block_descr_type* bdescr = &(this->bdescr_);            
00643 
00644             // now lets find the first bit in block.
00645             bdescr->bit_.ptr = this->block_;
00646 
00647             const word_t* ptr_end = this->block_ + bm::set_block_size;
00648 
00649             do
00650             {
00651                 register bm::word_t w = *(bdescr->bit_.ptr);
00652 
00653                 if (w)  
00654                 {
00655                     bdescr->bit_.idx = 0;
00656                     bdescr->bit_.pos = this->position_;
00657                     bdescr->bit_.cnt = 
00658                               bm::bit_list_4(w, bdescr->bit_.bits);
00659                     this->position_ += bdescr->bit_.bits[0];
00660 
00661                     return true;
00662                 }
00663                 else
00664                 {
00665                     this->position_ += 32;
00666                 }
00667 
00668             } 
00669             while (++(bdescr->bit_.ptr) < ptr_end);
00670 
00671             return false;
00672         }
00673 
00674         bool search_in_gapblock()
00675         {
00676             BM_ASSERT(this->block_type_ == 1);
00677 
00678             typedef typename iterator_base::block_descr block_descr_type;
00679             block_descr_type* bdescr = &(this->bdescr_);            
00680 
00681             bdescr->gap_.ptr = BMGAP_PTR(this->block_);
00682             unsigned bitval = *(bdescr->gap_.ptr) & 1;
00683 
00684             ++(bdescr->gap_.ptr);
00685 
00686             for (;true;)
00687             {
00688                 register unsigned val = *(bdescr->gap_.ptr);
00689 
00690                 if (bitval)
00691                 {
00692                     gap_word_t* first = BMGAP_PTR(this->block_) + 1;
00693                     if (bdescr->gap_.ptr == first)
00694                     {
00695                         bdescr->gap_.gap_len = (gap_word_t)val + 1;
00696                     }
00697                     else
00698                     {
00699                         bdescr->gap_.gap_len = 
00700                              (gap_word_t)(val - *(bdescr->gap_.ptr-1));
00701                     }
00702            
00703                     return true;
00704                 }
00705                 this->position_ += val + 1;
00706 
00707                 if (val == bm::gap_max_bits - 1)
00708                 {
00709                     break;
00710                 }
00711 
00712                 bitval ^= 1;
00713                 ++(bdescr->gap_.ptr);
00714 
00715             }
00716 
00717             return false;
00718         }
00719 
00720     };
00721     
00731     class counted_enumerator : public enumerator
00732     {
00733     public:
00734 #ifndef BM_NO_STL
00735         typedef std::input_iterator_tag  iterator_category;
00736 #endif
00737         counted_enumerator() : bit_count_(0){}
00738         
00739         counted_enumerator(const enumerator& en)
00740         : enumerator(en)
00741         {
00742             if (this->valid())
00743                 bit_count_ = 1;
00744         }
00745         
00746         counted_enumerator& operator=(const enumerator& en)
00747         {
00748             enumerator* me = this;
00749             *me = en;
00750             if (this->valid())
00751                 this->bit_count_ = 1;
00752             return *this;
00753         }
00754         
00755         counted_enumerator& operator++()
00756         {
00757             this->go_up();
00758             if (this->valid())
00759                 ++(this->bit_count_);
00760             return *this;
00761         }
00762 
00763         counted_enumerator operator++(int)
00764         {
00765             counted_enumerator tmp(*this);
00766             this->go_up();
00767             if (this->valid())
00768                 ++bit_count_;
00769             return tmp;
00770         }
00771         
00777         bm::id_t count() const { return bit_count_; }
00778         
00779     private:
00780         bm::id_t   bit_count_;
00781     };
00782 
00783     friend class iterator_base;
00784     friend class enumerator;
00785 
00786 public:
00787 
00788 #ifdef BMCOUNTOPT
00789     bvector(strategy          strat      = BM_BIT,
00790             const gap_word_t* glevel_len = bm::gap_len_table<true>::_len,
00791             size_type         bv_size    = bm::id_max,
00792             const Alloc&      alloc      = Alloc()) 
00793     : count_(0),
00794       count_is_valid_(true),
00795       blockman_(glevel_len, bv_size, alloc),
00796       new_blocks_strat_(strat),
00797       size_(bv_size)
00798     {}
00799 
00800     bvector(size_type         bv_size,
00801             bm::strategy      strat      = BM_BIT,
00802             const gap_word_t* glevel_len = bm::gap_len_table<true>::_len,
00803             const Alloc&      alloc = Alloc()) 
00804     : count_(0),
00805       count_is_valid_(true),
00806       blockman_(glevel_len, bv_size, alloc),
00807       new_blocks_strat_(strat),
00808       size_(bv_size)
00809     {}
00810 
00811 
00812     bvector(const bm::bvector<Alloc>& bvect)
00813      : count_(bvect.count_),
00814        count_is_valid_(bvect.count_is_valid_),
00815        blockman_(bvect.blockman_),
00816        new_blocks_strat_(bvect.new_blocks_strat_),
00817        size_(bvect.size_)
00818     {}
00819 
00820 #else
00821 
00839     bvector(strategy          strat      = BM_BIT,
00840             const gap_word_t* glevel_len = bm::gap_len_table<true>::_len,
00841             size_type         bv_size    = bm::id_max,
00842             const Alloc&      alloc      = Alloc()) 
00843     : blockman_(glevel_len, bv_size, alloc),
00844       new_blocks_strat_(strat),
00845       size_(bv_size)
00846     {}
00847 
00851     bvector(size_type         bv_size,
00852             strategy          strat      = BM_BIT,
00853             const gap_word_t* glevel_len = bm::gap_len_table<true>::_len,
00854             const Alloc&      alloc      = Alloc()) 
00855     : blockman_(glevel_len, bv_size, alloc),
00856       new_blocks_strat_(strat),
00857       size_(bv_size)
00858     {}
00859 
00860 
00861     bvector(const bvector<Alloc>& bvect)
00862         :  blockman_(bvect.blockman_),
00863            new_blocks_strat_(bvect.new_blocks_strat_),
00864            size_(bvect.size_)
00865     {}
00866 
00867 #endif
00868 
00869     bvector& operator=(const bvector<Alloc>& bvect)
00870     {
00871         clear(true); // memory free cleaning
00872         resize(bvect.size());
00873         bit_or(bvect);
00874         return *this;
00875     }
00876 
00877     reference operator[](bm::id_t n)
00878     {
00879         BM_ASSERT(n < size_);
00880         return reference(*this, n);
00881     }
00882 
00883 
00884     bool operator[](bm::id_t n) const
00885     {
00886         BM_ASSERT(n < size_);
00887         return get_bit(n);
00888     }
00889 
00890     void operator &= (const bvector<Alloc>& bvect)
00891     {
00892         bit_and(bvect);
00893     }
00894 
00895     void operator ^= (const bvector<Alloc>& bvect)
00896     {
00897         bit_xor(bvect);
00898     }
00899 
00900     void operator |= (const bvector<Alloc>& bvect)
00901     {
00902         bit_or(bvect);
00903     }
00904 
00905     void operator -= (const bvector<Alloc>& bvect)
00906     {
00907         bit_sub(bvect);
00908     }
00909 
00910     bool operator < (const bvector<Alloc>& bvect) const
00911     {
00912         return compare(bvect) < 0;
00913     }
00914 
00915     bool operator <= (const bvector<Alloc>& bvect) const
00916     {
00917         return compare(bvect) <= 0;
00918     }
00919 
00920     bool operator > (const bvector<Alloc>& bvect) const
00921     {
00922         return compare(bvect) > 0;
00923     }
00924 
00925     bool operator >= (const bvector<Alloc>& bvect) const
00926     {
00927         return compare(bvect) >= 0;
00928     }
00929 
00930     bool operator == (const bvector<Alloc>& bvect) const
00931     {
00932         return compare(bvect) == 0;
00933     }
00934 
00935     bool operator != (const bvector<Alloc>& bvect) const
00936     {
00937         return compare(bvect) != 0;
00938     }
00939 
00940     bvector<Alloc> operator~() const
00941     {
00942         return bvector<Alloc>(*this).invert();
00943     }
00944     
00945     Alloc get_allocator() const
00946     {
00947         return blockman_.get_allocator();
00948     }
00949 
00950 
00957     bool set_bit(bm::id_t n, bool val = true)
00958     {
00959         BM_ASSERT(n < size_);
00960         return set_bit_no_check(n, val);
00961     }
00962 
00969     bool set_bit_and(bm::id_t n, bool val = true)
00970     {
00971         BM_ASSERT(n < size_);
00972         return and_bit_no_check(n, val);
00973     }
00974 
00982     bool set_bit_conditional(bm::id_t n, bool val, bool condition)
00983     {
00984         BM_ASSERT(n < size_);
00985         if (val == condition) return false;
00986         return set_bit_conditional_impl(n, val, condition);
00987     }
00988 
00989 
00996     bvector<Alloc>& set(bm::id_t n, bool val = true)
00997     {
00998         set_bit(n, val);
00999         return *this;
01000     }
01001 
01002 
01003 
01008     bvector<Alloc>& set()
01009     {
01010         BMCOUNT_VALID(false)
01011         set_range(0, size_ - 1, true);
01012         return *this;
01013     }
01014 
01015 
01027     bvector<Alloc>& set_range(bm::id_t left,
01028                               bm::id_t right,
01029                               bool     value = true);
01030 
01031     
01033     insert_iterator inserter()
01034     {
01035         return insert_iterator(*this);
01036     }
01037 
01038 
01043     void clear_bit(bm::id_t n)
01044     {
01045         set(n, false);
01046     }
01047 
01048 
01055     void clear(bool free_mem = false)
01056     {
01057         blockman_.set_all_zero(free_mem);
01058         BMCOUNT_SET(0);
01059     }
01060 
01065     bvector<Alloc>& reset()
01066     {
01067         clear();
01068         return *this;
01069     }
01070 
01071 
01076     bm::id_t count() const;
01077 
01081     size_type capacity() const 
01082     {
01083         return blockman_.capacity();
01084     }
01085 
01089     size_type size() const 
01090     {
01091         return size_;
01092     }
01093 
01098     void resize(size_type new_size);
01099 
01106     unsigned count_blocks(unsigned* arr) const
01107     {
01108         bm::word_t*** blk_root = blockman_.get_rootblock();
01109         typename blocks_manager_type::block_count_arr_func func(blockman_, &(arr[0]));
01110         for_each_nzblock(blk_root, blockman_.effective_top_block_size(), 
01111                          func);
01112         return func.last_block();
01113     }
01114 
01124     bm::id_t count_range(bm::id_t left, 
01125                          bm::id_t right, 
01126                          unsigned* block_count_arr=0) const;
01127 
01128 
01129     bm::id_t recalc_count()
01130     {
01131         BMCOUNT_VALID(false)
01132         return count();
01133     }
01134     
01142     void forget_count()
01143     {
01144         BMCOUNT_VALID(false)    
01145     }
01146 
01150     bvector<Alloc>& invert();
01151 
01152 
01158     bool get_bit(bm::id_t n) const;
01159 
01165     bool test(bm::id_t n) const 
01166     { 
01167         return get_bit(n); 
01168     }
01169 
01174     bool any() const
01175     {
01176     #ifdef BMCOUNTOPT
01177         if (count_is_valid_ && count_) return true;
01178     #endif
01179         
01180         word_t*** blk_root = blockman_.get_rootblock();
01181         if (!blk_root) 
01182             return false;
01183         typename blocks_manager_type::block_any_func func(blockman_);
01184         return for_each_nzblock_if(blk_root, 
01185                                    blockman_.effective_top_block_size(),
01186                                    func);
01187     }
01188 
01192     bool none() const
01193     {
01194         return !any();
01195     }
01196 
01201     bvector<Alloc>& flip(bm::id_t n) 
01202     {
01203         set(n, !get_bit(n));
01204         return *this;
01205     }
01206 
01211     bvector<Alloc>& flip() 
01212     {
01213         return invert();
01214     }
01215 
01218     void swap(bvector<Alloc>& bv)
01219     {
01220         if (this != &bv) 
01221         {
01222             blockman_.swap(bv.blockman_);
01223             bm::xor_swap(size_,bv.size_);
01224     #ifdef BMCOUNTOPT
01225             BMCOUNT_VALID(false)
01226             bv.recalc_count();
01227     #endif
01228         }
01229     }
01230 
01231 
01238     bm::id_t get_first() const { return check_or_next(0); }
01239 
01247     bm::id_t get_next(bm::id_t prev) const
01248     {
01249         return (++prev == bm::id_max) ? 0 : check_or_next(prev);
01250     }
01251 
01259     bm::id_t extract_next(bm::id_t prev)
01260     {
01261         return (++prev == bm::id_max) ? 0 : check_or_next_extract(prev);
01262     }
01263 
01264 
01276     void calc_stat(struct bm::bvector<Alloc>::statistics* st) const;
01277 
01282     bm::bvector<Alloc>& bit_or(const  bm::bvector<Alloc>& vect)
01283     {
01284         BMCOUNT_VALID(false);
01285         combine_operation(vect, BM_OR);
01286         return *this;
01287     }
01288 
01293     bm::bvector<Alloc>& bit_and(const bm::bvector<Alloc>& vect)
01294     {
01295         BMCOUNT_VALID(false);
01296         combine_operation(vect, BM_AND);
01297         return *this;
01298     }
01299 
01304     bm::bvector<Alloc>& bit_xor(const bm::bvector<Alloc>& vect)
01305     {
01306         BMCOUNT_VALID(false);
01307         combine_operation(vect, BM_XOR);
01308         return *this;
01309     }
01310 
01315     bm::bvector<Alloc>& bit_sub(const bm::bvector<Alloc>& vect)
01316     {
01317         BMCOUNT_VALID(false);
01318         combine_operation(vect, BM_SUB);
01319         return *this;
01320     }
01321 
01322 
01328     void set_new_blocks_strat(strategy strat) 
01329     { 
01330         new_blocks_strat_ = strat; 
01331     }
01332 
01339     strategy  get_new_blocks_strat() const 
01340     { 
01341         return new_blocks_strat_; 
01342     }
01343 
01344 
01350     enum optmode
01351     {
01352         opt_free_0    = 1, 
01353         opt_free_01   = 2, 
01354         opt_compress  = 3  
01355     };
01356 
01369     void optimize(bm::word_t* temp_block = 0, 
01370                   optmode opt_mode       = opt_compress,
01371                   statistics* stat       = 0);
01372 
01380     void optimize_gap_size();
01381 
01382 
01389     void set_gap_levels(const gap_word_t* glevel_len);
01390 
01398     int compare(const bvector<Alloc>& bvect) const;
01399 
01411     bm::word_t* allocate_tempblock() const
01412     {
01413         blocks_manager_type* bm = 
01414             const_cast<blocks_manager_type*>(&blockman_);
01415         return bm->get_allocator().alloc_bit_block();
01416     }
01417 
01426     void free_tempblock(bm::word_t* block) const
01427     {
01428         blocks_manager_type* bm = 
01429             const_cast<blocks_manager_type*>(&blockman_);
01430         bm->get_allocator().free_bit_block(block);
01431     }
01432 
01436     enumerator first() const
01437     {
01438         typedef typename bvector<Alloc>::enumerator enumerator_type;
01439         return enumerator_type(this, 0);
01440     }
01441 
01446     enumerator end() const
01447     {
01448         typedef typename bvector<Alloc>::enumerator enumerator_type;
01449         return enumerator_type(this, 1);
01450     }
01451 
01452 
01453     const bm::word_t* get_block(unsigned nb) const 
01454     { 
01455         return blockman_.get_block(nb); 
01456     }
01457     
01458     void combine_operation(const bm::bvector<Alloc>& bvect, 
01459                             bm::operation            opcode);
01460     
01461 private:
01462 
01463     bm::id_t check_or_next(bm::id_t prev) const;
01464     
01468     bm::id_t check_or_next_extract(bm::id_t prev);
01469 
01473     bool set_bit_no_check(bm::id_t n, bool val);
01474 
01478     bool and_bit_no_check(bm::id_t n, bool val);
01479 
01480     bool set_bit_conditional_impl(bm::id_t n, bool val, bool condition);
01481 
01482 
01483     void combine_operation_with_block(unsigned nb,
01484                                       unsigned gap,
01485                                       bm::word_t* blk,
01486                                       const bm::word_t* arg_blk,
01487                                       int arg_gap,
01488                                       bm::operation opcode);
01489 public:
01490     void combine_operation_with_block(unsigned nb,
01491                                       const bm::word_t* arg_blk,
01492                                       int arg_gap,
01493                                       bm::operation opcode)
01494     {
01495         bm::word_t* blk = const_cast<bm::word_t*>(get_block(nb));
01496         bool gap = BM_IS_GAP(blk);
01497         combine_operation_with_block(nb, gap, blk, arg_blk, arg_gap, opcode);
01498     }
01499 private:
01500     void combine_count_operation_with_block(unsigned nb,
01501                                             const bm::word_t* arg_blk,
01502                                             int arg_gap,
01503                                             bm::operation opcode)
01504     {
01505         const bm::word_t* blk = get_block(nb);
01506         bool gap = BM_IS_GAP(blk);
01507         combine_count_operation_with_block(nb, gap, blk, arg_blk, arg_gap, opcode);
01508     }
01509 
01510 
01516     void extend_gap_block(unsigned nb, gap_word_t* blk)
01517     {
01518         blockman_.extend_gap_block(nb, blk);
01519     }
01520 
01524     void set_range_no_check(bm::id_t left,
01525                             bm::id_t right,
01526                             bool     value);
01527 public:
01528 
01529     const blocks_manager_type& get_blocks_manager() const
01530     {
01531         return blockman_;
01532     }
01533 
01534     blocks_manager_type& get_blocks_manager()
01535     {
01536         return blockman_;
01537     }
01538 
01539 
01540 private:
01541 
01542 // This block defines two additional hidden variables used for bitcount
01543 // optimization, in rare cases can make bitvector thread unsafe.
01544 #ifdef BMCOUNTOPT
01545     mutable id_t      count_;            
01546     mutable bool      count_is_valid_;   
01547 #endif
01548 
01549     blocks_manager_type  blockman_;         
01550     strategy             new_blocks_strat_; 
01551     size_type            size_;             
01552 };
01553 
01554 
01555 
01556 
01557 
01558 //---------------------------------------------------------------------
01559 
01560 template<class Alloc> 
01561 inline bvector<Alloc> operator& (const bvector<Alloc>& v1,
01562                                  const bvector<Alloc>& v2)
01563 {
01564 #ifdef BM_USE_EXPLICIT_TEMP
01565     bvector<Alloc, MS> ret(v1);
01566     ret.bit_and(v2);
01567     return ret;
01568 #else    
01569     return bvector<Alloc>(v1).bit_and(v2);
01570 #endif
01571 }
01572 
01573 //---------------------------------------------------------------------
01574 
01575 template<class Alloc> 
01576 inline bvector<Alloc> operator| (const bvector<Alloc>& v1,
01577                                  const bvector<Alloc>& v2)
01578 {
01579 #ifdef BM_USE_EXPLICIT_TEMP
01580     bvector<Alloc, MS> ret(v1);
01581     ret.bit_or(v2);
01582     return ret;
01583 #else    
01584     return bvector<Alloc>(v1).bit_or(v2);
01585 #endif
01586 }
01587 
01588 //---------------------------------------------------------------------
01589 
01590 template<class Alloc> 
01591 inline bvector<Alloc> operator^ (const bvector<Alloc>& v1,
01592                                  const bvector<Alloc>& v2)
01593 {
01594 #ifdef BM_USE_EXPLICIT_TEMP
01595     bvector<Alloc, MS> ret(v1);
01596     ret.bit_xor(v2);
01597     return ret;
01598 #else    
01599     return bvector<Alloc>(v1).bit_xor(v2);
01600 #endif
01601 }
01602 
01603 //---------------------------------------------------------------------
01604 
01605 template<class Alloc> 
01606 inline bvector<Alloc> operator- (const bvector<Alloc>& v1,
01607                                  const bvector<Alloc>& v2)
01608 {
01609 #ifdef BM_USE_EXPLICIT_TEMP
01610     bvector<Alloc, MS> ret(v1);
01611     ret.bit_sub(v2);
01612     return ret;
01613 #else    
01614     return bvector<Alloc>(v1).bit_sub(v2);
01615 #endif
01616 }
01617 
01618 
01619 
01620 
01621 // -----------------------------------------------------------------------
01622 
01623 template<typename Alloc> 
01624 bvector<Alloc>& bvector<Alloc>::set_range(bm::id_t left,
01625                                           bm::id_t right,
01626                                           bool     value)
01627 {
01628     if (right < left)
01629     {
01630         return set_range(right, left, value);
01631     }
01632 
01633     BM_ASSERT(left < size_);
01634     BM_ASSERT(right < size_);
01635 
01636     BMCOUNT_VALID(false)
01637     BM_SET_MMX_GUARD
01638 
01639     set_range_no_check(left, right, value);
01640 
01641     return *this;
01642 }
01643 
01644 // -----------------------------------------------------------------------
01645 
01646 template<typename Alloc> 
01647 bm::id_t bvector<Alloc>::count() const
01648 {
01649 #ifdef BMCOUNTOPT
01650     if (count_is_valid_) return count_;
01651 #endif
01652     word_t*** blk_root = blockman_.get_rootblock();
01653     if (!blk_root) 
01654     {
01655         BMCOUNT_SET(0);
01656         return 0;
01657     }    
01658     typename blocks_manager_type::block_count_func func(blockman_);
01659     for_each_nzblock2(blk_root, blockman_.effective_top_block_size(), 
01660                       func);
01661 
01662     BMCOUNT_SET(func.count());
01663     return func.count();
01664 }
01665 
01666 // -----------------------------------------------------------------------
01667 
01668 template<typename Alloc> 
01669 void bvector<Alloc>::resize(size_type new_size)
01670 {
01671     if (size_ == new_size) return; // nothing to do
01672     if (size_ < new_size) // size grows 
01673     {
01674         blockman_.reserve(new_size);
01675         size_ = new_size;
01676     }
01677     else // shrink
01678     {
01679         set_range(new_size, size_ - 1, false); // clear the tail
01680         size_ = new_size;
01681     }
01682 }
01683 
01684 // -----------------------------------------------------------------------
01685 
01686 template<typename Alloc> 
01687 bm::id_t bvector<Alloc>::count_range(bm::id_t left, 
01688                                          bm::id_t right, 
01689                                          unsigned* block_count_arr) const
01690 {
01691     BM_ASSERT(left <= right);
01692 
01693     unsigned count = 0;
01694 
01695     // calculate logical number of start and destination blocks
01696     unsigned nblock_left  = unsigned(left  >>  bm::set_block_shift);
01697     unsigned nblock_right = unsigned(right >>  bm::set_block_shift);
01698 
01699     const bm::word_t* block = blockman_.get_block(nblock_left);
01700     bool left_gap = BM_IS_GAP(block);
01701 
01702     unsigned nbit_left  = unsigned(left  & bm::set_block_mask); 
01703     unsigned nbit_right = unsigned(right & bm::set_block_mask); 
01704 
01705     unsigned r = 
01706         (nblock_left == nblock_right) ? nbit_right : (bm::bits_in_block-1);
01707 
01708     typename blocks_manager_type::block_count_func func(blockman_);
01709 
01710     if (block)
01711     {
01712         if ((nbit_left == 0) && (r == (bm::bits_in_block-1))) // whole block
01713         {
01714             if (block_count_arr)
01715             {
01716                 count += block_count_arr[nblock_left];
01717             }
01718             else
01719             {
01720                 func(block);//, nblock_left);
01721             }
01722         }
01723         else
01724         {
01725             if (left_gap)
01726             {
01727                 count += gap_bit_count_range(BMGAP_PTR(block), 
01728                                             (gap_word_t)nbit_left,
01729                                             (gap_word_t)r);
01730             }
01731             else
01732             {
01733                 count += bit_block_calc_count_range(block, nbit_left, r);
01734             }
01735         }
01736     }
01737 
01738     if (nblock_left == nblock_right)  // in one block
01739     {
01740         return count + func.count();
01741     }
01742 
01743     for (unsigned nb = nblock_left+1; nb < nblock_right; ++nb)
01744     {
01745         block = blockman_.get_block(nb);
01746         if (block_count_arr)
01747         {
01748             count += block_count_arr[nb];
01749         }
01750         else 
01751         {
01752             if (block)
01753                 func(block);
01754         }
01755     }
01756     count += func.count();
01757 
01758     block = blockman_.get_block(nblock_right);
01759     bool right_gap = BM_IS_GAP(block);
01760 
01761     if (block)
01762     {
01763         if (right_gap)
01764         {
01765             count += gap_bit_count_range(BMGAP_PTR(block),
01766                                         (gap_word_t)0,
01767                                         (gap_word_t)nbit_right);
01768         }
01769         else
01770         {
01771             count += bit_block_calc_count_range(block, 0, nbit_right);
01772         }
01773     }
01774 
01775     return count;
01776 }
01777 
01778 // -----------------------------------------------------------------------
01779 
01780 template<typename Alloc>
01781 bvector<Alloc>& bvector<Alloc>::invert()
01782 {
01783     BMCOUNT_VALID(false)
01784     BM_SET_MMX_GUARD
01785 
01786     bm::word_t*** blk_root = blockman_.get_rootblock();
01787     typename blocks_manager_type::block_invert_func func(blockman_);    
01788     for_each_block(blk_root, blockman_.top_block_size(), func);
01789     if (size_ == bm::id_max) 
01790     {
01791         set_bit_no_check(bm::id_max, false);
01792     } 
01793     else
01794     {
01795         set_range_no_check(size_, bm::id_max, false);
01796     }
01797 
01798     return *this;
01799 }
01800 
01801 // -----------------------------------------------------------------------
01802 
01803 template<typename Alloc> 
01804 bool bvector<Alloc>::get_bit(bm::id_t n) const
01805 {    
01806     BM_ASSERT(n < size_);
01807 
01808     // calculate logical block number
01809     unsigned nblock = unsigned(n >>  bm::set_block_shift); 
01810 
01811     const bm::word_t* block = blockman_.get_block(nblock);
01812 
01813     if (block)
01814     {
01815         // calculate word number in block and bit
01816         unsigned nbit = unsigned(n & bm::set_block_mask); 
01817         unsigned is_set;
01818 
01819         if (BM_IS_GAP(block))
01820         {
01821             is_set = gap_test(BMGAP_PTR(block), nbit);
01822         }
01823         else 
01824         {
01825             unsigned nword  = unsigned(nbit >> bm::set_word_shift); 
01826             nbit &= bm::set_word_mask;
01827 
01828             is_set = (block[nword] & (((bm::word_t)1) << nbit));
01829         }
01830         return is_set != 0;
01831     }
01832     return false;
01833 }
01834 
01835 // -----------------------------------------------------------------------
01836 
01837 template<typename Alloc> 
01838 void bvector<Alloc>::optimize(bm::word_t* temp_block, 
01839                               optmode     opt_mode,
01840                               statistics* stat)
01841 {
01842     word_t*** blk_root = blockman_.blocks_root();
01843 
01844     if (!temp_block)
01845         temp_block = blockman_.check_allocate_tempblock();
01846 
01847     typename 
01848         blocks_manager_type::block_opt_func  opt_func(blockman_, 
01849                                                 temp_block, 
01850                                                 (int)opt_mode,
01851                                                 stat);
01852     if (stat)
01853     {
01854         stat->bit_blocks = stat->gap_blocks 
01855                          = stat->max_serialize_mem 
01856                          = stat->memory_used 
01857                          = 0;
01858         ::memcpy(stat->gap_levels, 
01859                 blockman_.glen(), sizeof(gap_word_t) * bm::gap_levels);
01860         stat->max_serialize_mem = sizeof(id_t) * 4;
01861 
01862     }
01863 
01864     for_each_nzblock(blk_root, blockman_.effective_top_block_size(),
01865                      opt_func);
01866 
01867     if (stat)
01868     {
01869         unsigned safe_inc = stat->max_serialize_mem / 10; // 10% increment
01870         if (!safe_inc) safe_inc = 256;
01871         stat->max_serialize_mem += safe_inc;
01872         stat->memory_used += sizeof(*this) - sizeof(blockman_);
01873         stat->memory_used += blockman_.mem_used();
01874     }
01875 }
01876 
01877 // -----------------------------------------------------------------------
01878 
01879 template<typename Alloc> 
01880 void bvector<Alloc>::optimize_gap_size()
01881 {
01882     struct bvector<Alloc>::statistics st;
01883     calc_stat(&st);
01884 
01885     if (!st.gap_blocks)
01886         return;
01887 
01888     gap_word_t opt_glen[bm::gap_levels];
01889     ::memcpy(opt_glen, st.gap_levels, bm::gap_levels * sizeof(*opt_glen));
01890 
01891     improve_gap_levels(st.gap_length, 
01892                             st.gap_length + st.gap_blocks, 
01893                             opt_glen);
01894     
01895     set_gap_levels(opt_glen);
01896 }
01897 
01898 // -----------------------------------------------------------------------
01899 
01900 template<typename Alloc> 
01901 void bvector<Alloc>::set_gap_levels(const gap_word_t* glevel_len)
01902 {
01903     word_t*** blk_root = blockman_.blocks_root();
01904     typename 
01905         blocks_manager_type::gap_level_func  gl_func(blockman_, glevel_len);
01906     for_each_nzblock(blk_root, blockman_.top_block_size(),gl_func);
01907 
01908     blockman_.set_glen(glevel_len);
01909 }
01910 
01911 // -----------------------------------------------------------------------
01912 
01913 template<typename Alloc> 
01914 int bvector<Alloc>::compare(const bvector<Alloc>& bvect) const
01915 {
01916     int res;
01917     unsigned bn = 0;
01918 
01919     unsigned top_blocks = blockman_.effective_top_block_size();
01920     unsigned bvect_top_blocks = bvect.blockman_.effective_top_block_size();
01921 
01922     if (bvect_top_blocks > top_blocks) top_blocks = bvect_top_blocks;
01923 
01924     for (unsigned i = 0; i < top_blocks; ++i)
01925     {
01926         const bm::word_t* const* blk_blk = blockman_.get_topblock(i);
01927         const bm::word_t* const* arg_blk_blk = 
01928                                 bvect.blockman_.get_topblock(i);
01929 
01930         if (blk_blk == arg_blk_blk) 
01931         {
01932             bn += bm::set_array_size;
01933             continue;
01934         }
01935 
01936         for (unsigned j = 0; j < bm::set_array_size; ++j, ++bn)
01937         {
01938             const bm::word_t* arg_blk = arg_blk_blk ? arg_blk_blk[j] : 0;
01939             const bm::word_t* blk = blk_blk ? blk_blk[j] : 0;
01940             if (blk == arg_blk) continue;
01941 
01942             // If one block is zero we check if the other one has at least 
01943             // one bit ON
01944 
01945             if (!blk || !arg_blk)  
01946             {
01947                 const bm::word_t*  pblk;
01948                 bool is_gap;
01949 
01950                 if (blk)
01951                 {
01952                     pblk = blk;
01953                     res = 1;
01954                     is_gap = BM_IS_GAP(blk);
01955                 }
01956                 else
01957                 {
01958                     pblk = arg_blk;
01959                     res = -1;
01960                     is_gap = BM_IS_GAP(arg_blk);
01961                 }
01962 
01963                 if (is_gap)
01964                 {
01965                     if (!gap_is_all_zero(BMGAP_PTR(pblk), bm::gap_max_bits))
01966                     {
01967                         return res;
01968                     }
01969                 }
01970                 else
01971                 {
01972                     bm::wordop_t* blk1 = (wordop_t*)pblk;
01973                     bm::wordop_t* blk2 = 
01974                         (wordop_t*)(pblk + bm::set_block_size);
01975                     if (!bit_is_all_zero(blk1, blk2))
01976                     {
01977                         return res;
01978                     }
01979                 }
01980 
01981                 continue;
01982             }
01983 
01984             bool arg_gap = BM_IS_GAP(arg_blk);
01985             bool gap = BM_IS_GAP(blk);
01986 
01987             if (arg_gap != gap)
01988             {
01989                 bm::wordop_t temp_blk[bm::set_block_size_op]; 
01990                 bm::wordop_t* blk1;
01991                 bm::wordop_t* blk2;
01992 
01993                 if (gap)
01994                 {
01995                     gap_convert_to_bitset((bm::word_t*)temp_blk, 
01996                                             BMGAP_PTR(blk));
01997 
01998                     blk1 = (bm::wordop_t*)temp_blk;
01999                     blk2 = (bm::wordop_t*)arg_blk;
02000                 }
02001                 else
02002                 {
02003                     gap_convert_to_bitset((bm::word_t*)temp_blk, 
02004                                             BMGAP_PTR(arg_blk));
02005 
02006                     blk1 = (bm::wordop_t*)blk;
02007                     blk2 = (bm::wordop_t*)temp_blk;
02008 
02009                 }                        
02010                 res = bitcmp(blk1, blk2, bm::set_block_size_op);  
02011 
02012             }
02013             else
02014             {
02015                 if (gap)
02016                 {
02017                     res = gapcmp(BMGAP_PTR(blk), BMGAP_PTR(arg_blk));
02018                 }
02019                 else
02020                 {
02021                     res = bitcmp((bm::wordop_t*)blk, 
02022                                     (bm::wordop_t*)arg_blk, 
02023                                     bm::set_block_size_op);
02024                 }
02025             }
02026 
02027             if (res != 0)
02028             {
02029                 return res;
02030             }
02031         
02032 
02033         } // for j
02034 
02035     } // for i
02036 
02037     return 0;
02038 }
02039 
02040 
02041 // -----------------------------------------------------------------------
02042 
02043 template<typename Alloc> 
02044 void bvector<Alloc>::calc_stat(struct bvector<Alloc>::statistics* st) const
02045 {
02046     st->bit_blocks = st->gap_blocks 
02047                    = st->max_serialize_mem 
02048                    = st->memory_used = 0;
02049 
02050     ::memcpy(st->gap_levels, 
02051              blockman_.glen(), sizeof(gap_word_t) * bm::gap_levels);
02052 
02053     unsigned empty_blocks = 0;
02054     unsigned blocks_memory = 0;
02055     gap_word_t* gapl_ptr = st->gap_length;
02056 
02057     st->max_serialize_mem = sizeof(id_t) * 4;
02058 
02059     unsigned block_idx = 0;
02060 
02061     unsigned top_size = blockman_.effective_top_block_size();
02062     // Walk the blocks, calculate statistics.
02063     for (unsigned i = 0; i < top_size; ++i)
02064     {
02065         const bm::word_t* const* blk_blk = blockman_.get_topblock(i);
02066 
02067         if (!blk_blk) 
02068         {
02069             block_idx += bm::set_array_size;
02070             st->max_serialize_mem += sizeof(unsigned) + 1;
02071             continue;
02072         }
02073 
02074         for (unsigned j = 0;j < bm::set_array_size; ++j, ++block_idx)
02075         {
02076             const bm::word_t* blk = blk_blk[j];
02077             if (IS_VALID_ADDR(blk))
02078             {
02079                 st->max_serialize_mem += empty_blocks << 2;
02080                 empty_blocks = 0;
02081 
02082                 if (BM_IS_GAP(blk))
02083                 {
02084                     ++(st->gap_blocks);
02085 
02086                     bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
02087 
02088                     unsigned mem_used = 
02089                         bm::gap_capacity(gap_blk, blockman_.glen()) 
02090                         * sizeof(gap_word_t);
02091 
02092                     *gapl_ptr = gap_length(gap_blk);
02093 
02094                     st->max_serialize_mem += *gapl_ptr * sizeof(gap_word_t);
02095                     blocks_memory += mem_used;
02096 
02097                     ++gapl_ptr;
02098                 }
02099                 else // bit block
02100                 {
02101                     ++(st->bit_blocks);
02102                     unsigned mem_used = sizeof(bm::word_t) * bm::set_block_size;
02103                     st->max_serialize_mem += mem_used;
02104                     blocks_memory += mem_used;
02105                 }
02106             }
02107             else
02108             {
02109                 ++empty_blocks;
02110             }
02111         }
02112     }  
02113 
02114     unsigned safe_inc = st->max_serialize_mem / 10; // 10% increment
02115     if (!safe_inc) safe_inc = 256;
02116     st->max_serialize_mem += safe_inc;
02117 
02118     // Calc size of different odd and temporary things.
02119 
02120     st->memory_used += sizeof(*this) - sizeof(blockman_);
02121     st->memory_used += blockman_.mem_used();
02122     st->memory_used += blocks_memory;
02123 }
02124 
02125 
02126 // -----------------------------------------------------------------------
02127 
02128 
02129 template<class Alloc> 
02130 bool bvector<Alloc>::set_bit_no_check(bm::id_t n, bool val)
02131 {
02132     // calculate logical block number
02133     unsigned nblock = unsigned(n >>  bm::set_block_shift); 
02134 
02135     int block_type;
02136 
02137     bm::word_t* blk = 
02138         blockman_.check_allocate_block(nblock, 
02139                                         val,
02140                                         get_new_blocks_strat(), 
02141                                         &block_type);
02142 
02143     if (!blk) return false;
02144 
02145     // calculate word number in block and bit
02146     unsigned nbit   = unsigned(n & bm::set_block_mask); 
02147 
02148     if (block_type == 1) // gap
02149     {
02150         unsigned is_set;
02151         unsigned new_block_len;
02152         
02153         new_block_len = 
02154             gap_set_value(val, BMGAP_PTR(blk), nbit, &is_set);
02155         if (is_set)
02156         {
02157             BMCOUNT_ADJ(val)
02158 
02159             unsigned threshold = 
02160             bm::gap_limit(BMGAP_PTR(blk), blockman_.glen());
02161 
02162             if (new_block_len > threshold) 
02163             {
02164                 extend_gap_block(nblock, BMGAP_PTR(blk));
02165             }
02166             return true;
02167         }
02168     }
02169     else  // bit block
02170     {
02171         unsigned nword  = unsigned(nbit >> bm::set_word_shift); 
02172         nbit &= bm::set_word_mask;
02173 
02174         bm::word_t* word = blk + nword;
02175         bm::word_t  mask = (((bm::word_t)1) << nbit);
02176 
02177         if (val)
02178         {
02179             if ( ((*word) & mask) == 0 )
02180             {
02181                 *word |= mask; // set bit
02182                 BMCOUNT_INC;
02183                 return true;
02184             }
02185         }
02186         else
02187         {
02188             if ((*word) & mask)
02189             {
02190                 *word &= ~mask; // clear bit
02191                 BMCOUNT_DEC;
02192                 return true;
02193             }
02194         }
02195     }
02196     return false;
02197 }
02198 
02199 // -----------------------------------------------------------------------
02200 
02201 template<class Alloc> 
02202 bool bvector<Alloc>::set_bit_conditional_impl(bm::id_t n, 
02203                                               bool     val, 
02204                                               bool     condition)
02205 {
02206     // calculate logical block number
02207     unsigned nblock = unsigned(n >>  bm::set_block_shift); 
02208 
02209     int block_type;
02210     bm::word_t* blk = 
02211         blockman_.check_allocate_block(nblock, 
02212                                        val,
02213                                        get_new_blocks_strat(), 
02214                                        &block_type);
02215     if (!blk) 
02216         return false;
02217 
02218     // calculate word number in block and bit
02219     unsigned nbit   = unsigned(n & bm::set_block_mask); 
02220 
02221     if (block_type == 1) // gap
02222     {
02223         bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
02224         bool old_val = (gap_test(gap_blk, nbit) != 0);
02225 
02226         if (old_val != condition) 
02227         {
02228             return false;
02229         }
02230 
02231         if (val != old_val)
02232         {
02233             unsigned is_set;
02234             unsigned new_block_len = 
02235                 gap_set_value(val, gap_blk, nbit, &is_set);
02236             BM_ASSERT(is_set);
02237             BMCOUNT_ADJ(val)
02238 
02239             unsigned threshold = 
02240                 bm::gap_limit(gap_blk, blockman_.glen());
02241             if (new_block_len > threshold) 
02242             {
02243                 extend_gap_block(nblock, gap_blk);
02244             }
02245             return true;
02246         }
02247     }
02248     else  // bit block
02249     {
02250         unsigned nword  = unsigned(nbit >> bm::set_word_shift); 
02251         nbit &= bm::set_word_mask;
02252 
02253         bm::word_t* word = blk + nword;
02254         bm::word_t  mask = (((bm::word_t)1) << nbit);
02255         bool is_set = ((*word) & mask) != 0;
02256 
02257         if (is_set != condition)
02258         {
02259             return false;
02260         }
02261         if (is_set != val)    // need to change bit
02262         {
02263             if (val)          // set bit
02264             {
02265                 *word |= mask;
02266                 BMCOUNT_INC;
02267             }
02268             else               // clear bit
02269             {
02270                 *word &= ~mask;
02271                 BMCOUNT_DEC;
02272             }
02273             return true;
02274         }
02275     }
02276     return false;
02277 
02278 }
02279 
02280 // -----------------------------------------------------------------------
02281 
02282 
02283 template<class Alloc> 
02284 bool bvector<Alloc>::and_bit_no_check(bm::id_t n, bool val)
02285 {
02286     // calculate logical block number
02287     unsigned nblock = unsigned(n >>  bm::set_block_shift); 
02288 
02289     int block_type;
02290     bm::word_t* blk = 
02291         blockman_.check_allocate_block(nblock, 
02292                                        val,
02293                                        get_new_blocks_strat(), 
02294                                        &block_type);
02295     if (!blk) return false;
02296 
02297     // calculate word number in block and bit
02298     unsigned nbit   = unsigned(n & bm::set_block_mask); 
02299 
02300     if (block_type == 1) // gap
02301     {
02302         bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
02303         bool old_val = (gap_test(gap_blk, nbit) != 0);
02304 
02305         bool new_val = val & old_val;
02306         if (new_val != old_val)
02307         {
02308             unsigned is_set;
02309             unsigned new_block_len = 
02310                 gap_set_value(new_val, gap_blk, nbit, &is_set);
02311             BM_ASSERT(is_set);
02312             BMCOUNT_ADJ(val)
02313 
02314             unsigned threshold = 
02315                 bm::gap_limit(gap_blk, blockman_.glen());
02316             if (new_block_len > threshold) 
02317             {
02318                 extend_gap_block(nblock, gap_blk);
02319             }
02320             return true;
02321         }
02322     }
02323     else  // bit block
02324     {
02325         unsigned nword  = unsigned(nbit >> bm::set_word_shift); 
02326         nbit &= bm::set_word_mask;
02327 
02328         bm::word_t* word = blk + nword;
02329         bm::word_t  mask = (((bm::word_t)1) << nbit);
02330         bool is_set = ((*word) & mask) != 0;
02331 
02332         bool new_val = is_set & val;
02333         if (new_val != val)    // need to change bit
02334         {
02335             if (new_val)       // set bit
02336             {
02337                 *word |= mask;
02338                 BMCOUNT_INC;
02339             }
02340             else               // clear bit
02341             {
02342                 *word &= ~mask;
02343                 BMCOUNT_DEC;
02344             }
02345             return true;
02346         }
02347     }
02348     return false;
02349 }
02350 
02351 
02352 //---------------------------------------------------------------------
02353 
02354 template<class Alloc> 
02355 bm::id_t bvector<Alloc>::check_or_next(bm::id_t prev) const
02356 {
02357     for (;;)
02358     {
02359         unsigned nblock = unsigned(prev >> bm::set_block_shift); 
02360         if (nblock >= bm::set_total_blocks) 
02361             break;
02362 
02363         if (blockman_.is_subblock_null(nblock >> bm::set_array_shift))
02364         {
02365             prev += (bm::set_blkblk_mask + 1) -
02366                             (prev & bm::set_blkblk_mask);
02367         }
02368         else
02369         {
02370             unsigned nbit = unsigned(prev & bm::set_block_mask);
02371             int no_more_blocks;
02372             const bm::word_t* block = 
02373                 blockman_.get_block(nblock, &no_more_blocks);
02374 
02375             if (no_more_blocks) 
02376             {
02377                 BM_ASSERT(block == 0);
02378                 break;
02379             }
02380 
02381             if (block)
02382             {
02383                 if (IS_FULL_BLOCK(block)) return prev;
02384                 if (BM_IS_GAP(block))
02385                 {
02386                     if (bm::gap_find_in_block(BMGAP_PTR(block),
02387                                                 nbit,
02388                                                 &prev))
02389                     {
02390                         return prev;
02391                     }
02392                 }
02393                 else
02394                 {
02395                     if (bm::bit_find_in_block(block, nbit, &prev)) 
02396                     {
02397                         return prev;
02398                     }
02399                 }
02400             }
02401             else
02402             {
02403                 prev += (bm::set_block_mask + 1) - 
02404                             (prev & bm::set_block_mask);
02405             }
02406 
02407         }
02408         if (!prev) break;
02409     }
02410 
02411     return 0;
02412 }
02413 
02414 
02415 //---------------------------------------------------------------------
02416 
02417 template<class Alloc> 
02418 bm::id_t bvector<Alloc>::check_or_next_extract(bm::id_t prev)
02419 {
02420     for (;;)
02421     {
02422         unsigned nblock = unsigned(prev >> bm::set_block_shift); 
02423         if (nblock >= bm::set_total_blocks) break;
02424 
02425         if (blockman_.is_subblock_null(nblock >> bm::set_array_shift))
02426         {
02427             prev += (bm::set_blkblk_mask + 1) -
02428                             (prev & bm::set_blkblk_mask);
02429         }
02430         else
02431         {
02432             unsigned nbit = unsigned(prev & bm::set_block_mask);
02433 
02434             int no_more_blocks;
02435             bm::word_t* block = 
02436                 blockman_.get_block(nblock, &no_more_blocks);
02437 
02438             if (no_more_blocks) 
02439             {
02440                 BM_ASSERT(block == 0);
02441                 break;
02442             }
02443 
02444 
02445             if (block)
02446             {
02447                 if (IS_FULL_BLOCK(block))
02448                 {
02449                     set(prev, false);
02450                     return prev;
02451                 }
02452                 if (BM_IS_GAP(block))
02453                 {
02454                     unsigned is_set;
02455                     unsigned new_block_len = 
02456                         gap_set_value(0, BMGAP_PTR(block), nbit, &is_set);
02457                     if (is_set) {
02458                         BMCOUNT_DEC
02459                         unsigned threshold = 
02460                             bm::gap_limit(BMGAP_PTR(block), blockman_.glen());
02461                         if (new_block_len > threshold) 
02462                         {
02463                             extend_gap_block(nblock, BMGAP_PTR(block));
02464                         }
02465                         return prev;
02466                     } else {
02467                         if (bm::gap_find_in_block(BMGAP_PTR(block),
02468                                                     nbit,
02469                                                     &prev))
02470                         {
02471                             set(prev, false);
02472                             return prev;
02473                         }
02474                     }
02475                 }
02476                 else // bit block
02477                 {
02478                     if (bm::bit_find_in_block(block, nbit, &prev)) 
02479                     {
02480                         BMCOUNT_DEC
02481 
02482                         unsigned nbit = 
02483                             unsigned(prev & bm::set_block_mask); 
02484                         unsigned nword = 
02485                             unsigned(nbit >> bm::set_word_shift);
02486                         nbit &= bm::set_word_mask;
02487                         bm::word_t* word = block + nword;
02488                         bm::word_t  mask = ((bm::word_t)1) << nbit;
02489                         *word &= ~mask;
02490 
02491                         return prev;
02492                     }
02493                 }
02494             }
02495             else
02496             {
02497                 prev += (bm::set_block_mask + 1) - 
02498                             (prev & bm::set_block_mask);
02499             }
02500 
02501         }
02502         if (!prev) break;
02503     }
02504 
02505     return 0;
02506 }
02507 
02508 //---------------------------------------------------------------------
02509 
02510 template<class Alloc> 
02511 void bvector<Alloc>::combine_operation(
02512                                   const bm::bvector<Alloc>& bvect, 
02513                                   bm::operation             opcode)
02514 {
02515     typedef void (*block_bit_op)(bm::word_t*, const bm::word_t*);
02516     typedef void (*block_bit_op_next)(bm::word_t*, 
02517                                       const bm::word_t*, 
02518                                       bm::word_t*, 
02519                                       const bm::word_t*);
02520 
02521     unsigned top_blocks = blockman_.top_block_size();
02522     unsigned bvect_top_blocks = bvect.blockman_.top_block_size();
02523 
02524     if (size_ == bvect.size_) 
02525     {
02526         BM_ASSERT(top_blocks >= bvect_top_blocks);
02527     }
02528     else
02529     if (size_ < bvect.size_) // this vect shorter than the arg.
02530     {
02531         size_ = bvect.size_;
02532         // stretch our capacity
02533         blockman_.reserve_top_blocks(bvect_top_blocks);
02534         top_blocks = blockman_.top_block_size();
02535     }
02536     else 
02537     if (size_ > bvect.size_) // this vector larger
02538     {
02539         if (opcode == BM_AND) // clear the tail with zeros
02540         {
02541             set_range(bvect.size_, size_ - 1, false);
02542             if (bvect_top_blocks < top_blocks)
02543             {
02544                 // not to scan blocks we already swiped
02545                 top_blocks = bvect_top_blocks;
02546             }
02547         }
02548     }
02549     
02550     bm::word_t*** blk_root = blockman_.blocks_root();
02551     unsigned block_idx = 0;
02552     unsigned i, j;
02553 
02554     BM_SET_MMX_GUARD
02555 
02556     // calculate effective top size to avoid overscan
02557     top_blocks = blockman_.effective_top_block_size();
02558     if (top_blocks < bvect.blockman_.effective_top_block_size())
02559     {
02560         if (opcode != BM_AND)
02561         {
02562             top_blocks = bvect.blockman_.effective_top_block_size();
02563         }
02564     }
02565 
02566     for (i = 0; i < top_blocks; ++i)
02567     {
02568         bm::word_t** blk_blk = blk_root[i];
02569         if (blk_blk == 0) // not allocated
02570         {
02571             if (opcode == BM_AND) // 0 AND anything == 0
02572             {
02573                 block_idx += bm::set_array_size;
02574                 continue; 
02575             }
02576             const bm::word_t* const* bvbb = bvect.blockman_.get_topblock(i);
02577             if (bvbb == 0) // skip it because 0 OP 0 == 0 
02578             {
02579                 block_idx += bm::set_array_size;
02580                 continue; 
02581             }
02582             // 0 - self, non-zero argument
02583             unsigned r = i * bm::set_array_size;
02584             for (j = 0; j < bm::set_array_size; ++j)
02585             {
02586                 const bm::word_t* arg_blk = bvect.blockman_.get_block(i, j);
02587                 if (arg_blk )
02588                     combine_operation_with_block(r + j,
02589                                                  0, 0, 
02590                                                  arg_blk, BM_IS_GAP(arg_blk), 
02591                                                  opcode);
02592             } // for j
02593             continue;
02594         }
02595 
02596         if (opcode == BM_AND)
02597         {
02598             unsigned r = i * bm::set_array_size;
02599             for (j = 0; j < bm::set_array_size; ++j)
02600             {            
02601                 bm::word_t* blk = blk_blk[j];
02602                 if (blk)
02603                 {
02604                     const bm::word_t* arg_blk = bvect.blockman_.get_block(i, j);            
02605                     if (arg_blk)
02606                         combine_operation_with_block(r + j,
02607                                                      BM_IS_GAP(blk), blk, 
02608                                                      arg_blk, BM_IS_GAP(arg_blk),
02609                                                      opcode);                    
02610                     else
02611                         blockman_.zero_block(i, j);
02612                 }
02613 
02614             } // for j
02615         }
02616         else // OR, SUB, XOR
02617         {
02618             unsigned r = i * bm::set_array_size;
02619             for (j = 0; j < bm::set_array_size; ++j)
02620             {            
02621                 bm::word_t* blk = blk_blk[j];
02622                 const bm::word_t* arg_blk = bvect.blockman_.get_block(i, j);            
02623                 if (arg_blk || blk)
02624                     combine_operation_with_block(r + j, BM_IS_GAP(blk), blk, 
02625                                                  arg_blk, BM_IS_GAP(arg_blk),
02626                                                  opcode);
02627             } // for j
02628         }
02629     } // for i
02630 
02631 }
02632 
02633 
02634 //---------------------------------------------------------------------
02635 
02636 
02637 template<class Alloc> 
02638 void 
02639 bvector<Alloc>::combine_operation_with_block(unsigned          nb,
02640                                              unsigned          gap,
02641                                              bm::word_t*       blk,
02642                                              const bm::word_t* arg_blk,
02643                                              int               arg_gap,
02644                                              bm::operation     opcode)
02645 {
02646     gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result            
02647     const bm::gap_word_t* res;
02648     unsigned res_len;
02649     int      level;
02650     unsigned threshold;
02651 
02652 
02653     if (opcode == BM_OR || opcode == BM_XOR)
02654     {        
02655         if (!blk && arg_gap) 
02656         {
02657             res = BMGAP_PTR(arg_blk);
02658             res_len = bm::gap_length(res);
02659             level = -1;
02660             threshold = 0;
02661             goto assign_gap_result;
02662         }
02663     }
02664 
02665         if (gap) // our block GAP-type
02666         {
02667             if (arg_gap)  // both blocks GAP-type
02668             {
02669                 {
02670                     gap_operation_func_type gfunc = 
02671                         operation_functions<true>::gap_operation(opcode);
02672                     BM_ASSERT(gfunc);
02673                     res = (*gfunc)(BMGAP_PTR(blk), 
02674                                    BMGAP_PTR(arg_blk), 
02675                                    tmp_buf,
02676                                    res_len);
02677                 }
02678                 BM_ASSERT(res == tmp_buf);
02679                 ++res_len;// = bm::gap_length(res);
02680 
02681                 BM_ASSERT(!(res == tmp_buf && res_len == 0));
02682 
02683                 // if as a result of the operation gap block turned to zero
02684                 // we can now replace it with NULL
02685                 if (gap_is_all_zero(res, bm::gap_max_bits))
02686                 {
02687                     blockman_.zero_block(nb);
02688                     return;
02689                 }
02690 
02691                 // mutation check
02692 
02693                 level = gap_level(BMGAP_PTR(blk));
02694                 threshold = blockman_.glen(level)-4;
02695 
02696             assign_gap_result:
02697                 int new_level = gap_calc_level(res_len, blockman_.glen());
02698                 if (new_level == -1)
02699                 {
02700                     blockman_.convert_gap2bitset(nb, res, res_len-1);
02701                     return;
02702                 }
02703 
02704                 if (res_len > threshold)
02705                 {
02706                     gap_word_t* new_blk = 
02707                         blockman_.allocate_gap_block(new_level, res);
02708                     set_gap_level(new_blk, new_level);
02709 
02710                     bm::word_t* p = (bm::word_t*)new_blk;
02711                     BMSET_PTRGAP(p);
02712 
02713                     if (blk)
02714                     {
02715                         blockman_.set_block_ptr(nb, p);
02716                         blockman_.get_allocator().free_gap_block(BMGAP_PTR(blk), 
02717                                                                  blockman_.glen());
02718                     }
02719                     else
02720                     {
02721                         blockman_.set_block(nb, p, true); // set GAP block
02722                     }
02723                     return;
02724                 }
02725 
02726                 // gap operation result is in the temporary buffer
02727                 // we copy it back to the gap_block
02728 
02729                 BM_ASSERT(blk);
02730 
02731                 set_gap_level(tmp_buf, level);
02732                 ::memcpy(BMGAP_PTR(blk), tmp_buf, res_len * sizeof(gap_word_t));
02733                 return;
02734             }
02735             else // argument is BITSET-type (own block is GAP)
02736             {
02737                 // since we can not combine blocks of mixed type
02738                 // we need to convert our block to bitset
02739                
02740                 if (arg_blk == 0)  // Combining against an empty block
02741                 {
02742                     switch (opcode)
02743                     {
02744                     case BM_AND:  // ("Value" AND  0) == 0
02745                         blockman_.zero_block(nb);
02746                         return;
02747                     case BM_OR: case BM_SUB: case BM_XOR:
02748                         return; // nothing to do
02749                     }
02750                 }
02751                 gap_word_t* gap_blk = BMGAP_PTR(blk);
02752                 if (opcode == BM_AND)
02753                 {
02754                     unsigned gap_cnt = gap_bit_count(gap_blk);
02755                     if (gap_cnt < 128)
02756                     {
02757                         gap_word_t tmp_buf[bm::gap_equiv_len * 3];         
02758                         gap_word_t arr_len = 
02759                             gap_convert_to_arr(tmp_buf, gap_blk, 
02760                                                bm::gap_equiv_len-10);
02761                         BM_ASSERT(gap_cnt == arr_len);
02762                         blockman_.zero_block(nb);
02763                         unsigned arr_i = 0;
02764                         int block_type;
02765                         blk =
02766                             blockman_.check_allocate_block(nb,
02767                                                            true,
02768                                                            BM_GAP,
02769                                                            &block_type,
02770                                                            false //no null return
02771                                                            );
02772                         BM_ASSERT(block_type==1); // GAP
02773                         gap_blk = BMGAP_PTR(blk);
02774                         unsigned threshold = bm::gap_limit(gap_blk, blockman_.glen());
02775                         for (; arr_i < arr_len; ++arr_i)
02776                         {
02777                             gap_word_t bit_idx = tmp_buf[arr_i];
02778                             if (bm::test_bit(arg_blk, bit_idx))
02779                             {
02780                                 unsigned is_set;
02781                                 unsigned new_block_len =
02782                                     gap_set_value(true, gap_blk, bit_idx, &is_set);
02783                                 BM_ASSERT(is_set);
02784                                 if (new_block_len > threshold) 
02785                                 {
02786                                     gap_blk = 
02787                                         blockman_.extend_gap_block(nb, gap_blk);
02788                                     if (gap_blk == 0) // mutated into bit-block
02789                                     {
02790                                         blk = blockman_.check_allocate_block(
02791                                                          nb,
02792                                                          true,
02793                                                          this->get_new_blocks_strat(),
02794                                                          &block_type,
02795                                                          false // no null return
02796                                                          );  
02797                                         BM_ASSERT(block_type == 0); // BIT
02798                                         // target block degraded into plain bit-block
02799                                         for (++arr_i; arr_i < arr_len; ++arr_i)
02800                                         {
02801                                             bit_idx = tmp_buf[arr_i];
02802                                             if (bm::test_bit(arg_blk, bit_idx))
02803                                             {
02804                                                 or_bit_block(blk, bit_idx, 1);
02805                                             }
02806                                         } // for arr_i
02807                                         return;
02808                                     } // if gap mutated
02809                                 }
02810                             } // for arr_i
02811                         }
02812 
02813                         return;
02814                     }                    
02815                 } // BM_AND
02816 
02817                 blk = blockman_.convert_gap2bitset(nb, gap_blk);
02818             }
02819         } 
02820         else // our block is BITSET-type
02821         {
02822             if (arg_gap) // argument block is GAP-type
02823             {
02824                 if (IS_VALID_ADDR(blk))
02825                 {
02826                     // special case, maybe we can do the job without 
02827                     // converting the GAP argument to bitblock
02828                     gap_operation_to_bitset_func_type gfunc = 
02829                         operation_functions<true>::gap_op_to_bit(opcode);
02830                     BM_ASSERT(gfunc);
02831                     (*gfunc)(blk, BMGAP_PTR(arg_blk));
02832                     return;
02833                 }
02834                 
02835                 // the worst case we need to convert argument block to 
02836                 // bitset type.
02837                 gap_word_t* temp_blk = (gap_word_t*) blockman_.check_allocate_tempblock();
02838                 arg_blk = 
02839                     gap_convert_to_bitset_smart((bm::word_t*)temp_blk, 
02840                                                 BMGAP_PTR(arg_blk), 
02841                                                 bm::gap_max_bits);
02842             
02843             }   
02844         }
02845     
02846         // Now here we combine two plain bitblocks using supplied bit function.
02847         bm::word_t* dst = blk;
02848 
02849         bm::word_t* ret; 
02850         if (dst == 0 && arg_blk == 0)
02851         {
02852             return;
02853         }
02854 
02855         switch (opcode)
02856         {
02857         case BM_AND:
02858             ret = bit_operation_and(dst, arg_blk);
02859             goto copy_block;
02860         case BM_XOR:
02861             ret = bit_operation_xor(dst, arg_blk);
02862             if (ret && (ret == arg_blk) && IS_FULL_BLOCK(dst))
02863             {
02864                 ret = blockman_.get_allocator().alloc_bit_block();
02865 #ifdef BMVECTOPT
02866             VECT_XOR_ARR_2_MASK(ret, 
02867                                 arg_blk, 
02868                                 arg_blk + bm::set_block_size, 
02869                                 bm::all_bits_mask);
02870 #else
02871                 bm::wordop_t* dst_ptr = (wordop_t*)ret;
02872                 const bm::wordop_t* wrd_ptr = (wordop_t*) arg_blk;
02873                 const bm::wordop_t* wrd_end = 
02874                 (wordop_t*) (arg_blk + bm::set_block_size);
02875 
02876                 do
02877                 {
02878                     dst_ptr[0] = bm::all_bits_mask ^ wrd_ptr[0];
02879                     dst_ptr[1] = bm::all_bits_mask ^ wrd_ptr[1];
02880                     dst_ptr[2] = bm::all_bits_mask ^ wrd_ptr[2];
02881                     dst_ptr[3] = bm::all_bits_mask ^ wrd_ptr[3];
02882 
02883                     dst_ptr+=4;
02884                     wrd_ptr+=4;
02885 
02886                 } while (wrd_ptr < wrd_end);
02887 #endif
02888                 break;
02889             }
02890             goto copy_block;
02891         case BM_OR:
02892             ret = bit_operation_or(dst, arg_blk);
02893         copy_block:
02894             if (ret && (ret == arg_blk) && !IS_FULL_BLOCK(ret))
02895             {
02896             ret = blockman_.get_allocator().alloc_bit_block();
02897             bit_block_copy(ret, arg_blk);
02898             }
02899             break;
02900 
02901         case BM_SUB:
02902             ret = bit_operation_sub(dst, arg_blk);
02903             if (ret && ret == arg_blk)
02904             {
02905                 ret = blockman_.get_allocator().alloc_bit_block();
02906 #ifdef BMVECTOPT
02907                 VECT_ANDNOT_ARR_2_MASK(ret, 
02908                                     arg_blk,
02909                                     arg_blk + bm::set_block_size,
02910                                     bm::all_bits_mask);
02911 #else
02912 
02913                 bm::wordop_t* dst_ptr = (wordop_t*)ret;
02914                 const bm::wordop_t* wrd_ptr = (wordop_t*) arg_blk;
02915                 const bm::wordop_t* wrd_end = 
02916                 (wordop_t*) (arg_blk + bm::set_block_size);
02917 
02918                 do
02919                 {
02920                     dst_ptr[0] = bm::all_bits_mask & ~wrd_ptr[0];
02921                     dst_ptr[1] = bm::all_bits_mask & ~wrd_ptr[1];
02922                     dst_ptr[2] = bm::all_bits_mask & ~wrd_ptr[2];
02923                     dst_ptr[3] = bm::all_bits_mask & ~wrd_ptr[3];
02924 
02925                     dst_ptr+=4;
02926                     wrd_ptr+=4;
02927 
02928                 } while (wrd_ptr < wrd_end);
02929 #endif
02930             }
02931             break;
02932         default:
02933             BM_ASSERT(0);
02934             ret = 0;
02935         }
02936 
02937         if (ret != dst) // block mutation
02938         {
02939             blockman_.set_block(nb, ret);
02940             blockman_.get_allocator().free_bit_block(dst);
02941         }
02942 }
02943 
02944 //---------------------------------------------------------------------
02945 
02946 template<class Alloc> 
02947 void bvector<Alloc>::set_range_no_check(bm::id_t left,
02948                                         bm::id_t right,
02949                                         bool     value)
02950 {
02951     // calculate logical number of start and destination blocks
02952     unsigned nblock_left  = unsigned(left  >>  bm::set_block_shift);
02953     unsigned nblock_right = unsigned(right >>  bm::set_block_shift);
02954 
02955     bm::word_t* block = blockman_.get_block(nblock_left);
02956     bool left_gap = BM_IS_GAP(block);
02957 
02958     unsigned nbit_left  = unsigned(left  & bm::set_block_mask); 
02959     unsigned nbit_right = unsigned(right & bm::set_block_mask); 
02960 
02961     unsigned r = 
02962         (nblock_left == nblock_right) ? nbit_right :(bm::bits_in_block-1);
02963 
02964         bm::gap_word_t tmp_gap_blk[5] = {0,};
02965 
02966     // Set bits in the starting block
02967 
02968     unsigned nb;
02969     if ((nbit_left == 0) && (r == bm::bits_in_block - 1)) // full block
02970     {
02971         nb = nblock_left;
02972     }
02973     else
02974     {
02975         gap_init_range_block<gap_word_t>(tmp_gap_blk,
02976                                          (gap_word_t)nbit_left, 
02977                                          (gap_word_t)r, 
02978                                          (gap_word_t)value, 
02979                                          bm::bits_in_block);
02980 
02981         combine_operation_with_block(nblock_left, 
02982                                     left_gap, 
02983                                     block,
02984                                     (bm::word_t*) tmp_gap_blk,
02985                                     1,
02986                                     value ? BM_OR : BM_AND);
02987 
02988         if (nblock_left == nblock_right)  // in one block
02989             return;
02990         nb = nblock_left+1;
02991     }
02992 
02993     // Set (or clear) all full blocks between left and right
02994     
02995     unsigned nb_to = nblock_right + (nbit_right ==(bm::bits_in_block-1));
02996             
02997     if (value)
02998     {
02999         for (; nb < nb_to; ++nb)
03000         {
03001             block = blockman_.get_block(nb);
03002             if (IS_FULL_BLOCK(block)) 
03003                 continue;
03004 
03005             blockman_.set_block(nb, FULL_BLOCK_ADDR);
03006             blockman_.free_block(block);
03007         } // for
03008     }
03009     else // value == 0
03010     {
03011         for (; nb < nb_to; ++nb)
03012         {
03013             block = blockman_.get_block(nb);
03014             if (block == 0)  // nothing to do
03015                 continue;
03016             blockman_.set_block(nb, 0, false /*bit*/);
03017             blockman_.free_block(block);
03018 
03019         } // for
03020     } // if value else 
03021 
03022     if (nb_to > nblock_right)
03023         return;
03024 
03025     block = blockman_.get_block(nblock_right);
03026     bool right_gap = BM_IS_GAP(block);
03027 
03028     gap_init_range_block<gap_word_t>(tmp_gap_blk, 
03029                                      (gap_word_t)0, 
03030                                      (gap_word_t)nbit_right, 
03031                                      (gap_word_t)value, 
03032                                      bm::bits_in_block);
03033 
03034     combine_operation_with_block(nblock_right, 
03035                                     right_gap, 
03036                                     block,
03037                                     (bm::word_t*) tmp_gap_blk,
03038                                     1,
03039                                     value ? BM_OR : BM_AND);
03040 
03041 }
03042 
03043 //---------------------------------------------------------------------
03044 
03045 
03046 } // namespace
03047 
03048 #include "bmundef.h"
03049 
03050 #ifdef _MSC_VER
03051 #pragma warning( pop )
03052 #endif
03053 
03054 
03055 #endif