BitMagic-C++
bm.h
Go to the documentation of this file.
1 #ifndef BM__H__INCLUDED__
2 #define BM__H__INCLUDED__
3 /*
4 Copyright(c) 2002-2019 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
5 
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9 
10  http://www.apache.org/licenses/LICENSE-2.0
11 
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 
18 For more information please visit: http://bitmagic.io
19 */
20 
21 /*! \file bm.h
22  \brief Compressed bit-vector bvector<> container, set algebraic methods, traversal iterators
23 */
24 
25 
26 // define BM_NO_STL if you use BM in "STL free" environment and want
27 // to disable any references to STL headers
28 #ifndef BM_NO_STL
29 # include <iterator>
30 # include <initializer_list>
31 # include <stdexcept>
32 #endif
33 
34 #include <limits.h>
35 
36 #ifdef _MSC_VER
37 #pragma warning( push )
38 #pragma warning( disable : 4311 4312 4127)
39 #endif
40 
41 
42 #include "bmdef.h"
43 #include "bmconst.h"
44 #include "bmsimd.h"
45 #include "bmfwd.h"
46 
47 # define BM_DECLARE_TEMP_BLOCK(x) bm::bit_block_t x;
48 
49 #include "bmfunc.h"
50 #include "encoding.h"
51 #include "bmalloc.h"
52 #include "bmblocks.h"
53 #include "bmbuffer.h"
54 #include "bmdef.h"
55 
56 #include "bmrs.h"
57 
58 extern "C"
59 {
60 #ifdef BM64ADDR
61  typedef int (*bit_visitor_callback_type)(void* handle_ptr, bm::id64_t bit_idx);
62 #else
63  /**
64  Callback type to visit (callback style) bits in bit-vector(s)
65 
66  @param handle_ptr - custom pointer to callback specific data
67  @param bit_idx - number/index of visited bit
68 
69  @ingroup bvector
70  */
71  typedef int (*bit_visitor_callback_type)(void* handle_ptr, bm::id_t bit_idx);
72 #endif
73 }
74 
75 
76 namespace bm
77 {
78 
79 /** @defgroup bmagic BitMagic Library
80  BitMagic C++ Library
81  For more information please visit: http://bitmagic.io
82 */
83 
84 
85 /** @defgroup bvector bvector<> container
86  The Main bvector<> Group
87  bvector<> template: front end of the BitMagic library.
88 
89  @ingroup bmagic
90 */
91 
92 /** @defgroup bvit bvector<> iterators
93  Iterators for compressed bit-vector traversal
94  @ingroup bvector
95 */
96 
97 
98 
99 
100 /*!
101  @brief Bitvector
102  Bit-vector container with runtime compression of bits
103 
104  @ingroup bvector
105 */
106 template<class Alloc>
107 class bvector
108 {
109 public:
110  typedef Alloc allocator_type;
111  typedef typename allocator_type::allocator_pool_type allocator_pool_type;
112  typedef blocks_manager<Alloc> blocks_manager_type;
113  typedef typename blocks_manager_type::block_idx_type block_idx_type;
114 #ifdef BM64ADDR
115  typedef bm::id64_t size_type;
116 #else
118 #endif
119 
120  /** Statistical information about bitset's memory allocation details. */
121  struct statistics : public bv_statistics
122  {};
123 
124  /*!
125  \brief Optimization mode
126  Every next level means additional checks (better compression vs time)
127  \sa optimize
128  */
129  enum optmode
130  {
131  opt_none = 0, ///< no optimization
132  opt_free_0 = 1, ///< Free unused 0 blocks
133  opt_free_01 = 2, ///< Free unused 0 and 1 blocks
134  opt_compress = 3 ///< compress blocks when possible (GAP/prefix sum)
135  };
136 
137 
138  /**
139  @brief Class reference implements an object for bit assignment.
140  Since C++ does not provide with build-in bit type supporting l-value
141  operations we have to emulate it.
142 
143  @ingroup bvector
144  */
145  class reference
146  {
147  public:
149  : bv_(bv),
150  position_(position)
151  {}
152 
154  : bv_(ref.bv_),
155  position_(ref.position_)
156  {
157  bv_.set(position_, ref.bv_.get_bit(position_));
158  }
159 
160  operator bool() const BMNOEXCEPT
161  {
162  return bv_.get_bit(position_);
163  }
164 
165  const reference& operator=(const reference& ref) const
166  {
167  bv_.set(position_, (bool)ref);
168  return *this;
169  }
170 
171  const reference& operator=(bool value) const BMNOEXCEPT
172  {
173  bv_.set(position_, value);
174  return *this;
175  }
176 
177  bool operator==(const reference& ref) const BMNOEXCEPT
178  {
179  return bool(*this) == bool(ref);
180  }
181 
182  /*! Bitwise AND. Performs operation: bit = bit AND value */
183  const reference& operator&=(bool value) const
184  {
185  bv_.set_bit_and(position_, value);
186  return *this;
187  }
188 
189  /*! Bitwise OR. Performs operation: bit = bit OR value */
190  const reference& operator|=(bool value) const
191  {
192  if (value != bv_.get_bit(position_))
193  {
194  bv_.set_bit(position_);
195  }
196  return *this;
197  }
198 
199  /*! Bitwise exclusive-OR (XOR). Performs operation: bit = bit XOR value */
200  const reference& operator^=(bool value) const
201  {
202  bv_.set(position_, value != bv_.get_bit(position_));
203  return *this;
204  }
205 
206  /*! Logical Not operator */
207  bool operator!() const BMNOEXCEPT
208  {
209  return !bv_.get_bit(position_);
210  }
211 
212  /*! Bit Not operator */
213  bool operator~() const BMNOEXCEPT
214  {
215  return !bv_.get_bit(position_);
216  }
217 
218  /*! Negates the bit value */
220  {
221  bv_.flip(position_);
222  return *this;
223  }
224 
225  private:
226  bvector<Alloc>& bv_; //!< Reference variable on the parent.
227  size_type position_; //!< Position in the parent bitvector.
228  };
229 
230  typedef bool const_reference;
231 
232  /*!
233  @brief Base class for all iterators.
234  @ingroup bvit
235  */
237  {
238  friend class bvector;
239  public:
241  : bv_(0), position_(bm::id_max), block_(0), block_type_(0),
242  block_idx_(0)
243  {}
244 
245  bool operator==(const iterator_base& it) const BMNOEXCEPT
246  {
247  return (position_ == it.position_) && (bv_ == it.bv_);
248  }
249 
250  bool operator!=(const iterator_base& it) const BMNOEXCEPT
251  {
252  return ! operator==(it);
253  }
254 
255  bool operator < (const iterator_base& it) const BMNOEXCEPT
256  {
257  return position_ < it.position_;
258  }
259 
260  bool operator <= (const iterator_base& it) const BMNOEXCEPT
261  {
262  return position_ <= it.position_;
263  }
264 
265  bool operator > (const iterator_base& it) const BMNOEXCEPT
266  {
267  return position_ > it.position_;
268  }
269 
270  bool operator >= (const iterator_base& it) const BMNOEXCEPT
271  {
272  return position_ >= it.position_;
273  }
274 
275  /**
276  \fn bool bm::bvector::iterator_base::valid() const
277  \brief Checks if iterator is still valid. Analog of != 0 comparison for pointers.
278  \returns true if iterator is valid.
279  */
280  bool valid() const BMNOEXCEPT { return position_ != bm::id_max; }
281 
282  /**
283  \fn bool bm::bvector::iterator_base::invalidate()
284  \brief Turns iterator into an invalid state.
285  */
287  { position_ = bm::id_max; block_type_ = ~0u;}
288 
289  /** \brief Compare FSMs for testing purposes
290  \internal
291  */
292  bool compare_state(const iterator_base& ib) const BMNOEXCEPT
293  {
294  if (this->bv_ != ib.bv_) return false;
295  if (this->position_ != ib.position_) return false;
296  if (this->block_ != ib.block_) return false;
297  if (this->block_type_ != ib.block_type_) return false;
298  if (this->block_idx_ != ib.block_idx_) return false;
299 
300  const block_descr& bd = this->bdescr_;
301  const block_descr& ib_db = ib.bdescr_;
302 
303  if (this->block_type_ == 0) // bit block
304  {
305  if (bd.bit_.ptr != ib_db.bit_.ptr) return false;
306  if (bd.bit_.idx != ib_db.bit_.idx) return false;
307  if (bd.bit_.cnt != ib_db.bit_.cnt) return false;
308  if (bd.bit_.pos != ib_db.bit_.pos) return false;
309  for (unsigned i = 0; i < bd.bit_.cnt; ++i)
310  {
311  if (bd.bit_.bits[i] != ib_db.bit_.bits[i]) return false;
312  }
313  }
314  else // GAP block
315  {
316  if (bd.gap_.ptr != ib_db.gap_.ptr) return false;
317  if (bd.gap_.gap_len != ib_db.gap_.gap_len) return false;
318  }
319  return true;
320  }
321 
322  public:
323 
324  /** Bit-block descriptor
325  @internal
326  */
328  {
329  const bm::word_t* ptr; //!< Word pointer.
330  unsigned char bits[set_bitscan_wave_size*32]; //!< bit list
331  unsigned short idx; //!< Current position in the bit list
332  unsigned short cnt; //!< Number of ON bits
333  size_type pos; //!< Last bit position decode before
334  };
335 
336  /** Information about current DGAP block.
337  @internal
338  */
339  struct dgap_descr
340  {
341  const gap_word_t* ptr; //!< Word pointer.
342  gap_word_t gap_len; //!< Current dgap length.
343  };
344 
345  protected:
346  bm::bvector<Alloc>* bv_; //!< Pointer on parent bitvector
347  size_type position_; //!< Bit position (bit idx)
348  const bm::word_t* block_; //!< Block pointer.(NULL-invalid)
349  unsigned block_type_; //!< Type of block. 0-Bit, 1-GAP
350  block_idx_type block_idx_; //!< Block index
351 
352  /*! Block type dependent information for current block. */
354  {
355  bitblock_descr bit_; //!< BitBlock related info.
356  dgap_descr gap_; //!< DGAP block related info.
357  } bdescr_;
358  };
359 
360  /*!
361  @brief Output iterator iterator designed to set "ON" bits based on
362  input sequence of integers (bit indeces).
363 
364  STL container can be converted to bvector using this iterator
365  Insert iterator guarantees the vector will be dynamically resized
366  (set_bit does not do that).
367 
368  @note
369  If you have many bits to set it is a good idea to use output iterator
370  instead of explicitly calling set, because iterator may implement
371  some performance specific tricks to make sure bulk insert is fast.
372 
373  @sa bulk_insert_iterator
374 
375  @ingroup bvit
376  */
378  {
379  friend class bulk_insert_iterator;
380  public:
381 #ifndef BM_NO_STL
382  typedef std::output_iterator_tag iterator_category;
383 #endif
386  typedef void difference_type;
387  typedef void pointer;
388  typedef void reference;
389 
391 
393  : bvect_(&bvect),
394  max_bit_(bvect.size())
395  {
396  bvect_->init();
397  }
398 
400  : bvect_(iit.bvect_),
401  max_bit_(iit.max_bit_)
402  {
403  }
404 
406  {
407  bvect_ = ii.bvect_; max_bit_ = ii.max_bit_;
408  return *this;
409  }
410 
412  {
413  BM_ASSERT(n < bm::id_max);
414  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
415 
416  if (n >= max_bit_)
417  {
418  max_bit_ = n;
419  if (n >= bvect_->size())
420  {
421  size_type new_size = (n == bm::id_max) ? bm::id_max : n + 1;
422  bvect_->resize(new_size);
423  }
424  }
426  return *this;
427  }
428  /*! Returns *this without doing anything (no-op) */
429  insert_iterator& operator*() { return *this; }
430  /*! Returns *this. This iterator does not move (no-op) */
431  insert_iterator& operator++() { return *this; }
432  /*! Returns *this. This iterator does not move (no-op)*/
433  insert_iterator& operator++(int) { return *this; }
434 
435  bvector_type* get_bvector() const { return bvect_; }
436 
437  protected:
440  };
441 
442 
443  /*!
444  @brief Output iterator iterator designed to set "ON" bits based on
445  input sequence of integers.
446 
447  STL container can be converted to bvector using this iterator
448  Insert iterator guarantees the vector will be dynamically resized
449  (set_bit does not do that).
450 
451  The difference from the canonical insert iterator, is that
452  bulk insert implements internal buffering, which needs
453  to flushed (or flushed automatically when goes out of scope).
454  Buffering creates a delayed effect, which needs to be
455  taken into account.
456 
457  @sa insert_iterator
458 
459  @ingroup bvit
460  */
462  {
463  public:
464 #ifndef BM_NO_STL
465  typedef std::output_iterator_tag iterator_category;
466 #endif
470  typedef void difference_type;
471  typedef void pointer;
472  typedef void reference;
473 
475  : bvect_(0), buf_(0), buf_size_(0), sorted_(BM_UNKNOWN) {}
476 
478  {
479  flush();
480  if (buf_)
481  bvect_->blockman_.get_allocator().free_bit_block((bm::word_t*)buf_);
482  }
483 
486  : bvect_(&bvect), sorted_(so)
487  {
488  bvect_->init();
489 
490  buf_ = (value_type*) bvect_->blockman_.get_allocator().alloc_bit_block();
491  buf_size_ = 0;
492  }
493 
495  : bvect_(iit.bvect_)
496  {
497  buf_ = bvect_->blockman_.get_allocator().alloc_bit_block();
498  buf_size_ = iit.buf_size_;
499  sorted_ = iit.sorted_;
500  ::memcpy(buf_, iit.buf_, buf_size_ * sizeof(*buf_));
501  }
502 
504  : bvect_(iit.get_bvector())
505  {
506  buf_ = (value_type*) bvect_->blockman_.get_allocator().alloc_bit_block();
507  buf_size_ = 0;
509  }
510 
512  : bvect_(iit.bvect_)
513  {
514  buf_ = iit.buf_; iit.buf_ = 0;
515  buf_size_ = iit.buf_size_;
516  sorted_ = iit.sorted_;
517  }
518 
520  {
521  bvect_ = ii.bvect_;
522  if (!buf_)
523  buf_ = bvect_->allocate_tempblock();
524  buf_size_ = ii.buf_size_;
525  ::memcpy(buf_, ii.buf_, buf_size_ * sizeof(*buf_));
526  sorted_ = ii.sorted_;
527  return *this;
528  }
529 
531  {
532  bvect_ = ii.bvect_;
533  if (buf_)
534  bvect_->free_tempblock(buf_);
535  buf_ = ii.buf_; ii.buf_ = 0;
536  buf_size_ = ii.buf_size_;
537  sorted_ = ii.sorted_;
538  return *this;
539  }
540 
542  {
543  BM_ASSERT(n < bm::id_max);
544  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
545 
546  if (buf_size_ == buf_size_max())
547  {
549  buf_size_ = 0;
550  }
551  buf_[buf_size_++] = n;
552  return *this;
553  }
554 
555  /*! Returns *this without doing anything (no-op) */
556  bulk_insert_iterator& operator*() { return *this; }
557  /*! Returns *this. This iterator does not move (no-op) */
558  bulk_insert_iterator& operator++() { return *this; }
559  /*! Returns *this. This iterator does not move (no-op)*/
560  bulk_insert_iterator& operator++(int) { return *this; }
561 
562  /*! Flush the internal buffer into target bvector */
563  void flush()
564  {
565  BM_ASSERT(bvect_);
566  if (buf_size_)
567  {
569  buf_size_ = 0;
570  }
571  bvect_->sync_size();
572  }
573 
575 
576  protected:
577  static
579  {
580  #ifdef BM64ADDR
581  return bm::set_block_size / 2;
582  #else
583  return bm::set_block_size;
584  #endif
585  }
586 
587  protected:
588  bvector_type* bvect_; ///< target bvector
589  size_type* buf_; ///< bulk insert buffer
590  size_type buf_size_; ///< current buffer size
591  bm::sort_order sorted_; ///< sort order hint
592  };
593 
594 
595 
596  /*! @brief Constant iterator designed to enumerate "ON" bits
597  @ingroup bvit
598  */
599  class enumerator : public iterator_base
600  {
601  public:
602 #ifndef BM_NO_STL
603  typedef std::input_iterator_tag iterator_category;
604 #endif
606  typedef unsigned difference_type;
607  typedef unsigned* pointer;
608  typedef unsigned& reference;
609 
610  public:
612  {}
613 
614  /*! @brief Construct enumerator associated with a vector.
615  This construction creates unpositioned iterator with status
616  valid() == false. It can be re-positioned using go_first() or go_to()
617  */
619  : iterator_base()
620  {
621  this->bv_ = const_cast<bvector<Alloc>*>(bv);
622  }
623 
624  /*! @brief Construct enumerator for bit vector
625  @param bv bit-vector pointer
626  @param pos bit position in the vector
627  if position is 0, it finds the next 1 or becomes not valid
628  (en.valid() == false)
629  */
631  : iterator_base()
632  {
633  this->bv_ = const_cast<bvector<Alloc>*>(bv);
634  this->go_to(pos);
635  }
636 
637  /*! \brief Get current position (value) */
638  size_type operator*() const BMNOEXCEPT { return this->position_; }
639 
640  /*! \brief Get current position (value) */
641  size_type value() const BMNOEXCEPT { return this->position_; }
642 
643  /*! \brief Advance enumerator forward to the next available bit */
644  enumerator& operator++() BMNOEXCEPT { this->go_up(); return *this; }
645 
646  /*! \brief Advance enumerator forward to the next available bit.
647  Possibly do NOT use this operator it is slower than the pre-fix increment.
648  */
650  {
651  enumerator tmp = *this;
652  this->go_up();
653  return tmp;
654  }
655 
656  /*! \brief Position enumerator to the first available bit */
657  void go_first() BMNOEXCEPT;
658 
659  /*! advance iterator forward by one
660  @return true if advance was successfull and the enumerator is valid
661  */
662  bool advance() BMNOEXCEPT { return this->go_up(); }
663 
664  /*! \brief Advance enumerator to the next available bit */
665  bool go_up() BMNOEXCEPT;
666 
667  /*!
668  @brief Skip to specified relative rank
669  @param rank - number of ON bits to go for (must be: > 0)
670  @return true if skip was successfull and enumerator is valid
671  */
672  bool skip_to_rank(size_type rank) BMNOEXCEPT
673  {
674  BM_ASSERT(rank);
675  --rank;
676  if (!rank)
677  return this->valid();
678  return skip(rank);
679  }
680 
681  /*!
682  @brief Skip specified number of bits from enumeration
683  @param rank - number of ON bits to skip
684  @return true if skip was successfull and enumerator is valid
685  */
686  bool skip(size_type rank) BMNOEXCEPT;
687 
688  /*!
689  @brief go to a specific position in the bit-vector (or next)
690  */
691  bool go_to(size_type pos) BMNOEXCEPT;
692 
693  private:
694  typedef typename iterator_base::block_descr block_descr_type;
695 
696  static bool decode_wave(block_descr_type* bdescr) BMNOEXCEPT;
697  bool decode_bit_group(block_descr_type* bdescr) BMNOEXCEPT;
698  bool decode_bit_group(block_descr_type* bdescr,
700  bool search_in_bitblock() BMNOEXCEPT;
701  bool search_in_gapblock() BMNOEXCEPT;
702  bool search_in_blocks() BMNOEXCEPT;
703 
704  };
705 
706  /*!
707  @brief Constant iterator designed to enumerate "ON" bits
708  counted_enumerator keeps bitcount, ie number of ON bits starting
709  from the position 0 in the bit string up to the currently enumerated bit
710 
711  When increment operator called current position is increased by 1.
712 
713  @ingroup bvit
714  */
716  {
717  public:
718 #ifndef BM_NO_STL
719  typedef std::input_iterator_tag iterator_category;
720 #endif
721  counted_enumerator() BMNOEXCEPT : bit_count_(0){}
722 
724  {
725  bit_count_ = this->valid(); // 0 || 1
726  }
727 
729  {
730  enumerator* me = this;
731  *me = en;
732  if (this->valid())
733  this->bit_count_ = 1;
734  return *this;
735  }
736 
738  {
739  this->go_up();
740  this->bit_count_ += this->valid();
741  return *this;
742  }
743 
745  {
746  counted_enumerator tmp(*this);
747  this->go_up();
748  this->bit_count_ += this->valid();
749  return tmp;
750  }
751 
752  /*! @brief Number of bits ON starting from the .
753 
754  Method returns number of ON bits fromn the bit 0 to the current bit
755  For the first bit in bitvector it is 1, for the second 2
756  */
757  size_type count() const BMNOEXCEPT { return bit_count_; }
758  private:
759  /*! Function closed for usage */
761 
762  private:
763  size_type bit_count_;
764  };
765 
766  /*!
767  Resource guard for bvector<>::set_allocator_pool()
768  @ingroup bvector
769  @internal
770  */
772  {
773  public:
775  {}
776 
778  : bv_(&bv)
779  {
780  bv.set_allocator_pool(&pool);
781  }
783  {
784  if (bv_)
785  bv_->set_allocator_pool(0);
786  }
787 
788  /// check if vector has no assigned allocator and set one
791  {
792  if (!bv.get_allocator_pool()) // alloc pool not set yet
793  {
794  BM_ASSERT(!bv_);
795  bv_ = &bv;
796  bv_->set_allocator_pool(&pool);
797  }
798  }
799 
800  private:
801  mem_pool_guard(const mem_pool_guard&) = delete;
802  void operator=(const mem_pool_guard&) = delete;
803  private:
804  bvector<Alloc>* bv_; ///< garded object
805  };
806 
807 
808  friend class iterator_base;
809  friend class enumerator;
810  template<class BV> friend class aggregator;
811  template<class BV> friend class operation_deserializer;
812 
813 public:
814  /*! @brief memory allocation policy
815 
816  Defualt memory allocation policy uses BM_BIT, and standard
817  GAP levels tune-ups
818  */
820  {
823 
826  : strat(s), glevel_len(glevels)
827  {}
828  };
829 
830  typedef rs_index<allocator_type> blocks_count;
831  typedef rs_index<allocator_type> rs_index_type;
832 
833 public:
834  /*! @name Construction, initialization, assignment */
835  //@{
836 
837  /*!
838  \brief Constructs bvector class
839  \param strat - operation mode strategy,
840  BM_BIT - default strategy, bvector use plain bitset
841  blocks, (performance oriented strategy).
842  BM_GAP - memory effitent strategy, bvector allocates
843  blocks as array of intervals(gaps) and convert blocks
844  into plain bitsets only when enthropy grows.
845  \param glevel_len
846  - pointer on C-style array keeping GAP block sizes.
847  bm::gap_len_table<true>::_len - default value set
848  (use bm::gap_len_table_min<true>::_len for very sparse vectors)
849  (use bm::gap_len_table_nl<true>::_len non-linear GAP growth)
850  \param bv_size
851  - bvector size (number of bits addressable by bvector), bm::id_max means
852  "no limits" (recommended).
853  bit vector allocates this space dynamically on demand.
854  \param alloc - alllocator for this instance
855 
856  \sa bm::gap_len_table bm::gap_len_table_min set_new_blocks_strat
857  */
859  const gap_word_t* glevel_len = bm::gap_len_table<true>::_len,
860  size_type bv_size = bm::id_max,
861  const Alloc& alloc = Alloc())
862  : blockman_(glevel_len, bv_size, alloc),
863  new_blocks_strat_(strat),
864  size_(bv_size)
865  {}
866 
867  /*!
868  \brief Constructs bvector class
869  */
871  strategy strat = BM_BIT,
872  const gap_word_t* glevel_len = bm::gap_len_table<true>::_len,
873  const Alloc& alloc = Alloc())
874  : blockman_(glevel_len, bv_size, alloc),
875  new_blocks_strat_(strat),
876  size_(bv_size)
877  {}
878 
879  /*!
880  \brief Copy constructor
881  */
883  : blockman_(bvect.blockman_),
884  new_blocks_strat_(bvect.new_blocks_strat_),
885  size_(bvect.size_)
886  {}
887 
888  /*!
889  \brief Copy constructor for range copy [left..right]
890 
891  \sa copy_range
892  */
894  : blockman_(bvect.blockman_.glevel_len_, bvect.blockman_.max_bits_, bvect.blockman_.alloc_),
895  new_blocks_strat_(bvect.new_blocks_strat_),
896  size_(bvect.size_)
897  {
898  if (!bvect.blockman_.is_init())
899  return;
900  if (left > right)
901  bm::xor_swap(left, right);
902  copy_range_no_check(bvect, left, right);
903  }
904 
905 
907  /*!
908  \brief Explicit post-construction initialization
909  */
910  void init();
911 
912  /*!
913  \brief Copy assignment operator
914  */
916  {
917  if (this != &bvect)
918  {
919  blockman_.deinit_tree();
920  blockman_.copy(bvect.blockman_);
921  resize(bvect.size());
922  }
923  return *this;
924  }
925 
926 #ifndef BM_NO_CXX11
927  /*!
928  \brief Move constructor
929  */
931  {
932  blockman_.move_from(bvect.blockman_);
933  size_ = bvect.size_;
934  new_blocks_strat_ = bvect.new_blocks_strat_;
935  }
936 
937  /*!
938  \brief Brace constructor
939  */
940  bvector(std::initializer_list<size_type> il)
941  : blockman_(bm::gap_len_table<true>::_len, bm::id_max, Alloc()),
942  new_blocks_strat_(BM_BIT),
943  size_(bm::id_max)
944  {
945  init();
946  std::initializer_list<size_type>::const_iterator it_start = il.begin();
947  std::initializer_list<size_type>::const_iterator it_end = il.end();
948  for (; it_start < it_end; ++it_start)
949  {
950  this->set_bit_no_check(*it_start);
951  }
952  }
953 
954  /*!
955  \brief Move assignment operator
956  */
958  {
959  this->move_from(bvect);
960  return *this;
961  }
962 #endif
963  /*!
964  \brief Move bvector content from another bvector
965  */
967 
968  /*! \brief Exchanges content of bv and this bvector.
969  */
971 
972  /*! \brief Merge/move content from another vector
973 
974  Merge performs a logical OR operation, but the source vector
975  is not immutable. Source content gets destroyed (memory moved)
976  to create a union of two vectors.
977  Merge operation can be more efficient than OR if argument is
978  a temporary vector.
979 
980  @param bvect - [in, out] - source vector (NOT immutable)
981  */
983 
984  //@}
985 
987  {
988  if (n >= size_)
989  {
990  size_type new_size = (n == bm::id_max) ? bm::id_max : n + 1;
991  resize(new_size);
992  }
993  return reference(*this, n);
994  }
995 
997  {
998  BM_ASSERT(n < size_);
999  return get_bit(n);
1000  }
1001 
1002  void operator &= (const bvector<Alloc>& bv) { bit_and(bv); }
1003  void operator ^= (const bvector<Alloc>& bv) { bit_xor(bv); }
1004  void operator |= (const bvector<Alloc>& bv) { bit_or(bv); }
1005  void operator -= (const bvector<Alloc>& bv) { bit_sub(bv); }
1006 
1007  bool operator < (const bvector<Alloc>& bv) const { return compare(bv)<0; }
1008  bool operator <= (const bvector<Alloc>& bv) const { return compare(bv)<=0; }
1009  bool operator > (const bvector<Alloc>& bv) const { return compare(bv)>0; }
1010  bool operator >= (const bvector<Alloc>& bv) const { return compare(bv) >= 0; }
1011  bool operator == (const bvector<Alloc>& bv) const BMNOEXCEPT { return equal(bv); }
1012  bool operator != (const bvector<Alloc>& bv) const BMNOEXCEPT { return !equal(bv); }
1013 
1014  bvector<Alloc> operator~() const { return bvector<Alloc>(*this).invert(); }
1015 
1016  Alloc get_allocator() const
1017  { return blockman_.get_allocator(); }
1018 
1019  /// Set allocator pool for local (non-th readed)
1020  /// memory cyclic(lots of alloc-free ops) opertations
1021  ///
1023  { blockman_.get_allocator().set_pool(pool_ptr); }
1024 
1025  /// Get curent allocator pool (if set)
1026  /// @return pointer to the current pool or NULL
1028  { return blockman_.get_allocator().get_pool(); }
1029 
1030  // --------------------------------------------------------------------
1031  /*! @name Bit access/modification methods */
1032  //@{
1033 
1034  /*!
1035  \brief Sets bit n.
1036  \param n - index of the bit to be set.
1037  \param val - new bit value
1038  \return TRUE if bit was changed
1039  */
1040  bool set_bit(size_type n, bool val = true);
1041 
1042  /*!
1043  \brief Sets bit n using bit AND with the provided value.
1044  \param n - index of the bit to be set.
1045  \param val - new bit value
1046  \return TRUE if bit was changed
1047  */
1048  bool set_bit_and(size_type n, bool val = true);
1049 
1050  /*!
1051  \brief Increment the specified element
1052 
1053  Bit increment rules:
1054  0 + 1 = 1 (no carry over)
1055  1 + 1 = 0 (with carry over returned)
1056 
1057  \param n - index of the bit to be set
1058  \return TRUE if carry over created (1+1)
1059  */
1060  bool inc(size_type n);
1061 
1062 
1063  /*!
1064  \brief Sets bit n only if current value equals the condition
1065  \param n - index of the bit to be set.
1066  \param val - new bit value
1067  \param condition - expected current value
1068  \return TRUE if bit was changed
1069  */
1070  bool set_bit_conditional(size_type n, bool val, bool condition);
1071 
1072  /*!
1073  \brief Sets bit n if val is true, clears bit n if val is false
1074  \param n - index of the bit to be set
1075  \param val - new bit value
1076  \return *this
1077  */
1078  bvector<Alloc>& set(size_type n, bool val = true);
1079 
1080  /*!
1081  \brief Sets every bit in this bitset to 1.
1082  \return *this
1083  */
1084  bvector<Alloc>& set();
1085 
1086  /*!
1087  \brief Set list of bits in this bitset to 1.
1088 
1089  Method implements optimized bulk setting of multiple bits at once.
1090  The best results are achieved when the imput comes sorted.
1091  This is equivalent of OR (Set Union), argument set as an array.
1092 
1093  @param ids - pointer on array of indexes to set
1094  @param ids_size - size of the input (ids)
1095  @param so - sort order (use BM_SORTED for faster load)
1096 
1097  @sa keep, clear
1098  */
1099  void set(const size_type* ids, size_type ids_size,
1101 
1102  /*!
1103  \brief Keep list of bits in this bitset, others are cleared
1104 
1105  This is equivalent of AND (Set Intersect), argument set as an array.
1106 
1107  @param ids - pointer on array of indexes to set
1108  @param ids_size - size of the input (ids)
1109  @param so - sort order (use BM_SORTED for faster load)
1110 
1111  @sa set, clear
1112  */
1113  void keep(const size_type* ids, size_type ids_size,
1115 
1116  /*!
1117  \brief clear list of bits in this bitset
1118 
1119  This is equivalent of AND NOT (Set Substract), argument set as an array.
1120 
1121  @param ids - pointer on array of indexes to set
1122  @param ids_size - size of the input (ids)
1123  @param so - sort order (use BM_SORTED for faster load)
1124 
1125  @sa set, keep
1126  */
1127  void clear(const size_type* ids, size_type ids_size,
1129 
1130 
1131  /*!
1132  \brief Set bit without checking preconditions (size, etc)
1133 
1134  Fast set bit method, without safety net.
1135  Make sure you call bvector<>::init() before setting bits with this
1136  function.
1137 
1138  \param n - bit number
1139  */
1140  void set_bit_no_check(size_type n);
1141 
1142  /**
1143  \brief Set specified bit without checking preconditions (size, etc)
1144  */
1145  bool set_bit_no_check(size_type n, bool val);
1146 
1147  /*!
1148  \brief Sets all bits in the specified closed interval [left,right]
1149  Interval must be inside the bvector's size.
1150  This method DOES NOT resize vector.
1151 
1152  \param left - interval start
1153  \param right - interval end (closed interval)
1154  \param value - value to set interval in
1155 
1156  \return *this
1157  @sa clear_range
1158  */
1160  size_type right,
1161  bool value = true);
1162 
1163 
1164  /*!
1165  \brief Sets all bits to zero in the specified closed interval [left,right]
1166  Interval must be inside the bvector's size.
1167  This method DOES NOT resize vector.
1168 
1169  \param left - interval start
1170  \param right - interval end (closed interval)
1171 
1172  @sa set_range
1173  */
1174  void clear_range(size_type left, size_type right)
1175  { set_range(left, right, false); }
1176 
1177 
1178  /*!
1179  \brief Sets all bits to zero outside of the closed interval [left,right]
1180  Expected result: 00000...0[left, right]0....0000
1181 
1182  \param left - interval start
1183  \param right - interval end (closed interval)
1184 
1185  @sa set_range
1186  */
1187  void keep_range(size_type left, size_type right);
1188 
1189  /*!
1190  \brief Copy all bits in the specified closed interval [left,right]
1191 
1192  \param bvect - source bit-vector
1193  \param left - interval start
1194  \param right - interval end (closed interval)
1195  */
1196  void copy_range(const bvector<Alloc>& bvect,
1197  size_type left,
1198  size_type right);
1199 
1200  /*!
1201  \brief Clears bit n.
1202  \param n - bit's index to be cleaned.
1203  \return true if bit was cleared
1204  */
1205  bool clear_bit(size_type n) { return set_bit(n, false); }
1206 
1207  /*!
1208  \brief Clears bit n without precondiion checks
1209  \param n - bit's index to be cleaned.
1210  */
1212 
1213  /*!
1214  \brief Clears every bit in the bitvector.
1215 
1216  \param free_mem if "true" (default) bvector frees the memory,
1217  otherwise sets blocks to 0.
1218  */
1219  void clear(bool free_mem = false) { blockman_.set_all_zero(free_mem); }
1220 
1221  /*!
1222  \brief Clears every bit in the bitvector.
1223  \return *this;
1224  */
1225  bvector<Alloc>& reset() { clear(true); return *this; }
1226 
1227  /*!
1228  \brief Flips bit n
1229  \return *this
1230  */
1231  bvector<Alloc>& flip(size_type n) { this->inc(n); return *this; }
1232 
1233  /*!
1234  \brief Flips all bits
1235  \return *this
1236  @sa invert
1237  */
1238  bvector<Alloc>& flip() { return invert(); }
1239 
1240  //@}
1241  // --------------------------------------------------------------------
1242 
1243 
1244  /*! Function erturns insert iterator for this bitvector */
1245  insert_iterator inserter() { return insert_iterator(*this); }
1246 
1247  // --------------------------------------------------------------------
1248  /*! @name Size and capacity
1249  By default bvector is dynamically sized, manual control methods
1250  available
1251  */
1252  //@{
1253 
1254  /** \brief Returns bvector's capacity (number of bits it can store) */
1255  //size_type capacity() const { return blockman_.capacity(); }
1256 
1257  /*! \brief return current size of the vector (bits) */
1258  size_type size() const BMNOEXCEPT { return size_; }
1259 
1260  /*!
1261  \brief Change size of the bvector
1262  \param new_size - new size in bits
1263  */
1264  void resize(size_type new_size);
1265 
1266  //@}
1267  // --------------------------------------------------------------------
1268 
1269  /*! @name Population counting, ranks, ranges and intervals
1270  */
1271  //@{
1272 
1273  /*!
1274  \brief population cout (count of ON bits)
1275  \sa count_range
1276  \return Total number of bits ON
1277  */
1278  size_type count() const BMNOEXCEPT;
1279 
1280  /*! \brief Computes bitcount values for all bvector blocks
1281  \param arr - pointer on array of block bit counts
1282  \return Index of the last block counted.
1283  This number +1 gives you number of arr elements initialized during the
1284  function call.
1285  */
1286  block_idx_type count_blocks(unsigned* arr) const BMNOEXCEPT;
1287 
1288 
1289  /*!
1290  \brief Returns count of 1 bits in the given range [left..right]
1291  Uses rank-select index to accelerate the search
1292  \param left - index of first bit start counting from
1293  \param right - index of last bit
1294  \param rs_idx - block count structure to accelerate search
1295  \sa build_rs_index
1296 
1297  \return population count in the diapason
1298  */
1300  size_type right,
1301  const rs_index_type& rs_idx) const BMNOEXCEPT;
1302 
1303  /*!
1304  \brief Returns count of 1 bits in the given range [left..right]
1305 
1306  \param left - index of first bit start counting from
1307  \param right - index of last bit
1308 
1309  \return population count in the diapason
1310  */
1311  size_type count_range(size_type left, size_type right) const BMNOEXCEPT;
1312 
1313  /*!
1314  \brief Returns true if all bits in the range are 1s (saturated interval)
1315  Function uses closed interval [left, right]
1316 
1317  \param left - index of first bit start checking
1318  \param right - index of last bit
1319 
1320  \return true if all bits are 1, false otherwise
1321  @sa any_range, count_range
1322  */
1323  bool is_all_one_range(size_type left, size_type right) const BMNOEXCEPT;
1324 
1325  /*!
1326  \brief Returns true if any bits in the range are 1s (non-empty interval)
1327  Function uses closed interval [left, right]
1328 
1329  \param left - index of first bit start checking
1330  \param right - index of last bit
1331 
1332  \return true if at least 1 bits is set
1333  @sa is_all_one_range, count_range
1334  */
1335  bool any_range(size_type left, size_type right) const BMNOEXCEPT;
1336 
1337 
1338  /*! \brief compute running total of all blocks in bit vector (rank-select index)
1339  \param rs_idx - [out] pointer to index / count structure
1340  \param bv_blocks - [out] list of block ids in the vector (internal, optional)
1341  Function will fill full array of running totals
1342  \sa count_to, select, find_rank
1343  */
1344  void build_rs_index(rs_index_type* rs_idx, bvector<Alloc>* bv_blocks=0) const;
1345 
1346  /*!
1347  \brief Returns count of 1 bits (population) in [0..right] range.
1348 
1349  This operation is also known as rank of bit N.
1350 
1351  \param n - index of bit to rank
1352  \param rs_idx - rank-select to accelerate search
1353  should be prepared using build_rs_index
1354  \return population count in the range [0..n]
1355  \sa build_rs_index
1356  \sa count_to_test, select, rank, rank_corrected
1357  */
1359  const rs_index_type& rs_idx) const BMNOEXCEPT;
1360 
1361 
1362  /*!
1363  \brief Returns rank of specified bit position (same as count_to())
1364 
1365  \param n - index of bit to rank
1366  \param rs_idx - rank-select index
1367  \return population count in the range [0..n]
1368  \sa build_rs_index
1369  \sa count_to_test, select, rank, rank_corrected
1370  */
1372  const rs_index_type& rs_idx) const BMNOEXCEPT
1373  { return count_to(n, rs_idx); }
1374 
1375  /*!
1376  \brief Returns rank corrceted by the requested border value (as -1)
1377 
1378  This is rank function (bit-count) minus value of bit 'n'
1379  if bit-n is true function returns rank()-1 if false returns rank()
1380  faster than rank() + test().
1381 
1382 
1383  \param n - index of bit to rank
1384  \param rs_idx - rank-select index
1385  \return population count in the range [0..n] corrected as -1 by the value of n
1386  \sa build_rs_index
1387  \sa count_to_test, select, rank
1388  */
1390  const rs_index_type& rs_idx) const BMNOEXCEPT;
1391 
1392  /*!
1393  \brief popcount in [0..right] range if test(right) == true
1394 
1395  This is conditional rank operation, which is faster than test()
1396  plus count_to()
1397 
1398  \param n - index of bit to test and rank
1399  \param rs_idx - rank-select index
1400  (block count structure to accelerate search)
1401  should be prepared using build_rs_index()
1402 
1403  \return population count in the diapason or 0 if right bit test failed
1404 
1405  \sa build_rs_index
1406  \sa count_to
1407  */
1408  size_type
1410  const rs_index_type& rs_idx) const BMNOEXCEPT;
1411 
1412 
1413  /*! Recalculate bitcount (deprecated)
1414  */
1416 
1417  /*!
1418  Disables count cache. (deprecated).
1419  */
1421 
1422  //@}
1423 
1424  // --------------------------------------------------------------------
1425  /*! @name Bit access (read-only) */
1426  //@{
1427 
1428  /*!
1429  \brief returns true if bit n is set and false is bit n is 0.
1430  \param n - Index of the bit to check.
1431  \return Bit value (1 or 0)
1432  */
1433  bool get_bit(size_type n) const BMNOEXCEPT;
1434 
1435  /*!
1436  \brief returns true if bit n is set and false is bit n is 0.
1437  \param n - Index of the bit to check.
1438  \return Bit value (1 or 0)
1439  */
1440  bool test(size_type n) const BMNOEXCEPT { return get_bit(n); }
1441 
1442  //@}
1443 
1444  // --------------------------------------------------------------------
1445  /*! @name bit-shift and insert operations */
1446  //@{
1447 
1448  /*!
1449  \brief Shift right by 1 bit, fill with zero return carry out
1450  \return Carry over bit value (1 or 0)
1451  */
1452  bool shift_right();
1453 
1454  /*!
1455  \brief Shift left by 1 bit, fill with zero return carry out
1456  \return Carry over bit value (1 or 0)
1457  */
1458  bool shift_left();
1459 
1460  /*!
1461  \brief Insert bit into specified position
1462  All the vector content after insert position is shifted right.
1463 
1464  \param n - index of the bit to insert
1465  \param value - insert value
1466 
1467  \return Carry over bit value (1 or 0)
1468  */
1469  bool insert(size_type n, bool value);
1470 
1471  /*!
1472  \brief Erase bit in the specified position
1473  All the vector content after erase position is shifted left.
1474 
1475  \param n - index of the bit to insert
1476  */
1477  void erase(size_type n);
1478 
1479  //@}
1480 
1481  // --------------------------------------------------------------------
1482  /*! @name Check for empty-ness of container */
1483  //@{
1484 
1485  /*!
1486  \brief Returns true if any bits in this bitset are set, and otherwise returns false.
1487  \return true if any bit is set
1488  */
1489  bool any() const BMNOEXCEPT;
1490 
1491  /*!
1492  \brief Returns true if no bits are set, otherwise returns false.
1493  */
1494  bool none() const BMNOEXCEPT { return !any(); }
1495 
1496  //@}
1497  // --------------------------------------------------------------------
1498 
1499  /*! @name Scan and find bits and indexes */
1500  //@{
1501 
1502  /*!
1503  \fn bool bvector::find(bm::id_t& pos) const
1504  \brief Finds index of first 1 bit
1505  \param pos - [out] index of the found 1 bit
1506  \return true if search returned result
1507  \sa get_first, get_next, extract_next, find_reverse, find_first_mismatch
1508  */
1509  bool find(size_type& pos) const BMNOEXCEPT;
1510 
1511  /*!
1512  \fn bool bvector::find(bm::id_t from, bm::id_t& pos) const
1513  \brief Find index of 1 bit starting from position
1514  \param from - position to start search from
1515  \param pos - [out] index of the found 1 bit
1516  \return true if search returned result
1517  \sa get_first, get_next, extract_next, find_reverse, find_first_mismatch
1518  */
1519  bool find(size_type from, size_type& pos) const BMNOEXCEPT;
1520 
1521 
1522  /*!
1523  \fn bm::id_t bvector::get_first() const
1524  \brief find first 1 bit in vector.
1525  Function may return 0 and this requires an extra check if bit 0 is
1526  actually set or bit-vector is empty
1527 
1528  \return Index of the first 1 bit, may return 0
1529  \sa get_next, find, extract_next, find_reverse
1530  */
1531  size_type get_first() const BMNOEXCEPT { return check_or_next(0); }
1532 
1533  /*!
1534  \fn bm::id_t bvector::get_next(bm::id_t prev) const
1535  \brief Finds the number of the next bit ON.
1536  \param prev - Index of the previously found bit.
1537  \return Index of the next bit which is ON or 0 if not found.
1538  \sa get_first, find, extract_next, find_reverse
1539  */
1541  { return (++prev == bm::id_max) ? 0 : check_or_next(prev); }
1542 
1543  /*!
1544  \fn bm::id_t bvector::extract_next(bm::id_t prev)
1545  \brief Finds the number of the next bit ON and sets it to 0.
1546  \param prev - Index of the previously found bit.
1547  \return Index of the next bit which is ON or 0 if not found.
1548  \sa get_first, get_next, find_reverse
1549  */
1551  {
1552  return (++prev == bm::id_max) ? 0 : check_or_next_extract(prev);
1553  }
1554 
1555  /*!
1556  \brief Finds last index of 1 bit
1557  \param pos - index of the last found 1 bit
1558  \return true if search returned result
1559  \sa get_first, get_next, extract_next, find, find_first_mismatch
1560  */
1561  bool find_reverse(size_type& pos) const BMNOEXCEPT;
1562 
1563  /*!
1564  \brief Finds dynamic range of bit-vector [first, last]
1565  \param first - index of the first found 1 bit
1566  \param last - index of the last found 1 bit
1567  \return true if search returned result
1568  \sa get_first, get_next, extract_next, find, find_reverse
1569  */
1570  bool find_range(size_type& first, size_type& last) const BMNOEXCEPT;
1571 
1572  /*!
1573  \brief Find bit-vector position for the specified rank(bitcount)
1574 
1575  Rank based search, counts number of 1s from specified position until
1576  finds the ranked position relative to start from position.
1577  In other words: range population count between from and pos == rank.
1578 
1579  \param rank - rank to find (bitcount)
1580  \param from - start positioon for rank search
1581  \param pos - position with speciefied rank (relative to from position)
1582 
1583  \return true if requested rank was found
1584  */
1585  bool find_rank(size_type rank, size_type from,
1586  size_type& pos) const BMNOEXCEPT;
1587 
1588  /*!
1589  \brief Find bit-vector position for the specified rank(bitcount)
1590 
1591  Rank based search, counts number of 1s from specified position until
1592  finds the ranked position relative to start from position.
1593  In other words: range population count between from and pos == rank.
1594 
1595  \param rank - rank to find (bitcount)
1596  \param from - start positioon for rank search
1597  \param pos - position with speciefied rank (relative to from position)
1598  \param rs_idx - rank-select index to accelarate search
1599  (should be prepared using build_rs_index)
1600 
1601  \sa build_rs_index, select
1602 
1603  \return true if requested rank was found
1604  */
1605  bool find_rank(size_type rank, size_type from, size_type& pos,
1606  const rs_index_type& rs_idx) const BMNOEXCEPT;
1607 
1608  /*!
1609  \brief select bit-vector position for the specified rank(bitcount)
1610 
1611  Rank based search, counts number of 1s from specified position until
1612  finds the ranked position relative to start from position.
1613  Uses
1614  In other words: range population count between from and pos == rank.
1615 
1616  \param rank - rank to find (bitcount)
1617  \param pos - position with speciefied rank (relative to from position) [out]
1618  \param rs_idx - block count structure to accelerate rank search
1619 
1620  \sa running_count_blocks, find_rank
1621 
1622  \return true if requested rank was found
1623  */
1624  bool select(size_type rank, size_type& pos,
1625  const rs_index_type& rs_idx) const BMNOEXCEPT;
1626 
1627  //@}
1628 
1629 
1630  // --------------------------------------------------------------------
1631  /*! @name Algebra of Sets operations */
1632  //@{
1633 
1634  /*!
1635  \brief 3-operand OR : this := bv1 OR bv2
1636  \param bv1 - Argument vector 1
1637  \param bv2 - Argument vector 2
1638  \param opt_mode - optimization compression
1639  (when it is performed on the fly it is faster than a separate
1640  call to optimize()
1641  @sa optimize, bit_or
1642  */
1644  const bm::bvector<Alloc>& bv2,
1645  typename bm::bvector<Alloc>::optmode opt_mode);
1646 
1647  /*!
1648  \brief 3-operand XOR : this := bv1 XOR bv2
1649  \param bv1 - Argument vector 1
1650  \param bv2 - Argument vector 2
1651  \param opt_mode - optimization compression
1652  (when it is performed on the fly it is faster than a separate
1653  call to optimize()
1654  @sa optimize, bit_xor
1655  */
1657  const bm::bvector<Alloc>& bv2,
1658  typename bm::bvector<Alloc>::optmode opt_mode);
1659 
1660  /*!
1661  \brief 3-operand AND : this := bv1 AND bv2
1662  \param bv1 - Argument vector 1
1663  \param bv2 - Argument vector 2
1664  \param opt_mode - optimization compression
1665  (when it is performed on the fly it is faster than a separate
1666  call to optimize()
1667  @sa optimize, bit_and
1668  */
1670  const bm::bvector<Alloc>& bv2,
1671  typename bm::bvector<Alloc>::optmode opt_mode);
1672 
1673 
1674  /*!
1675  \brief 3-operand SUB : this := bv1 MINUS bv2
1676  SUBtraction is also known as AND NOT
1677  \param bv1 - Argument vector 1
1678  \param bv2 - Argument vector 2
1679  \param opt_mode - optimization compression
1680  (when it is performed on the fly it is faster than a separate
1681  call to optimize()
1682  @sa optimize, bit_sub
1683  */
1685  const bm::bvector<Alloc>& bv2,
1686  typename bm::bvector<Alloc>::optmode opt_mode);
1687 
1688 
1689  /*!
1690  \brief 2 operand logical OR
1691  \param bv - Argument vector.
1692  */
1694  {
1696  return *this;
1697  }
1698 
1699  /*!
1700  \brief 2 operand logical AND
1701  \param bv - argument vector
1702  \param opt_mode - set an immediate optimization
1703  */
1705  optmode opt_mode = opt_none)
1706  {
1707  combine_operation_and(bv, opt_mode);
1708  return *this;
1709  }
1710 
1711  /*!
1712  \brief 2 operand logical XOR
1713  \param bv - argument vector.
1714  */
1716  {
1718  return *this;
1719  }
1720 
1721  /*!
1722  \brief 2 operand logical SUB(AND NOT). Also known as MINUS.
1723  \param bv - argument vector.
1724  */
1726  {
1728  return *this;
1729  }
1730 
1731  /*!
1732  \brief Invert/NEG all bits
1733  It should be noted, invert is affected by size()
1734  if size is set - it only inverts [0..size-1] bits
1735  */
1737 
1738 
1739  /*! \brief perform a set-algebra operation by operation code
1740  */
1742  bm::operation opcode);
1743 
1744  /*! \brief perform a set-algebra operation OR
1745  */
1747 
1748  /*! \brief perform a set-algebra operation AND
1749  */
1751  optmode opt_mode);
1752 
1753  /*! \brief perform a set-algebra operation MINUS (AND NOT)
1754  */
1756 
1757  /*! \brief perform a set-algebra operation XOR
1758  */
1760 
1761  // @}
1762 
1763  // --------------------------------------------------------------------
1764  /*! @name Iterator-traversal methods */
1765  //@{
1766 
1767  /**
1768  \brief Returns enumerator pointing on the first non-zero bit.
1769  */
1770  enumerator first() const { return get_enumerator(0); }
1771 
1772  /**
1773  \fn bvector::enumerator bvector::end() const
1774  \brief Returns enumerator pointing on the next bit after the last.
1775  */
1776  enumerator end() const
1777  { return typename bvector<Alloc>::enumerator(this); }
1778 
1779  /**
1780  \brief Returns enumerator pointing on specified or the next available bit.
1781  */
1783  { return typename bvector<Alloc>::enumerator(this, pos); }
1784 
1785  //@}
1786 
1787  // --------------------------------------------------------------------
1788  /*! @name Memory management and compression */
1789 
1790  //@{
1791 
1792  /*!
1793  @brief Calculates bitvector statistics.
1794 
1795  @param st - pointer on statistics structure to be filled in.
1796 
1797  Function fills statistics structure containing information about how
1798  this vector uses memory and estimation of max. amount of memory
1799  bvector needs to serialize itself.
1800 
1801  @sa statistics
1802  */
1803  void calc_stat(struct bm::bvector<Alloc>::statistics* st) const BMNOEXCEPT;
1804 
1805  /*!
1806  \brief Sets new blocks allocation strategy.
1807  \param strat - Strategy code 0 - bitblocks allocation only.
1808  1 - Blocks mutation mode (adaptive algorithm)
1809  */
1810  void set_new_blocks_strat(strategy strat) { new_blocks_strat_ = strat; }
1811 
1812  /*!
1813  \brief Returns blocks allocation strategy.
1814  \return - Strategy code 0 - bitblocks allocation only.
1815  1 - Blocks mutation mode (adaptive algorithm)
1816  \sa set_new_blocks_strat
1817  */
1819  { return new_blocks_strat_; }
1820 
1821  /*!
1822  \brief Optimize memory bitvector's memory allocation.
1823 
1824  Function analyze all blocks in the bitvector, compresses blocks
1825  with a regular structure, frees some memory. This function is recommended
1826  after a bulk modification of the bitvector using set_bit, clear_bit or
1827  logical operations.
1828 
1829  Optionally function can calculate vector post optimization statistics
1830 
1831  @sa optmode, optimize_gap_size
1832  */
1833  void optimize(bm::word_t* temp_block = 0,
1834  optmode opt_mode = opt_compress,
1835  statistics* stat = 0);
1836 
1837  /*!
1838  \brief Optimize sizes of GAP blocks
1839 
1840  This method runs an analysis to find optimal GAP levels for the
1841  specific vector. Current GAP compression algorithm uses several fixed
1842  GAP sizes. By default bvector uses some reasonable preset.
1843  */
1844  void optimize_gap_size();
1845 
1846  /*!
1847  @brief Sets new GAP lengths table. All GAP blocks will be reallocated
1848  to match the new scheme.
1849 
1850  @param glevel_len - pointer on C-style array keeping GAP block sizes.
1851  */
1852  void set_gap_levels(const gap_word_t* glevel_len);
1853 
1854  /**
1855  Return true if bvector is initialized at all
1856  @internal
1857  */
1858  bool is_init() const BMNOEXCEPT { return blockman_.is_init(); }
1859 
1860  //@}
1861 
1862  // --------------------------------------------------------------------
1863 
1864  /*! @name Comparison */
1865  //@{
1866 
1867  /*!
1868  \brief Lexicographical comparison with a bitvector.
1869 
1870  Function compares current bitvector with the provided argument
1871  bit by bit and returns -1 if this bitvector less than the argument,
1872  1 - greater, 0 - equal
1873 
1874  @return 0 if this == arg, -1 if this < arg, 1 if this > arg
1875  @sa find_first_mismatch
1876  */
1877  int compare(const bvector<Alloc>& bvect) const BMNOEXCEPT;
1878 
1879  /*!
1880  \brief Equal comparison with an agr bit-vector
1881  @return true if vectors are identical
1882  */
1884  {
1885  size_type pos;
1886  bool found = find_first_mismatch(bvect, pos);
1887  return !found;
1888  }
1889 
1890  /*!
1891  \brief Find index of first bit different between this and the agr vector
1892 
1893  @param bvect - argumnet vector to compare with
1894  @param pos - [out] position of the first difference
1895  @param search_to - search limiter [0..to] to avoid overscan
1896  (default: unlimited to the vectors end)
1897 
1898  @return true if didfference found, false - both vectors are equivalent
1899  @sa compare
1900  */
1902  size_type& pos,
1903  size_type search_to = bm::id_max
1904  ) const BMNOEXCEPT;
1905 
1906  //@}
1907 
1908  // --------------------------------------------------------------------
1909  /*! @name Open internals */
1910  //@{
1911 
1912  /*!
1913  @internal
1914  */
1916  const bm::word_t* arg_blk,
1917  bool arg_gap,
1918  bm::operation opcode);
1919  /**
1920  \brief get access to memory manager (internal)
1921  Use only if you are BitMagic library
1922  @internal
1923  */
1925  { return blockman_; }
1926 
1927  /**
1928  \brief get access to memory manager (internal)
1929  Use only if you are BitMagic library
1930  @internal
1931  */
1933  { return blockman_; }
1934 
1935  //@}
1936 
1937  static void throw_bad_alloc();
1938 
1939 protected:
1940  /**
1941  Syncronize size if it got extended due to bulk import
1942  @internal
1943  */
1944  void sync_size();
1945 
1946  /**
1947  Import integers (set bits).
1948  (Fast, no checks).
1949  @internal
1950  */
1951  void import(const size_type* ids, size_type ids_size,
1952  bm::sort_order sorted_idx);
1953 
1954  void import_block(const size_type* ids,
1955  block_idx_type nblock, size_type start, size_type stop);
1956 
1957 private:
1958 
1959  size_type check_or_next(size_type prev) const BMNOEXCEPT;
1960 
1961  /// set bit in GAP block with GAP block length control
1962  bool gap_block_set(bm::gap_word_t* gap_blk,
1963  bool val, block_idx_type nblock, unsigned nbit);
1964 
1965  /// set bit in GAP block with GAP block length control
1966  void gap_block_set_no_ret(bm::gap_word_t* gap_blk,
1967  bool val, block_idx_type nblock,
1968  unsigned nbit);
1969 
1970  /// check if specified bit is 1, and set it to 0
1971  /// if specified bit is 0, scan for the next 1 and returns it
1972  /// if no 1 found returns 0
1973  size_type check_or_next_extract(size_type prev);
1974 
1975 
1976  /**
1977  \brief AND specified bit without checking preconditions (size, etc)
1978  */
1979  bool and_bit_no_check(size_type n, bool val);
1980 
1981  bool set_bit_conditional_impl(size_type n, bool val, bool condition);
1982 
1983 
1985  bool gap,
1986  bm::word_t* blk,
1987  const bm::word_t* arg_blk,
1988  bool arg_gap,
1989  bm::operation opcode);
1990 
1991  /**
1992  @return true if block optimization may be needed
1993  */
1994  bool combine_operation_block_or(unsigned i,
1995  unsigned j,
1996  const bm::word_t* arg_blk1,
1997  const bm::word_t* arg_blk2);
1998  bool combine_operation_block_xor(unsigned i,
1999  unsigned j,
2000  const bm::word_t* arg_blk1,
2001  const bm::word_t* arg_blk2);
2002  bool combine_operation_block_and(unsigned i,
2003  unsigned j,
2004  const bm::word_t* arg_blk1,
2005  const bm::word_t* arg_blk2);
2006  bool combine_operation_block_sub(unsigned i,
2007  unsigned j,
2008  const bm::word_t* arg_blk1,
2009  const bm::word_t* arg_blk2);
2010 
2011 
2012  void combine_operation_block_or(unsigned i,
2013  unsigned j,
2014  bm::word_t* blk,
2015  const bm::word_t* arg_blk);
2016 
2017  void combine_operation_block_xor(unsigned i,
2018  unsigned j,
2019  bm::word_t* blk,
2020  const bm::word_t* arg_blk);
2021 
2022  void combine_operation_block_and(unsigned i,
2023  unsigned j,
2024  bm::word_t* blk,
2025  const bm::word_t* arg_blk);
2026 
2027  void combine_operation_block_sub(unsigned i,
2028  unsigned j,
2029  bm::word_t* blk,
2030  const bm::word_t* arg_blk);
2031 
2032  void copy_range_no_check(const bvector<Alloc>& bvect,
2033  size_type left,
2034  size_type right);
2035 
2036 private:
2037 
2038  /**
2039  \brief Set range without validity/bounds checking
2040  */
2041  void set_range_no_check(size_type left,
2042  size_type right);
2043  /**
2044  \brief Clear range without validity/bounds checking
2045  */
2046  void clear_range_no_check(size_type left,
2047  size_type right);
2048 
2049  /**
2050  \brief Clear outside the range without validity/bounds checking
2051  */
2052  void keep_range_no_check(size_type left,
2053  size_type right);
2054 
2055  /**
2056  Compute rank in block using rank-select index
2057  */
2058  static
2059  size_type block_count_to(const bm::word_t* block,
2060  block_idx_type nb,
2061  unsigned nbit_right,
2062  const rs_index_type& blocks_cnt) BMNOEXCEPT;
2063  /**
2064  Return value of first bit in the block
2065  */
2066  bool test_first_block_bit(block_idx_type nb) const BMNOEXCEPT;
2067 
2068 private:
2069  blocks_manager_type blockman_; //!< bitblocks manager
2070  strategy new_blocks_strat_; //!< block allocation strategy
2071  size_type size_; //!< size in bits
2072 };
2073 
2074 
2075 //---------------------------------------------------------------------
2076 
2077 template<class Alloc>
2079  const bvector<Alloc>& bv2)
2080 {
2081  bvector<Alloc> ret;
2082  ret.bit_and(bv1, bv2, bvector<Alloc>::opt_none);
2083  return ret;
2084 }
2085 
2086 //---------------------------------------------------------------------
2087 
2088 template<class Alloc>
2090  const bvector<Alloc>& bv2)
2091 {
2092  bvector<Alloc> ret;
2093  ret.bit_or(bv1, bv2, bvector<Alloc>::opt_none);
2094  return ret;
2095 }
2096 
2097 //---------------------------------------------------------------------
2098 
2099 template<class Alloc>
2101  const bvector<Alloc>& bv2)
2102 {
2103  bvector<Alloc> ret;
2104  ret.bit_xor(bv1, bv2, bvector<Alloc>::opt_none);
2105  return ret;
2106 }
2107 
2108 //---------------------------------------------------------------------
2109 
2110 template<class Alloc>
2112  const bvector<Alloc>& bv2)
2113 {
2114  bvector<Alloc> ret;
2115  ret.bit_sub(bv1, bv2, bvector<Alloc>::opt_none);
2116  return ret;
2117 }
2118 
2119 
2120 // -----------------------------------------------------------------------
2121 
2122 template<typename Alloc>
2124 {
2125  if (!blockman_.is_init())
2126  blockman_.init_tree();
2127 }
2128 
2129 // -----------------------------------------------------------------------
2130 
2131 template<typename Alloc>
2133 {
2134  if (this != &bvect)
2135  {
2136  blockman_.move_from(bvect.blockman_);
2137  size_ = bvect.size_;
2138  new_blocks_strat_ = bvect.new_blocks_strat_;
2139  }
2140 }
2141 
2142 //---------------------------------------------------------------------
2143 
2144 template<class Alloc>
2146 {
2147  if (!blockman_.is_init())
2148  return; // nothing to do
2149 
2150  if (right < left)
2151  bm::xor_swap(left, right);
2152 
2153  keep_range_no_check(left, right);
2154 }
2155 // -----------------------------------------------------------------------
2156 
2157 template<typename Alloc>
2159  size_type right,
2160  bool value)
2161 {
2162  if (!blockman_.is_init())
2163  {
2164  if (!value)
2165  return *this; // nothing to do
2166  }
2167 
2168  if (right < left)
2169  {
2170  return set_range(right, left, value);
2171  }
2172 
2173  BM_ASSERT_THROW(right < bm::id_max, BM_ERR_RANGE);
2174  if (right >= size_) // this vect shorter than the arg.
2175  {
2176  size_type new_size = (right == bm::id_max) ? bm::id_max : right + 1;
2177  resize(new_size);
2178  }
2179 
2180  BM_ASSERT(left <= right);
2181  BM_ASSERT(left < size_);
2182 
2183  if (value)
2184  set_range_no_check(left, right);
2185  else
2186  clear_range_no_check(left, right);
2187 
2188  return *this;
2189 }
2190 
2191 // -----------------------------------------------------------------------
2192 
2193 template<typename Alloc>
2195 {
2196  if (!blockman_.is_init())
2197  return 0;
2198 
2199  word_t*** blk_root = blockman_.top_blocks_root();
2200  BM_ASSERT(blk_root);
2201 
2202  size_type cnt = 0;
2203  unsigned top_blocks = blockman_.top_block_size();
2204  for (unsigned i = 0; i < top_blocks; ++i)
2205  {
2206  bm::word_t** blk_blk = blk_root[i];
2207  if (!blk_blk)
2208  {
2209  ++i;
2210  bool found = bm::find_not_null_ptr(blk_root, i, top_blocks, &i);
2211  if (!found)
2212  break;
2213  blk_blk = blk_root[i];
2214  BM_ASSERT(blk_blk);
2215  if (!blk_blk)
2216  break;
2217  }
2218  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
2219  {
2221  continue;
2222  }
2223  unsigned j = 0;
2224  do
2225  {
2226  if (blk_blk[j])
2227  cnt += blockman_.block_bitcount(blk_blk[j]);
2228  if (blk_blk[j+1])
2229  cnt += blockman_.block_bitcount(blk_blk[j+1]);
2230  if (blk_blk[j+2])
2231  cnt += blockman_.block_bitcount(blk_blk[j+2]);
2232  if (blk_blk[j+3])
2233  cnt += blockman_.block_bitcount(blk_blk[j+3]);
2234  j += 4;
2235  } while (j < bm::set_sub_array_size);
2236 
2237  } // for i
2238  return cnt;
2239 }
2240 
2241 // -----------------------------------------------------------------------
2242 
2243 template<typename Alloc>
2245 {
2246  word_t*** blk_root = blockman_.top_blocks_root();
2247  if (!blk_root)
2248  return false;
2249  typename blocks_manager_type::block_any_func func(blockman_);
2250  return for_each_nzblock_if(blk_root, blockman_.top_block_size(), func);
2251 }
2252 
2253 // -----------------------------------------------------------------------
2254 
2255 template<typename Alloc>
2257 {
2258  if (size_ == new_size) return; // nothing to do
2259  if (size_ < new_size) // size grows
2260  {
2261  if (!blockman_.is_init())
2262  blockman_.init_tree();
2263 
2264  blockman_.reserve(new_size);
2265  size_ = new_size;
2266  }
2267  else // shrink
2268  {
2269  set_range(new_size, size_ - 1, false); // clear the tail
2270  size_ = new_size;
2271  }
2272 }
2273 
2274 // -----------------------------------------------------------------------
2275 
2276 template<typename Alloc>
2278 {
2279  if (size_ >= bm::id_max)
2280  return;
2282  bool found = find_reverse(last);
2283  if (found && last >= size_)
2284  resize(last+1);
2285 }
2286 
2287 // -----------------------------------------------------------------------
2288 
2289 template<typename Alloc>
2291  bvector<Alloc>* bv_blocks) const
2292 {
2293  BM_ASSERT(rs_idx);
2294  if (bv_blocks)
2295  {
2296  bv_blocks->clear();
2297  bv_blocks->init();
2298  }
2299 
2300  unsigned bcount[bm::set_sub_array_size];
2301  unsigned sub_count[bm::set_sub_array_size];
2302 
2303  rs_idx->init();
2304  if (!blockman_.is_init())
2305  return;
2306 
2307  // resize the RS index to fit the vector
2308  //
2309  size_type last_bit;
2310  bool found = find_reverse(last_bit);
2311  if (!found)
2312  return;
2313  block_idx_type nb = (last_bit >> bm::set_block_shift);
2314  unsigned i0, j0;
2315  bm::get_block_coord(nb, i0, j0);
2316 
2317  unsigned real_top_blocks = blockman_.find_real_top_blocks();
2318  unsigned max_top_blocks = blockman_.find_max_top_blocks();
2319  if (nb < (max_top_blocks * bm::set_sub_array_size))
2320  nb = (max_top_blocks * bm::set_sub_array_size);
2321  rs_idx->set_total(nb + 1);
2322  rs_idx->resize(nb + 1);
2323  rs_idx->resize_effective_super_blocks(real_top_blocks);
2324 
2325  // index construction
2326  //
2327  BM_ASSERT(max_top_blocks <= blockman_.top_block_size());
2328  bm::word_t*** blk_root = blockman_.top_blocks_root();
2329  for (unsigned i = 0; i < max_top_blocks; ++i)
2330  {
2331  bm::word_t** blk_blk = blk_root[i];
2332  if (!blk_blk)
2333  {
2334  rs_idx->set_null_super_block(i);
2335  continue;
2336  }
2337  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
2338  {
2339  rs_idx->set_full_super_block(i);
2340  if (bv_blocks)
2341  {
2342  size_type nb_from = i * bm::set_sub_array_size;
2343  size_type nb_to = nb_from + bm::set_sub_array_size - 1;
2344  bv_blocks->set_range_no_check(nb_from, nb_to);
2345  }
2346  continue;
2347  }
2348 
2349  unsigned j = 0;
2350  do
2351  {
2352  const bm::word_t* block = blk_blk[j];
2353  if (!block)
2354  {
2355  bcount[j] = sub_count[j] = 0;
2356  continue;
2357  }
2358 
2359  unsigned cnt = blockman_.block_bitcount(block);
2360  bcount[j] = cnt;
2361  if (bv_blocks && cnt)
2362  {
2363  bv_blocks->set(i * bm::set_sub_array_size + j);
2364  }
2365 
2366  // TODO: optimize sub-index compute
2367  unsigned local_first, local_second;
2368  if (BM_IS_GAP(block))
2369  {
2370  const bm::gap_word_t* const gap_block = BMGAP_PTR(block);
2371  local_first =
2373  local_second =
2374  bm::gap_bit_count_range(gap_block,
2376  bm::rs3_border1);
2377  }
2378  else
2379  {
2380  block = BLOCK_ADDR_SAN(block); // TODO: optimize FULL
2381 
2382  local_first =
2384  local_second =
2386  bm::rs3_border0+1,
2387  bm::rs3_border1);
2388  }
2389  BM_ASSERT(cnt >= local_first + local_second);
2390  sub_count[j] = local_first | (local_second << 16);
2391 
2392  } while (++j < bm::set_sub_array_size);
2393 
2394  rs_idx->register_super_block(i, &bcount[0], &sub_count[0]);
2395 
2396  } // for i
2397 
2398 }
2399 
2400 
2401 // -----------------------------------------------------------------------
2402 
2403 template<typename Alloc>
2406 {
2407  bm::word_t*** blk_root = blockman_.top_blocks_root();
2408  if (blk_root == 0)
2409  return 0;
2410  typename blocks_manager_type::block_count_arr_func func(blockman_, &(arr[0]));
2411  bm::for_each_nzblock(blk_root, blockman_.top_block_size(), func);
2412  return func.last_block();
2413 }
2414 
2415 // -----------------------------------------------------------------------
2416 
2417 template<typename Alloc>
2420  block_idx_type nb,
2421  unsigned nbit_right,
2422  const rs_index_type& rs_idx) BMNOEXCEPT
2423 {
2424  size_type c;
2425  unsigned sub_range = rs_idx.find_sub_range(nbit_right);
2426 
2427  unsigned sub_cnt = rs_idx.sub_count(nb);
2428  unsigned first = sub_cnt & 0xFFFF;
2429  unsigned second = sub_cnt >> 16;
2430 
2433 
2434  // evaluate 3 sub-block intervals
2435  // |--------[0]-----------[1]----------|
2436 
2437  switch(sub_range) // sub-range rank calc
2438  {
2439  case 0:
2440  // |--x-----[0]-----------[1]----------|
2441  if (nbit_right <= rs3_border0/2)
2442  {
2443  c = bm::bit_block_calc_count_to(block, nbit_right);
2444  }
2445  else
2446  {
2447  // |--------[x]-----------[1]----------|
2448  if (nbit_right == rs3_border0)
2449  {
2450  c = first;
2451  }
2452  else
2453  {
2454  // |------x-[0]-----------[1]----------|
2456  nbit_right+1,
2457  rs3_border0);
2458  c = first - c;
2459  }
2460  }
2461  break;
2462  case 1:
2463  // |--------[0]-x---------[1]----------|
2464  if (nbit_right <= (rs3_border0 + rs3_half_span))
2465  {
2467  rs3_border0 + 1,
2468  nbit_right);
2469  c += first;
2470  }
2471  else
2472  {
2473  unsigned bc_second_range = first + second;
2474  // |--------[0]-----------[x]----------|
2475  if (nbit_right == rs3_border1)
2476  {
2477  c = bc_second_range;
2478  }
2479  else
2480  {
2481  // |--------[0]--------x--[1]----------|
2483  nbit_right+1,
2484  rs3_border1);
2485  c = bc_second_range - c;
2486  }
2487  }
2488  break;
2489  case 2:
2490  {
2491  unsigned bc_second_range = first + second;
2492 
2493  // |--------[0]-----------[1]-x--------|
2494  if (nbit_right <= (rs3_border1 + rs3_half_span))
2495  {
2497  rs3_border1 + 1,
2498  nbit_right);
2499  c += bc_second_range;
2500  }
2501  else
2502  {
2503  // |--------[0]-----------[1]----------x
2504  if (nbit_right == bm::gap_max_bits-1)
2505  {
2506  c = rs_idx.count(nb);
2507  }
2508  else
2509  {
2510  // |--------[0]-----------[1]-------x--|
2512  nbit_right+1,
2513  bm::gap_max_bits-1);
2514  size_type cnt = rs_idx.count(nb);
2515  c = cnt - c;
2516  }
2517  }
2518  }
2519  break;
2520  default:
2521  BM_ASSERT(0);
2522  c = 0;
2523  } // switch
2524 
2525  BM_ASSERT(c == bm::bit_block_calc_count_to(block, nbit_right));
2526  return c;
2527 }
2528 
2529 // -----------------------------------------------------------------------
2530 
2531 template<typename Alloc>
2532 typename bvector<Alloc>::size_type
2534  const rs_index_type& rs_idx) const BMNOEXCEPT
2535 {
2536  BM_ASSERT(right < bm::id_max);
2537  if (!blockman_.is_init())
2538  return 0;
2539 
2540  unsigned nblock_right = unsigned(right >> bm::set_block_shift);
2541  unsigned nbit_right = unsigned(right & bm::set_block_mask);
2542 
2543  // running count of all blocks before target
2544  //
2545  size_type cnt;
2546  if (nblock_right >= rs_idx.get_total())
2547  {
2548  cnt = rs_idx.count();
2549  return cnt;
2550  }
2551  cnt = nblock_right ? rs_idx.rcount(nblock_right-1) : 0;
2552 
2553  unsigned i, j;
2554  bm::get_block_coord(nblock_right, i, j);
2555  const bm::word_t* block = blockman_.get_block_ptr(i, j);
2556 
2557  if (!block)
2558  return cnt;
2559 
2560  bool gap = BM_IS_GAP(block);
2561  if (gap)
2562  {
2563  unsigned c = bm::gap_bit_count_to(BMGAP_PTR(block), (gap_word_t)nbit_right);
2564  BM_ASSERT(c == bm::gap_bit_count_range(BMGAP_PTR(block), (gap_word_t)0, (gap_word_t)nbit_right));
2565  cnt += c;
2566  }
2567  else
2568  {
2569  if (block == FULL_BLOCK_FAKE_ADDR) // TODO: misses REAL full sometimes
2570  {
2571  cnt += nbit_right + 1;
2572  }
2573  else // real bit-block
2574  {
2575  size_type c =
2576  this->block_count_to(block, nblock_right, nbit_right, rs_idx);
2577  cnt += c;
2578  }
2579  }
2580  return cnt;
2581 }
2582 
2583 // -----------------------------------------------------------------------
2584 
2585 template<typename Alloc>
2586 typename bvector<Alloc>::size_type
2588  const rs_index_type& rs_idx) const BMNOEXCEPT
2589 {
2590  BM_ASSERT(right < bm::id_max);
2591  if (!blockman_.is_init())
2592  return 0;
2593 
2594  unsigned nblock_right = unsigned(right >> bm::set_block_shift);
2595  unsigned nbit_right = unsigned(right & bm::set_block_mask);
2596 
2597  unsigned i, j;
2598  bm::get_block_coord(nblock_right, i, j);
2599  const bm::word_t* block = blockman_.get_block_ptr(i, j);
2600 
2601  size_type cnt = 0;
2602  if (!block)
2603  return cnt;
2604 
2605  bool gap = BM_IS_GAP(block);
2606  if (gap)
2607  {
2608  bm::gap_word_t *gap_blk = BMGAP_PTR(block);
2609  if (bm::gap_test_unr(gap_blk, (gap_word_t)nbit_right))
2610  cnt = bm::gap_bit_count_to(gap_blk, (gap_word_t)nbit_right);
2611  else
2612  return cnt;
2613  }
2614  else
2615  {
2616  if (block == FULL_BLOCK_FAKE_ADDR)
2617  {
2618  cnt = nbit_right + 1;
2619  }
2620  else
2621  {
2622  unsigned nword = nbit_right >> bm::set_word_shift;
2623  unsigned w = block[nword];
2624  w &= (1u << (nbit_right & bm::set_word_mask));
2625  if (w)
2626  {
2627  cnt = block_count_to(block, nblock_right, nbit_right, rs_idx);
2628  BM_ASSERT(cnt == bm::bit_block_calc_count_to(block, nbit_right));
2629  }
2630  else
2631  {
2632  return cnt;
2633  }
2634  }
2635  }
2636  cnt += nblock_right ? rs_idx.rcount(nblock_right - 1) : 0;
2637  return cnt;
2638 }
2639 
2640 // -----------------------------------------------------------------------
2641 
2642 template<typename Alloc>
2645  const rs_index_type& rs_idx) const BMNOEXCEPT
2646 {
2647  BM_ASSERT(right < bm::id_max);
2648  if (!blockman_.is_init())
2649  return 0;
2650 
2651  unsigned nblock_right = unsigned(right >> bm::set_block_shift);
2652  unsigned nbit_right = unsigned(right & bm::set_block_mask);
2653 
2654  size_type cnt = nblock_right ? rs_idx.rcount(nblock_right - 1) : 0;
2655 
2656  unsigned i, j;
2657  bm::get_block_coord(nblock_right, i, j);
2658  const bm::word_t* block = blockman_.get_block_ptr(i, j);
2659 
2660  if (!block)
2661  return cnt;
2662 
2663  bool gap = BM_IS_GAP(block);
2664  if (gap)
2665  {
2666  cnt += bm::gap_bit_count_to(BMGAP_PTR(block), (gap_word_t)nbit_right,
2667  true /* rank corrected */);
2668  }
2669  else
2670  {
2671  if (block == FULL_BLOCK_FAKE_ADDR)
2672  cnt += nbit_right;
2673  else
2674  {
2675  cnt += block_count_to(block, nblock_right, nbit_right, rs_idx);
2676  unsigned w = block[nbit_right >> bm::set_word_shift] &
2677  (1u << (nbit_right & bm::set_word_mask));
2678  cnt -= bool(w); // rank correction
2679  }
2680  }
2681  return cnt;
2682 }
2683 
2684 
2685 // -----------------------------------------------------------------------
2686 
2687 template<typename Alloc>
2690 {
2691  BM_ASSERT(left < bm::id_max && right < bm::id_max);
2692  if (left > right)
2693  bm::xor_swap(left, right);
2694  if (right == bm::id_max)
2695  --right;
2696 
2697  if (!blockman_.is_init())
2698  return 0;
2699 
2700  size_type cnt = 0;
2701 
2702  // calculate logical number of start and destination blocks
2703  block_idx_type nblock_left = (left >> bm::set_block_shift);
2704  block_idx_type nblock_right = (right >> bm::set_block_shift);
2705 
2706  unsigned i0, j0;
2707  bm::get_block_coord(nblock_left, i0, j0);
2708  const bm::word_t* block = blockman_.get_block(i0, j0);
2709 
2710  bool left_gap = BM_IS_GAP(block);
2711 
2712  unsigned nbit_left = unsigned(left & bm::set_block_mask);
2713  unsigned nbit_right = unsigned(right & bm::set_block_mask);
2714 
2715  unsigned r =
2716  (nblock_left == nblock_right) ? nbit_right : (bm::bits_in_block-1);
2717 
2718  typename blocks_manager_type::block_count_func func(blockman_);
2719 
2720  if (block)
2721  {
2722  if ((nbit_left == 0) && (r == (bm::bits_in_block-1))) // whole block
2723  {
2724  func(block);
2725  }
2726  else
2727  {
2728  if (left_gap)
2729  {
2730  cnt += bm::gap_bit_count_range(BMGAP_PTR(block),
2731  (gap_word_t)nbit_left,
2732  (gap_word_t)r);
2733  }
2734  else
2735  {
2736  cnt += bm::bit_block_calc_count_range(block, nbit_left, r);
2737  }
2738  }
2739  }
2740 
2741  cnt += func.count();
2742  if (nblock_left == nblock_right) // in one block
2743  {
2744  return cnt;
2745  }
2746 
2747  // process all full mid-blocks
2748  {
2749  func.reset();
2750  word_t*** blk_root = blockman_.top_blocks_root();
2751  block_idx_type top_blocks_size = blockman_.top_block_size();
2752 
2753  bm::for_each_nzblock_range(blk_root, top_blocks_size,
2754  nblock_left+1, nblock_right-1, func);
2755  cnt += func.count();
2756  }
2757 
2758  bm::get_block_coord(nblock_right, i0, j0);
2759  block = blockman_.get_block(i0, j0);
2760  bool right_gap = BM_IS_GAP(block);
2761 
2762  if (block)
2763  {
2764  if (right_gap)
2765  {
2766  cnt += bm::gap_bit_count_range(BMGAP_PTR(block),
2767  (gap_word_t)0,
2768  (gap_word_t)nbit_right);
2769  }
2770  else
2771  {
2772  cnt += bm::bit_block_calc_count_range(block, 0, nbit_right);
2773  }
2774  }
2775  return cnt;
2776 }
2777 
2778 // -----------------------------------------------------------------------
2779 
2780 template<typename Alloc>
2782  size_type right) const BMNOEXCEPT
2783 {
2784  if (!blockman_.is_init())
2785  return false; // nothing to do
2786 
2787  if (right < left)
2788  bm::xor_swap(left, right);
2789  if (right == bm::id_max)
2790  --right;
2791  if (left == right)
2792  return test(left);
2793 
2794  BM_ASSERT(left < bm::id_max && right < bm::id_max);
2795 
2796  block_idx_type nblock_left = (left >> bm::set_block_shift);
2797  block_idx_type nblock_right = (right >> bm::set_block_shift);
2798 
2799  unsigned i0, j0;
2800  bm::get_block_coord(nblock_left, i0, j0);
2801  const bm::word_t* block = blockman_.get_block(i0, j0);
2802 
2803  if (nblock_left == nblock_right) // hit in the same block
2804  {
2805  unsigned nbit_left = unsigned(left & bm::set_block_mask);
2806  unsigned nbit_right = unsigned(right & bm::set_block_mask);
2807  return bm::block_is_all_one_range(block, nbit_left, nbit_right);
2808  }
2809 
2810  // process entry point block
2811  {
2812  unsigned nbit_left = unsigned(left & bm::set_block_mask);
2813  bool all_one = bm::block_is_all_one_range(block,
2814  nbit_left, (bm::gap_max_bits-1));
2815  if (!all_one)
2816  return all_one;
2817  ++nblock_left;
2818  }
2819 
2820  // process tail block
2821  {
2822  bm::get_block_coord(nblock_right, i0, j0);
2823  block = blockman_.get_block(i0, j0);
2824  unsigned nbit_right = unsigned(right & bm::set_block_mask);
2825  bool all_one = bm::block_is_all_one_range(block, 0, nbit_right);
2826  if (!all_one)
2827  return all_one;
2828  --nblock_right;
2829  }
2830 
2831  // check all blocks in the middle
2832  //
2833  if (nblock_left <= nblock_right)
2834  {
2835  unsigned i_from, j_from, i_to, j_to;
2836  bm::get_block_coord(nblock_left, i_from, j_from);
2837  bm::get_block_coord(nblock_right, i_to, j_to);
2838 
2839  bm::word_t*** blk_root = blockman_.top_blocks_root();
2840 
2841  for (unsigned i = i_from; i <= i_to; ++i)
2842  {
2843  bm::word_t** blk_blk = blk_root[i];
2844  if (!blk_blk)
2845  return false;
2846  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
2847  continue;
2848 
2849  unsigned j = (i == i_from) ? j_from : 0;
2850  unsigned j_limit = (i == i_to) ? j_to+1 : bm::set_sub_array_size;
2851  do
2852  {
2853  bool all_one = bm::check_block_one(blk_blk[j], true);
2854  if (!all_one)
2855  return all_one;
2856  } while (++j < j_limit);
2857  } // for i
2858  }
2859  return true;
2860 }
2861 
2862 // -----------------------------------------------------------------------
2863 
2864 template<typename Alloc>
2866 {
2867  BM_ASSERT(left < bm::id_max && right < bm::id_max);
2868 
2869  if (!blockman_.is_init())
2870  return false; // nothing to do
2871 
2872  if (right < left)
2873  bm::xor_swap(left, right);
2874  if (right == bm::id_max)
2875  --right;
2876  if (left == right)
2877  return test(left);
2878 
2879  block_idx_type nblock_left = (left >> bm::set_block_shift);
2880  block_idx_type nblock_right = (right >> bm::set_block_shift);
2881 
2882  unsigned i0, j0;
2883  bm::get_block_coord(nblock_left, i0, j0);
2884  const bm::word_t* block = blockman_.get_block(i0, j0);
2885 
2886  if (nblock_left == nblock_right) // hit in the same block
2887  {
2888  unsigned nbit_left = unsigned(left & bm::set_block_mask);
2889  unsigned nbit_right = unsigned(right & bm::set_block_mask);
2890  return bm::block_any_range(block, nbit_left, nbit_right);
2891  }
2892 
2893  // process entry point block
2894  {
2895  unsigned nbit_left = unsigned(left & bm::set_block_mask);
2896  bool any_one = bm::block_any_range(block,
2897  nbit_left, (bm::gap_max_bits-1));
2898  if (any_one)
2899  return any_one;
2900  ++nblock_left;
2901  }
2902 
2903  // process tail block
2904  {
2905  bm::get_block_coord(nblock_right, i0, j0);
2906  block = blockman_.get_block(i0, j0);
2907  unsigned nbit_right = unsigned(right & bm::set_block_mask);
2908  bool any_one = bm::block_any_range(block, 0, nbit_right);
2909  if (any_one)
2910  return any_one;
2911  --nblock_right;
2912  }
2913 
2914  // check all blocks in the middle
2915  //
2916  if (nblock_left <= nblock_right)
2917  {
2918  unsigned i_from, j_from, i_to, j_to;
2919  bm::get_block_coord(nblock_left, i_from, j_from);
2920  bm::get_block_coord(nblock_right, i_to, j_to);
2921 
2922  bm::word_t*** blk_root = blockman_.top_blocks_root();
2923  {
2924  block_idx_type top_size = blockman_.top_block_size();
2925  if (i_from >= top_size)
2926  return false;
2927  if (i_to >= top_size)
2928  {
2929  i_to = unsigned(top_size-1);
2930  j_to = bm::set_sub_array_size-1;
2931  }
2932  }
2933 
2934  for (unsigned i = i_from; i <= i_to; ++i)
2935  {
2936  bm::word_t** blk_blk = blk_root[i];
2937  if (!blk_blk)
2938  continue;
2939  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
2940  return true;
2941 
2942  unsigned j = (i == i_from) ? j_from : 0;
2943  unsigned j_limit = (i == i_to) ? j_to+1 : bm::set_sub_array_size;
2944  do
2945  {
2946  bool any_one = bm::block_any(blk_blk[j]);
2947  if (any_one)
2948  return any_one;
2949  } while (++j < j_limit);
2950  } // for i
2951  }
2952  return false;
2953 }
2954 
2955 // -----------------------------------------------------------------------
2956 
2957 template<typename Alloc>
2960  size_type right,
2961  const rs_index_type& rs_idx) const BMNOEXCEPT
2962 {
2963  BM_ASSERT(left <= right);
2964 
2965  if (left > right)
2966  bm::xor_swap(left, right);
2967 
2968  BM_ASSERT_THROW(right < bm::id_max, BM_ERR_RANGE);
2969 
2970  if (left == right)
2971  return this->test(left);
2972 
2973  size_type cnt_l, cnt_r;
2974  if (left)
2975  cnt_l = this->count_to(left-1, rs_idx);
2976  else
2977  cnt_l = left; // == 0
2978 
2979  cnt_r = this->count_to(right, rs_idx);
2980 
2981  return cnt_r - cnt_l;
2982 }
2983 
2984 // -----------------------------------------------------------------------
2985 
2986 template<typename Alloc>
2988 {
2989  if (!size_)
2990  return *this; // cannot invert a set of power 0
2991 
2992  unsigned top_blocks = blockman_.reserve_top_blocks(bm::set_top_array_size);
2993  bm::word_t*** blk_root = blockman_.top_blocks_root();
2994  for (unsigned i = 0; i < top_blocks; ++i)
2995  {
2996  bm::word_t** blk_blk = blk_root[i];
2997  if (!blk_blk)
2998  {
2999  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
3000  continue;
3001  }
3002  if (blk_blk == (bm::word_t**)FULL_BLOCK_FAKE_ADDR)
3003  {
3004  blk_root[i] = 0;
3005  continue;
3006  }
3007  unsigned j = 0; bm::word_t* blk;
3008  do
3009  {
3010  blk = blk_blk[j];
3011  if (!blk)
3012  blockman_.set_block_ptr(i, j, FULL_BLOCK_FAKE_ADDR);
3013  else
3014  if (IS_FULL_BLOCK(blk))
3015  blockman_.set_block_ptr(i, j, 0);
3016  else
3017  {
3018  if (BM_IS_GAP(blk))
3019  bm::gap_invert(BMGAP_PTR(blk));
3020  else
3021  bm::bit_invert((wordop_t*)blk);
3022  }
3023  } while (++j < bm::set_sub_array_size);
3024  } // for i
3025 
3026  if (size_ == bm::id_max)
3027  set_bit_no_check(bm::id_max, false);
3028  else
3029  clear_range_no_check(size_, bm::id_max);
3030 
3031  return *this;
3032 }
3033 
3034 // -----------------------------------------------------------------------
3035 
3036 template<typename Alloc>
3038 {
3039  BM_ASSERT(n < size_);
3040  BM_ASSERT_THROW((n < size_), BM_ERR_RANGE);
3041 
3042  // calculate logical block number
3043  unsigned nb = unsigned(n >> bm::set_block_shift);
3044  unsigned i, j;
3045  bm::get_block_coord(nb, i, j);
3046  const bm::word_t* block = blockman_.get_block_ptr(i, j); // get unsanitized block ptr
3047 
3048  if (block)
3049  {
3050  // calculate word number in block and bit
3051  unsigned nbit = unsigned(n & bm::set_block_mask);
3052  if (BM_IS_GAP(block))
3053  {
3054  return gap_test_unr(BMGAP_PTR(block), nbit);
3055  }
3056  else
3057  {
3058  if (block == FULL_BLOCK_FAKE_ADDR)
3059  return true;
3060  unsigned nword = unsigned(nbit >> bm::set_word_shift);
3061  unsigned w = block[nword];
3062  return w & (1u << (nbit & bm::set_word_mask));
3063  }
3064  }
3065  return false;
3066 }
3067 
3068 // -----------------------------------------------------------------------
3069 
3070 template<typename Alloc>
3072  optmode opt_mode,
3073  statistics* stat)
3074 {
3075  if (!blockman_.is_init())
3076  {
3077  if (stat)
3078  calc_stat(stat);
3079  return;
3080  }
3081  if (!temp_block)
3082  temp_block = blockman_.check_allocate_tempblock();
3083 
3084  if (stat)
3085  {
3086  stat->reset();
3087  ::memcpy(stat->gap_levels,
3088  blockman_.glen(), sizeof(gap_word_t) * bm::gap_levels);
3089  stat->max_serialize_mem = (unsigned)sizeof(bm::id_t) * 4;
3090  }
3091 
3092  blockman_.optimize_tree(temp_block, opt_mode, stat);
3093 
3094  if (stat)
3095  {
3096  size_t safe_inc = stat->max_serialize_mem / 10; // 10% increment
3097  if (!safe_inc) safe_inc = 256;
3098  stat->max_serialize_mem += safe_inc;
3099 
3100  stat->memory_used += (unsigned)(sizeof(*this) - sizeof(blockman_));
3101 
3102  unsigned top_size = blockman_.top_block_size();
3103  size_t blocks_mem = sizeof(blockman_);
3104  blocks_mem += sizeof(bm::word_t**) * top_size;
3105  blocks_mem += stat->ptr_sub_blocks * (sizeof(void*) * bm::set_sub_array_size);
3106  stat->memory_used += blocks_mem;
3107  stat->bv_count = 1;
3108  }
3109 
3110  // don't need to keep temp block if we optimizing memory usage
3111  blockman_.free_temp_block();
3112 }
3113 
3114 // -----------------------------------------------------------------------
3115 
3116 template<typename Alloc>
3118 {
3119 #if 0
3120  if (!blockman_.is_init())
3121  return;
3122 
3123  struct bvector<Alloc>::statistics st;
3124  calc_stat(&st);
3125 
3126  if (!st.gap_blocks)
3127  return;
3128 
3129  gap_word_t opt_glen[bm::gap_levels];
3130  ::memcpy(opt_glen, st.gap_levels, bm::gap_levels * sizeof(*opt_glen));
3131 
3132  improve_gap_levels(st.gap_length,
3133  st.gap_length + st.gap_blocks,
3134  opt_glen);
3135 
3136  set_gap_levels(opt_glen);
3137 #endif
3138 }
3139 
3140 // -----------------------------------------------------------------------
3141 
3142 template<typename Alloc>
3143 void bvector<Alloc>::set_gap_levels(const gap_word_t* glevel_len)
3144 {
3145  if (blockman_.is_init())
3146  {
3147  word_t*** blk_root = blockman_.top_blocks_root();
3148  typename
3149  blocks_manager_type::gap_level_func gl_func(blockman_, glevel_len);
3150  for_each_nzblock(blk_root, blockman_.top_block_size(),gl_func);
3151  }
3152 
3153  blockman_.set_glen(glevel_len);
3154 }
3155 
3156 // -----------------------------------------------------------------------
3157 
3158 template<typename Alloc>
3160 {
3161  int res;
3162  unsigned top_blocks = blockman_.top_block_size();
3163  unsigned bvect_top_blocks = bv.blockman_.top_block_size();
3164 
3165  if (bvect_top_blocks > top_blocks) top_blocks = bvect_top_blocks;
3166 
3167  for (unsigned i = 0; i < top_blocks; ++i)
3168  {
3169  const bm::word_t* const* blk_blk = blockman_.get_topblock(i);
3170  const bm::word_t* const* arg_blk_blk = bv.blockman_.get_topblock(i);
3171 
3172  if (blk_blk == arg_blk_blk)
3173  continue;
3174 
3175  for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
3176  {
3177  const bm::word_t* arg_blk; const bm::word_t* blk;
3178  if ((bm::word_t*)arg_blk_blk == FULL_BLOCK_FAKE_ADDR)
3179  arg_blk = FULL_BLOCK_REAL_ADDR;
3180  else
3181  {
3182  arg_blk = arg_blk_blk ? arg_blk_blk[j] : 0;
3183  if (arg_blk == FULL_BLOCK_FAKE_ADDR)
3184  arg_blk = FULL_BLOCK_REAL_ADDR;
3185  }
3186  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
3187  blk = FULL_BLOCK_REAL_ADDR;
3188  else
3189  {
3190  blk = blk_blk ? blk_blk[j] : 0;
3191  if (blk == FULL_BLOCK_FAKE_ADDR)
3192  blk = FULL_BLOCK_REAL_ADDR;
3193  }
3194  if (blk == arg_blk) continue;
3195 
3196  // If one block is zero we check if the other one has at least
3197  // one bit ON
3198 
3199  if (!blk || !arg_blk)
3200  {
3201  const bm::word_t* pblk; bool is_gap;
3202 
3203  if (blk)
3204  {
3205  pblk = blk;
3206  res = 1;
3207  is_gap = BM_IS_GAP(blk);
3208  }
3209  else
3210  {
3211  pblk = arg_blk;
3212  res = -1;
3213  is_gap = BM_IS_GAP(arg_blk);
3214  }
3215 
3216  if (is_gap)
3217  {
3218  if (!bm::gap_is_all_zero(BMGAP_PTR(pblk)))
3219  return res;
3220  }
3221  else
3222  {
3223  if (!bm::bit_is_all_zero(pblk))
3224  return res;
3225  }
3226  continue;
3227  }
3228  bool arg_gap = BM_IS_GAP(arg_blk);
3229  bool gap = BM_IS_GAP(blk);
3230 
3231  if (arg_gap != gap)
3232  {
3233  BM_DECLARE_TEMP_BLOCK(temp_blk);
3234  bm::wordop_t* blk1; bm::wordop_t* blk2;
3235 
3236  if (gap)
3237  {
3239  BMGAP_PTR(blk));
3240  blk1 = (bm::wordop_t*)temp_blk;
3241  blk2 = (bm::wordop_t*)arg_blk;
3242  }
3243  else
3244  {
3246  BMGAP_PTR(arg_blk));
3247  blk1 = (bm::wordop_t*)blk;
3248  blk2 = (bm::wordop_t*)temp_blk;
3249  }
3250  res = bm::bitcmp(blk1, blk2, bm::set_block_size_op);
3251  }
3252  else
3253  {
3254  if (gap)
3255  {
3256  res = bm::gapcmp(BMGAP_PTR(blk), BMGAP_PTR(arg_blk));
3257  }
3258  else
3259  {
3260  res = bm::bitcmp((bm::wordop_t*)blk,
3261  (bm::wordop_t*)arg_blk,
3263  }
3264  }
3265  if (res != 0)
3266  return res;
3267  } // for j
3268 
3269  } // for i
3270 
3271  return 0;
3272 }
3273 
3274 // -----------------------------------------------------------------------
3275 
3276 template<typename Alloc>
3278  const bvector<Alloc>& bvect, size_type& pos,
3279  size_type search_to) const BMNOEXCEPT
3280 {
3281  unsigned top_blocks = blockman_.top_block_size();
3282  bm::word_t*** top_root = blockman_.top_blocks_root();
3283 
3284  if (!top_blocks || !top_root)
3285  {
3286  return bvect.find(pos);
3287  }
3288  bm::word_t*** arg_top_root = bvect.blockman_.top_blocks_root();
3289  unsigned i_to, j_to;
3290  {
3291  unsigned bvect_top_blocks = bvect.blockman_.top_block_size();
3292  if (!bvect_top_blocks || !arg_top_root)
3293  {
3294  bool f = this->find(pos);
3295  if (f)
3296  {
3297  if (pos > search_to)
3298  return false;
3299  }
3300  return f;
3301  }
3302 
3303  if (bvect_top_blocks > top_blocks)
3304  top_blocks = bvect_top_blocks;
3305  block_idx_type nb_to = (search_to >> bm::set_block_shift);
3306  bm::get_block_coord(nb_to, i_to, j_to);
3307  }
3308  if (i_to < top_blocks)
3309  top_blocks = i_to+1;
3310 
3311  for (unsigned i = 0; i < top_blocks; ++i)
3312  {
3313  const bm::word_t* const* blk_blk = blockman_.get_topblock(i);
3314  const bm::word_t* const* arg_blk_blk = bvect.blockman_.get_topblock(i);
3315 
3316  if (blk_blk == arg_blk_blk)
3317  {
3318  /* TODO: fix buffer overrread here
3319  unsigned arg_top_blocks = bvect.blockman_.top_block_size_;
3320  if (top_blocks < arg_top_blocks)
3321  arg_top_blocks = top_blocks;
3322  if (i_to < arg_top_blocks)
3323  arg_top_blocks = i_to+1;
3324 
3325  // look ahead for top level mismatch
3326  for (++i; i < arg_top_blocks; ++i)
3327  {
3328  if (top_root[i] != arg_top_root[i])
3329  {
3330  blk_blk = blockman_.get_topblock(i);
3331  arg_blk_blk = bvect.blockman_.get_topblock(i);
3332  BM_ASSERT(blk_blk != arg_blk_blk);
3333  goto find_sub_block;
3334  }
3335  }
3336  */
3337  continue;
3338  }
3339  //find_sub_block:
3340  unsigned j = 0;
3341  do
3342  {
3343  const bm::word_t* arg_blk; const bm::word_t* blk;
3344  arg_blk = ((bm::word_t*)arg_blk_blk == FULL_BLOCK_FAKE_ADDR) ?
3346  arg_blk_blk ? (BLOCK_ADDR_SAN(arg_blk_blk[j])) : 0;
3347  blk = ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR) ?
3349  (blk_blk ? (BLOCK_ADDR_SAN(blk_blk[j])) : 0);
3350  if (blk == arg_blk)
3351  continue;
3352 
3353  unsigned block_pos;
3354  bool found = bm::block_find_first_diff(blk, arg_blk, &block_pos);
3355  if (found)
3356  {
3357  pos =
3359  (size_type(j) * bm::gap_max_bits) + block_pos;
3360  if (pos > search_to)
3361  return false;
3362  return true;
3363  }
3364 
3365  if (i == i_to)
3366  {
3367  if (j >= j_to)
3368  return false;
3369  }
3370 
3371  } while (++j < bm::set_sub_array_size);
3372  } // for i
3373 
3374  return false;
3375 
3376 }
3377 
3378 // -----------------------------------------------------------------------
3379 
3380 template<typename Alloc>
3382 {
3383  if (this != &bvect)
3384  {
3385  blockman_.swap(bvect.blockman_);
3386  bm::xor_swap(size_,bvect.size_);
3387  }
3388 }
3389 
3390 // -----------------------------------------------------------------------
3391 
3392 template<typename Alloc>
3394  struct bvector<Alloc>::statistics* st) const BMNOEXCEPT
3395 {
3396  BM_ASSERT(st);
3397 
3398  st->reset();
3399  ::memcpy(st->gap_levels,
3400  blockman_.glen(), sizeof(gap_word_t) * bm::gap_levels);
3401 
3402  st->max_serialize_mem = unsigned(sizeof(bm::id_t) * 4);
3403  unsigned top_size = blockman_.top_block_size();
3404 
3405  size_t blocks_mem = sizeof(blockman_);
3406  blocks_mem +=
3407  (blockman_.temp_block_ ? sizeof(bm::word_t) * bm::set_block_size : 0);
3408  blocks_mem += sizeof(bm::word_t**) * top_size;
3409  bm::word_t*** blk_root = blockman_.top_blocks_root();
3410 
3411  if (blk_root)
3412  {
3413  for (unsigned i = 0; i < top_size; ++i)
3414  {
3415  const bm::word_t* const* blk_blk = blk_root[i];
3416  if (!blk_blk)
3417  {
3418  ++i;
3419  bool found = bm::find_not_null_ptr(blk_root, i, top_size, &i);
3420  if (!found)
3421  break;
3422  blk_blk = blk_root[i];
3423  BM_ASSERT(blk_blk);
3424  if (!blk_blk)
3425  break;
3426  }
3427  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
3428  continue;
3429  st->ptr_sub_blocks++;
3430  for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
3431  {
3432  const bm::word_t* blk = blk_blk[j];
3433  if (IS_VALID_ADDR(blk))
3434  {
3435  if (BM_IS_GAP(blk))
3436  {
3437  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
3438  unsigned cap = bm::gap_capacity(gap_blk, blockman_.glen());
3439  unsigned len = gap_length(gap_blk);
3440  st->add_gap_block(cap, len);
3441  }
3442  else // bit block
3443  st->add_bit_block();
3444  }
3445  }
3446  } // for i
3447 
3448  size_t full_null_size = blockman_.calc_serialization_null_full();
3449  st->max_serialize_mem += full_null_size;
3450 
3451  } // if blk_root
3452 
3453  size_t safe_inc = st->max_serialize_mem / 10; // 10% increment
3454  if (!safe_inc) safe_inc = 256;
3455  st->max_serialize_mem += safe_inc;
3456 
3457  // Calc size of different odd and temporary things.
3458  st->memory_used += unsigned(sizeof(*this) - sizeof(blockman_));
3459  blocks_mem += st->ptr_sub_blocks * (sizeof(void*) * bm::set_sub_array_size);
3460  st->memory_used += blocks_mem;
3461  st->bv_count = 1;
3462 
3463 }
3464 
3465 // -----------------------------------------------------------------------
3466 
3467 template<class Alloc>
3469 {
3470  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
3471 
3472  bool val = true; // set bit
3473 
3474  // calculate logical block number
3475  block_idx_type nblock = (n >> bm::set_block_shift);
3476  // calculate word number in block and bit
3477  unsigned nbit = unsigned(n & bm::set_block_mask);
3478 
3479  int block_type;
3480  bm::word_t* blk =
3481  blockman_.check_allocate_block(nblock,
3482  val,
3484  &block_type);
3485  if (!IS_VALID_ADDR(blk))
3486  return;
3487 
3488  if (block_type) // gap block
3489  {
3490  this->gap_block_set_no_ret(BMGAP_PTR(blk), val, nblock, nbit);
3491  }
3492  else // bit block
3493  {
3494  unsigned nword = nbit >> bm::set_word_shift;
3495  nbit &= bm::set_word_mask;
3496  blk[nword] |= (1u << nbit); // set bit
3497  }
3498 }
3499 
3500 // -----------------------------------------------------------------------
3501 
3502 template<class Alloc>
3504  size_type ids_size, bm::sort_order so)
3505 {
3506  if (!ids || !ids_size)
3507  return; // nothing to do
3508  if (!blockman_.is_init())
3509  blockman_.init_tree();
3510 
3511  import(ids, ids_size, so);
3512  sync_size();
3513 }
3514 
3515 // -----------------------------------------------------------------------
3516 
3517 template<class Alloc>
3518 void bvector<Alloc>::keep(const size_type* ids, size_type ids_size,
3519  bm::sort_order so)
3520 {
3521  if (!ids || !ids_size || !blockman_.is_init())
3522  {
3523  clear();
3524  return;
3525  }
3526  bvector<Alloc> bv_tmp; // TODO: better optimize for SORTED case (avoid temp)
3527  bv_tmp.import(ids, ids_size, so);
3528 
3529  size_type last;
3530  bool found = bv_tmp.find_reverse(last);
3531  if (found)
3532  {
3533  bv_tmp.resize(last+1);
3534  bit_and(bv_tmp);
3535  }
3536  else
3537  {
3538  BM_ASSERT(0);
3539  clear();
3540  }
3541 }
3542 
3543 // -----------------------------------------------------------------------
3544 
3545 template<class Alloc>
3547  size_type ids_size, bm::sort_order so)
3548 {
3549  if (!ids || !ids_size || !blockman_.is_init())
3550  {
3551  return;
3552  }
3553  bvector<Alloc> bv_tmp; // TODO: better optimize for SORTED case (avoid temp)
3554  bv_tmp.import(ids, ids_size, so);
3555 
3556  size_type last;
3557  bool found = bv_tmp.find_reverse(last);
3558  if (found)
3559  {
3560  bv_tmp.resize(last+1);
3561  bit_sub(bv_tmp);
3562  }
3563  else
3564  {
3565  BM_ASSERT(0);
3566  }
3567 }
3568 
3569 // -----------------------------------------------------------------------
3570 
3571 template<class Alloc>
3573 {
3574  set_range(0, size_ - 1, true);
3575  return *this;
3576 }
3577 
3578 // -----------------------------------------------------------------------
3579 
3580 template<class Alloc>
3582 {
3583  set_bit(n, val);
3584  return *this;
3585 }
3586 
3587 // -----------------------------------------------------------------------
3588 
3589 template<class Alloc>
3590 bool bvector<Alloc>::set_bit_conditional(size_type n, bool val, bool condition)
3591 {
3592  if (val == condition) return false;
3593  if (n >= size_)
3594  {
3595  size_type new_size = (n == bm::id_max) ? bm::id_max : n + 1;
3596  resize(new_size);
3597  }
3598  return set_bit_conditional_impl(n, val, condition);
3599 }
3600 
3601 // -----------------------------------------------------------------------
3602 
3603 template<class Alloc>
3605 {
3606  BM_ASSERT(n < size_);
3607  BM_ASSERT_THROW(n < size_, BM_ERR_RANGE);
3608 
3609  if (!blockman_.is_init())
3610  blockman_.init_tree();
3611  return and_bit_no_check(n, val);
3612 }
3613 
3614 // -----------------------------------------------------------------------
3615 
3616 template<class Alloc>
3618 {
3619  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
3620 
3621  if (!blockman_.is_init())
3622  blockman_.init_tree();
3623  if (n >= size_)
3624  {
3625  size_type new_size = (n == bm::id_max) ? bm::id_max : n + 1;
3626  resize(new_size);
3627  }
3628  return set_bit_no_check(n, val);
3629 }
3630 
3631 // -----------------------------------------------------------------------
3632 
3633 template<class Alloc>
3634 void bvector<Alloc>::import(const size_type* ids, size_type size_in,
3635  bm::sort_order sorted_idx)
3636 {
3637  size_type n, start, stop = size_in;
3638  block_idx_type nblock;
3639  start = 0;
3640 
3641  n = ids[start];
3642  nblock = (n >> bm::set_block_shift);
3643 
3644  switch(sorted_idx)
3645  {
3646  case BM_SORTED:
3647  {
3648  block_idx_type nblock_end = (ids[size_in-1] >> bm::set_block_shift);
3649  if (nblock == nblock_end) // special case: one block import
3650  {
3651  if (stop == 1)
3652  set_bit_no_check(ids[0]);
3653  else
3654  import_block(ids, nblock, 0, stop);
3655  return;
3656  }
3657  }
3658  break;
3659  default:
3660  break;
3661  } // switch
3662 
3663  do
3664  {
3665  n = ids[start];
3666  nblock = (n >> bm::set_block_shift);
3667  #ifdef BM64ADDR
3668  stop = bm::idx_arr_block_lookup_u64(ids, size_in, nblock, start);
3669  #else
3670  stop = bm::idx_arr_block_lookup_u32(ids, size_in, nblock, start);
3671  #endif
3672  BM_ASSERT(start < stop);
3673 
3674  if (stop - start == 1 && n < bm::id_max) // just one bit to set
3675  set_bit_no_check(n);
3676  else
3677  import_block(ids, nblock, start, stop);
3678  start = stop;
3679  } while (start < size_in);
3680 }
3681 
3682 // -----------------------------------------------------------------------
3683 
3684 template<class Alloc>
3686  block_idx_type nblock,
3687  size_type start,
3688  size_type stop)
3689 {
3690  BM_ASSERT(stop > start);
3691  int block_type;
3692  bm::word_t* blk =
3693  blockman_.check_allocate_block(nblock, 1, 0, &block_type,
3694  true/*allow NULL ret*/);
3695  if (!IS_FULL_BLOCK(blk))
3696  {
3697  // TODO: add a special case when we import just a few bits per block
3698  if (BM_IS_GAP(blk))
3699  {
3700  blk = blockman_.deoptimize_block(nblock); // TODO: try to avoid
3701  }
3702  #ifdef BM64ADDR
3703  bm::set_block_bits_u64(blk, ids, start, stop);
3704  #else
3705  bm::set_block_bits_u32(blk, ids, start, stop);
3706  #endif
3707 
3708  if (nblock == bm::set_total_blocks-1)
3709  blk[bm::set_block_size-1] &= ~(1u<<31);
3710  }
3711 }
3712 
3713 // -----------------------------------------------------------------------
3714 
3715 template<class Alloc>
3717 {
3718  // calculate logical block number
3719  block_idx_type nblock = (n >> bm::set_block_shift);
3720 
3721  int block_type;
3722  bm::word_t* blk =
3723  blockman_.check_allocate_block(nblock,
3724  val,
3726  &block_type);
3727 
3728  if (!IS_VALID_ADDR(blk))
3729  return false;
3730 
3731  // calculate word number in block and bit
3732  unsigned nbit = unsigned(n & bm::set_block_mask);
3733  if (block_type) // gap
3734  {
3735  return gap_block_set(BMGAP_PTR(blk), val, nblock, nbit);
3736  }
3737  else // bit block
3738  {
3739  unsigned nword = unsigned(nbit >> bm::set_word_shift);
3740  nbit &= bm::set_word_mask;
3741  bm::word_t* word = blk + nword;
3742  bm::word_t mask = (((bm::word_t)1) << nbit);
3743 
3744  if (val)
3745  {
3746  val = ~(*word & mask);
3747  *word |= mask; // set bit
3748  return val;
3749  }
3750  else
3751  {
3752  val = ~(*word & mask);
3753  *word &= ~mask; // clear bit
3754  return val;
3755  }
3756  }
3757  //return false;
3758 }
3759 
3760 // -----------------------------------------------------------------------
3761 
3762 template<class Alloc>
3764  bool val, block_idx_type nblock,
3765  unsigned nbit)
3766 {
3767  unsigned is_set, new_len, old_len;
3768  old_len = bm::gap_length(gap_blk)-1;
3769  new_len = bm::gap_set_value(val, gap_blk, nbit, &is_set);
3770  if (old_len < new_len)
3771  {
3772  unsigned threshold = bm::gap_limit(gap_blk, blockman_.glen());
3773  if (new_len > threshold)
3774  blockman_.extend_gap_block(nblock, gap_blk);
3775  }
3776  return is_set;
3777 }
3778 
3779 // -----------------------------------------------------------------------
3780 
3781 template<class Alloc>
3782 void bvector<Alloc>::gap_block_set_no_ret(bm::gap_word_t* gap_blk,
3783  bool val, block_idx_type nblock, unsigned nbit)
3784 {
3785  unsigned new_len, old_len;
3786  old_len = bm::gap_length(gap_blk)-1;
3787  new_len = bm::gap_set_value(val, gap_blk, nbit);
3788  if (old_len < new_len)
3789  {
3790  unsigned threshold = bm::gap_limit(gap_blk, blockman_.glen());
3791  if (new_len > threshold)
3792  blockman_.extend_gap_block(nblock, gap_blk);
3793  }
3794 }
3795 
3796 
3797 // -----------------------------------------------------------------------
3798 
3799 template<class Alloc>
3801 {
3802  // calculate logical block number
3803  block_idx_type nblock = (n >> bm::set_block_shift);
3804  bm::word_t* blk =
3805  blockman_.check_allocate_block(nblock,
3807  BM_ASSERT(IS_VALID_ADDR(blk));
3808 
3809  unsigned nbit = unsigned(n & bm::set_block_mask);
3810 
3811  unsigned is_set;
3812  if (BM_IS_GAP(blk))
3813  {
3814  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
3815  is_set = (bm::gap_test_unr(gap_blk, nbit) != 0);
3816  this->gap_block_set(gap_blk, !is_set, nblock, nbit); // flip
3817  }
3818  else // bit block
3819  {
3820  unsigned nword = unsigned(nbit >> bm::set_word_shift);
3821  nbit &= bm::set_word_mask;
3822 
3823  bm::word_t* word = blk + nword;
3824  bm::word_t mask = (((bm::word_t)1) << nbit);
3825  is_set = ((*word) & mask);
3826 
3827  *word = (is_set) ? (*word & ~mask) : (*word | mask);
3828  }
3829  return is_set;
3830 }
3831 
3832 // -----------------------------------------------------------------------
3833 
3834 template<class Alloc>
3836  bool val,
3837  bool condition)
3838 {
3839  // calculate logical block number
3840  block_idx_type nblock = (n >> bm::set_block_shift);
3841  int block_type;
3842  bm::word_t* blk =
3843  blockman_.check_allocate_block(nblock,
3844  val,
3846  &block_type);
3847  if (!IS_VALID_ADDR(blk))
3848  return false;
3849 
3850  // calculate word number in block and bit
3851  unsigned nbit = unsigned(n & bm::set_block_mask);
3852 
3853  if (block_type == 1) // gap
3854  {
3855  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
3856  bool old_val = (bm::gap_test_unr(gap_blk, nbit) != 0);
3857 
3858  if (old_val != condition)
3859  {
3860  return false;
3861  }
3862 
3863  if (val != old_val)
3864  {
3865  unsigned is_set = gap_block_set(gap_blk, val, nblock, nbit);
3866  BM_ASSERT(is_set);
3867  return is_set;
3868  }
3869  }
3870  else // bit block
3871  {
3872  unsigned nword = unsigned(nbit >> bm::set_word_shift);
3873  nbit &= bm::set_word_mask;
3874 
3875  bm::word_t* word = blk + nword;
3876  bm::word_t mask = (((bm::word_t)1) << nbit);
3877  bool is_set = ((*word) & mask) != 0;
3878 
3879  if (is_set != condition)
3880  {
3881  return false;
3882  }
3883  if (is_set != val) // need to change bit
3884  {
3885  if (val) // set bit
3886  {
3887  *word |= mask;
3888  }
3889  else // clear bit
3890  {
3891  *word &= ~mask;
3892  }
3893  return true;
3894  }
3895  }
3896  return false;
3897 
3898 }
3899 
3900 // -----------------------------------------------------------------------
3901 
3902 
3903 template<class Alloc>
3904 bool bvector<Alloc>::and_bit_no_check(size_type n, bool val)
3905 {
3906  // calculate logical block number
3907  block_idx_type nblock = (n >> bm::set_block_shift);
3908 
3909  int block_type;
3910  bm::word_t* blk =
3911  blockman_.check_allocate_block(nblock,
3912  val,
3914  &block_type);
3915  if (!IS_VALID_ADDR(blk))
3916  return false;
3917 
3918  // calculate word number in block and bit
3919  unsigned nbit = unsigned(n & bm::set_block_mask);
3920 
3921  if (block_type == 1) // gap
3922  {
3923  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
3924  bool old_val = (bm::gap_test_unr(gap_blk, nbit) != 0);
3925 
3926  bool new_val = val & old_val;
3927  if (new_val != old_val)
3928  {
3929  unsigned is_set = gap_block_set(gap_blk, val, nblock, nbit);
3930  BM_ASSERT(is_set);
3931  return is_set;
3932  }
3933  }
3934  else // bit block
3935  {
3936  unsigned nword = unsigned(nbit >> bm::set_word_shift);
3937  nbit &= bm::set_word_mask;
3938 
3939  bm::word_t* word = blk + nword;
3940  bm::word_t mask = (((bm::word_t)1) << nbit);
3941  bool is_set = ((*word) & mask) != 0;
3942 
3943  bool new_val = is_set & val;
3944  if (new_val != val) // need to change bit
3945  {
3946  if (new_val) // set bit
3947  {
3948  *word |= mask;
3949  }
3950  else // clear bit
3951  {
3952  *word &= ~mask;
3953  }
3954  return true;
3955  }
3956  }
3957  return false;
3958 }
3959 
3960 //---------------------------------------------------------------------
3961 
3962 template<class Alloc>
3964 {
3965  if (from == bm::id_max)
3966  return false;
3967  if (!from)
3968  {
3969  return find(pos);
3970  }
3971  pos = check_or_next(from);
3972  return (pos != 0);
3973 }
3974 
3975 //---------------------------------------------------------------------
3976 
3977 template<class Alloc>
3979 {
3980  bool found;
3981 
3982  unsigned top_blocks = blockman_.top_block_size();
3983  if (!top_blocks)
3984  return false;
3985  for (unsigned i = top_blocks-1; true; --i)
3986  {
3987  const bm::word_t* const* blk_blk = blockman_.get_topblock(i);
3988  if (blk_blk)
3989  {
3990  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
3991  blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
3992 
3993  for (unsigned short j = bm::set_sub_array_size-1; true; --j)
3994  {
3995  const bm::word_t* blk = blk_blk[j];
3996  if (blk)
3997  {
3998  unsigned block_pos;
3999  if (blk == FULL_BLOCK_FAKE_ADDR)
4000  {
4001  block_pos = bm::gap_max_bits-1;
4002  found = true;
4003  }
4004  else
4005  {
4006  bool is_gap = BM_IS_GAP(blk);
4007  found = is_gap ? bm::gap_find_last(BMGAP_PTR(blk), &block_pos)
4008  : bm::bit_find_last(blk, &block_pos);
4009  }
4010  if (found)
4011  {
4012  block_idx_type base_idx =
4015  base_idx += j * bm::gap_max_bits;
4016  pos = base_idx + block_pos;
4017  return found;
4018  }
4019  }
4020 
4021  if (j == 0)
4022  break;
4023  } // for j
4024  } // if blk_blk
4025 
4026  if (i == 0)
4027  break;
4028  } // for i
4029  return false;
4030 }
4031 
4032 //---------------------------------------------------------------------
4033 
4034 template<class Alloc>
4036 {
4037  bool found;
4038 
4039  unsigned top_blocks = blockman_.top_block_size();
4040  for (unsigned i = 0; i < top_blocks; ++i)
4041  {
4042  const bm::word_t* const* blk_blk = blockman_.get_topblock(i);
4043  if (blk_blk)
4044  {
4045  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
4046  blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
4047 
4048  for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
4049  {
4050  const bm::word_t* blk = blk_blk[j];
4051  if (blk)
4052  {
4053  unsigned block_pos;
4054  if (blk == FULL_BLOCK_FAKE_ADDR)
4055  {
4056  found = true; block_pos = 0;
4057  }
4058  else
4059  {
4060  bool is_gap = BM_IS_GAP(blk);
4061  found = (is_gap) ? bm::gap_find_first(BMGAP_PTR(blk), &block_pos)
4062  : bm::bit_find_first(blk, &block_pos);
4063  }
4064  if (found)
4065  {
4066  size_type base_idx = block_idx_type(i) * bm::bits_in_array;
4067  base_idx += j * bm::gap_max_bits;
4068  pos = base_idx + block_pos;
4069  return found;
4070  }
4071  }
4072  } // for j
4073  } // if blk_blk
4074  } // for i
4075  return false;
4076 }
4077 
4078 //---------------------------------------------------------------------
4079 
4080 template<class Alloc>
4082  size_type& in_last) const BMNOEXCEPT
4083 {
4084  bool found = find(in_first);
4085  if (found)
4086  {
4087  found = find_reverse(in_last);
4088  BM_ASSERT(found);
4089  BM_ASSERT(in_first <= in_last);
4090  }
4091  else
4092  {
4093  in_first = in_last = 0; // zero the output just in case
4094  }
4095  return found;
4096 }
4097 
4098 //---------------------------------------------------------------------
4099 
4100 template<class Alloc>
4102  size_type from,
4103  size_type& pos) const BMNOEXCEPT
4104 {
4105  BM_ASSERT_THROW(from < bm::id_max, BM_ERR_RANGE);
4106 
4107  bool ret = false;
4108 
4109  if (!rank_in || !blockman_.is_init())
4110  return ret;
4111 
4112  block_idx_type nb = (from >> bm::set_block_shift);
4114  unsigned bit_pos = 0;
4115 
4116  for (; nb < bm::set_total_blocks; ++nb)
4117  {
4118  int no_more_blocks;
4119  const bm::word_t* block = blockman_.get_block(nb, &no_more_blocks);
4120  if (block)
4121  {
4122  if (!nbit && (rank_in > bm::gap_max_bits)) // requested rank cannot be in this block
4123  {
4124  unsigned cnt = blockman_.block_bitcount(block);
4125  BM_ASSERT(cnt < rank_in);
4126  rank_in -= cnt;
4127  continue;
4128  }
4129  else
4130  {
4131  rank_in = bm::block_find_rank(block, rank_in, nbit, bit_pos);
4132  if (!rank_in) // target found
4133  {
4134  pos = bit_pos + (nb * bm::set_block_size * 32);
4135  return true;
4136  }
4137  }
4138  }
4139  else
4140  {
4141  // TODO: better next block search
4142  if (no_more_blocks)
4143  break;
4144  }
4145  nbit ^= nbit; // zero start bit after first scanned block
4146  } // for nb
4147 
4148  return ret;
4149 }
4150 
4151 //---------------------------------------------------------------------
4152 
4153 template<class Alloc>
4155  size_type from,
4156  size_type& pos,
4157  const rs_index_type& rs_idx) const BMNOEXCEPT
4158 {
4159  BM_ASSERT_THROW(from < bm::id_max, BM_ERR_RANGE);
4160 
4161  bool ret = false;
4162 
4163  if (!rank_in ||
4164  !blockman_.is_init() ||
4165  (rs_idx.count() < rank_in))
4166  return ret;
4167 
4168  block_idx_type nb;
4169  if (from)
4170  nb = (from >> bm::set_block_shift);
4171  else
4172  {
4173  nb = rs_idx.find(rank_in);
4174  BM_ASSERT(rs_idx.rcount(nb) >= rank_in);
4175  if (nb)
4176  rank_in -= rs_idx.rcount(nb-1);
4177  }
4178 
4180  unsigned bit_pos = 0;
4181 
4182  for (; nb < rs_idx.get_total(); ++nb)
4183  {
4184  int no_more_blocks;
4185  const bm::word_t* block = blockman_.get_block(nb, &no_more_blocks);
4186  if (block)
4187  {
4188  if (!nbit) // check if the whole block can be skipped
4189  {
4190  unsigned block_bc = rs_idx.count(nb);
4191  if (rank_in <= block_bc) // target block
4192  {
4193  nbit = rs_idx.select_sub_range(nb, rank_in);
4194  rank_in = bm::block_find_rank(block, rank_in, nbit, bit_pos);
4195  BM_ASSERT(rank_in == 0);
4196  pos = bit_pos + (nb * bm::set_block_size * 32);
4197  return true;
4198  }
4199  rank_in -= block_bc;
4200  continue;
4201  }
4202 
4203  rank_in = bm::block_find_rank(block, rank_in, nbit, bit_pos);
4204  if (!rank_in) // target found
4205  {
4206  pos = bit_pos + (nb * bm::set_block_size * 32);
4207  return true;
4208  }
4209  }
4210  else
4211  {
4212  // TODO: better next block search
4213  if (no_more_blocks)
4214  break;
4215  }
4216  nbit ^= nbit; // zero start bit after first scanned block
4217  } // for nb
4218 
4219  return ret;
4220 }
4221 
4222 //---------------------------------------------------------------------
4223 
4224 template<class Alloc>
4226  const rs_index_type& rs_idx) const BMNOEXCEPT
4227 {
4228  bool ret = false;
4229 
4230  if (!rank_in ||
4231  !blockman_.is_init() ||
4232  (rs_idx.count() < rank_in))
4233  return ret;
4234 
4235  block_idx_type nb;
4236  bm::gap_word_t sub_range_from;
4237 
4238  bool found = rs_idx.find(&rank_in, &nb, &sub_range_from);
4239  if (!found)
4240  return found;
4241 
4242  unsigned i, j;
4243  bm::get_block_coord(nb, i, j);
4244  const bm::word_t* block = blockman_.get_block_ptr(i, j);
4245 
4246  block = BLOCK_ADDR_SAN(block); // TODO: optimize FULL block selection
4247 
4248  BM_ASSERT(block);
4249  BM_ASSERT(rank_in <= rs_idx.count(nb));
4250 
4251  unsigned bit_pos = 0;
4252  rank_in = bm::block_find_rank(block, rank_in, sub_range_from, bit_pos);
4253  BM_ASSERT(rank_in == 0);
4254  pos = bit_pos + (nb * bm::set_block_size * 32);
4255  return true;
4256 }
4257 
4258 //---------------------------------------------------------------------
4259 
4260 template<class Alloc>
4261 typename bvector<Alloc>::size_type
4263 {
4264  if (!blockman_.is_init())
4265  return 0;
4266 
4267  // calculate logical block number
4268  block_idx_type nb = (prev >> bm::set_block_shift);
4269  unsigned i, j;
4270  bm::get_block_coord(nb, i, j);
4271  const bm::word_t* block = blockman_.get_block_ptr(i, j);
4272 
4273  if (block)
4274  {
4275  unsigned block_pos;
4276  bool found = false;
4277  // calculate word number in block and bit
4278  unsigned nbit = unsigned(prev & bm::set_block_mask);
4279  if (BM_IS_GAP(block))
4280  {
4281  if (bm::gap_block_find(BMGAP_PTR(block), nbit, &block_pos))
4282  {
4283  prev = (size_type(nb) * bm::gap_max_bits) + block_pos;
4284  return prev;
4285  }
4286  }
4287  else
4288  {
4289  if (block == FULL_BLOCK_FAKE_ADDR)
4290  return prev;
4291  found = bm::bit_block_find(block, nbit, &block_pos);
4292  if (found)
4293  {
4294  prev = (size_type(nb) * bm::gap_max_bits) + block_pos;
4295  return prev;
4296  }
4297  }
4298  }
4299  ++j;
4300  block_idx_type top_blocks = blockman_.top_block_size();
4301  for (; i < top_blocks; ++i)
4302  {
4303  const bm::word_t* const* blk_blk = blockman_.get_topblock(i);
4304  if (blk_blk)
4305  {
4306  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
4307  blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
4308 
4309  for (; j < bm::set_sub_array_size; ++j)
4310  {
4311  const bm::word_t* blk = blk_blk[j];
4312  if (blk)
4313  {
4314  bool found;
4315  unsigned block_pos;
4316  if (blk == FULL_BLOCK_FAKE_ADDR)
4317  {
4318  found = true; block_pos = 0;
4319  }
4320  else
4321  {
4322  bool is_gap = BM_IS_GAP(blk);
4323  found = (is_gap) ? bm::gap_find_first(BMGAP_PTR(blk), &block_pos)
4324  : bm::bit_find_first(blk, &block_pos);
4325  }
4326  if (found)
4327  {
4328  size_type base_idx = size_type(i) * bm::bits_in_array;
4329  base_idx += j * bm::gap_max_bits;
4330  prev = base_idx + block_pos;
4331  return prev;
4332  }
4333  }
4334  } // for j
4335  }
4336  j = 0;
4337  } // for i
4338 
4339  return 0;
4340 }
4341 
4342 //---------------------------------------------------------------------
4343 
4344 template<class Alloc>
4346 bvector<Alloc>::check_or_next_extract(size_type prev)
4347 {
4348  if (!blockman_.is_init())
4349  return 0;
4350  // TODO: optimization
4351  size_type pos = this->check_or_next(prev);
4352  if (pos >= prev)
4353  this->clear_bit_no_check(pos);
4354  return pos;
4355 }
4356 
4357 //---------------------------------------------------------------------
4358 
4359 template<class Alloc>
4361 {
4362  return insert(0, false);
4363 }
4364 
4365 //---------------------------------------------------------------------
4366 
4367 template<class Alloc>
4369 {
4370  bool b = this->test(0);
4371  this->erase(0);
4372  return b;
4373 }
4374 
4375 //---------------------------------------------------------------------
4376 
4377 template<class Alloc>
4379 {
4380  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
4381 
4382  if (size_ < bm::id_max)
4383  ++size_;
4384  if (!blockman_.is_init())
4385  {
4386  if (value)
4387  set(n);
4388  return 0;
4389  }
4390 
4391  // calculate logical block number
4392  block_idx_type nb = (n >> bm::set_block_shift);
4393 
4394  int block_type;
4395  bm::word_t carry_over = 0;
4396 
4397  if (!n && !value) // regular shift-right by 1 bit
4398  {}
4399  else // process target block insertion
4400  {
4401  unsigned i, j;
4402  bm::get_block_coord(nb, i, j);
4403  bm::word_t* block = blockman_.get_block_ptr(i, j);
4404 
4405  if (!block && !value) // nothing to do
4406  {}
4407  else
4408  {
4409  if (!block)
4410  block = blockman_.check_allocate_block(nb, BM_BIT);
4411  if (BM_IS_GAP(block) || IS_FULL_BLOCK(block))
4412  block = blockman_.deoptimize_block(nb); // TODO: optimize GAP block insert
4413  BM_ASSERT(IS_VALID_ADDR(block));
4414  {
4415  unsigned nbit = unsigned(n & bm::set_block_mask);
4416  carry_over = bm::bit_block_insert(block, nbit, value);
4417  }
4418  }
4419  ++nb;
4420  }
4421 
4422  unsigned i0, j0;
4423  bm::get_block_coord(nb, i0, j0);
4424 
4425  unsigned top_blocks = blockman_.top_block_size();
4426  bm::word_t*** blk_root = blockman_.top_blocks_root();
4427  bm::word_t** blk_blk;
4428  bm::word_t* block;
4429 
4430  for (unsigned i = i0; i < bm::set_top_array_size; ++i)
4431  {
4432  if (i >= top_blocks)
4433  {
4434  if (!carry_over)
4435  break;
4436  blk_blk = 0;
4437  }
4438  else
4439  blk_blk = blk_root[i];
4440 
4441  if (!blk_blk) // top level group of blocks missing - can skip it
4442  {
4443  if (carry_over)
4444  {
4445  // carry over: needs block-list extension and a block
4447  if (nblock > nb)
4448  {
4449  block =
4450  blockman_.check_allocate_block(nblock, 0, 0, &block_type, false);
4451  block[0] |= carry_over; // block is brand new (0000)
4452 
4453  // reset all control vars (blocks tree may have re-allocated)
4454  blk_root = blockman_.top_blocks_root();
4455  blk_blk = blk_root[i];
4456  top_blocks = blockman_.top_block_size();
4457 
4458  carry_over = 0;
4459  }
4460  }
4461  continue;
4462  }
4463  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
4464  {
4465  if (carry_over)
4466  continue;
4467  blk_blk = blockman_.check_alloc_top_subblock(i);
4468  }
4469 
4470  unsigned j = j0;
4471  do
4472  {
4474  block = blk_blk[j];
4475  if (!block)
4476  {
4477  if (carry_over)
4478  {
4479  size_type nbit = nblock * bm::gap_max_bits;
4480  set_bit_no_check(nbit);
4481  carry_over = 0; block = 0;
4482  }
4483  // no CO: tight loop scan for the next available block (if any)
4484  for (++j; j < bm::set_sub_array_size; ++j)
4485  {
4486  if (0 != (block = blk_blk[j]))
4487  {
4488  nblock = (i * bm::set_sub_array_size) + j;
4489  break;
4490  }
4491  } // for j
4492  if (!block) // no more blocks in this j-dimention
4493  continue;
4494  }
4495  if (IS_FULL_BLOCK(block))
4496  {
4497  // 1 in 1 out, block is still all 0xFFFF..
4498  // 0 into 1 -> carry in 0, carry out 1
4499  if (!carry_over)
4500  {
4501  block = blockman_.deoptimize_block(nblock);
4502  block[0] <<= (carry_over = 1);
4503  }
4504  continue;
4505  }
4506  if (BM_IS_GAP(block))
4507  {
4508  if (nblock == bm::set_total_blocks-1) // last block
4509  {
4510  // process as a bit-block (for simplicity)
4511  block = blockman_.deoptimize_block(nblock);
4512  }
4513  else // use gap-block shift here
4514  {
4515  unsigned new_block_len;
4516  bm::gap_word_t* gap_blk = BMGAP_PTR(block);
4517 
4518  carry_over = bm::gap_shift_r1(gap_blk, carry_over, &new_block_len);
4519  unsigned threshold = bm::gap_limit(gap_blk, blockman_.glen());
4520  if (new_block_len > threshold)
4521  {
4522  blockman_.extend_gap_block(nblock, gap_blk);
4523  }
4524  continue;
4525  }
4526  }
4527  // bit-block
4528  {
4529  bm::word_t acc;
4530  carry_over = bm::bit_block_shift_r1_unr(block, &acc, carry_over);
4531  BM_ASSERT(carry_over <= 1);
4532 
4533  if (nblock == bm::set_total_blocks-1) // last possible block
4534  {
4535  carry_over = block[bm::set_block_size-1] & (1u<<31);
4536  block[bm::set_block_size-1] &= ~(1u<<31); // clear the 1-bit tail
4537  if (!acc) // block shifted out: release memory
4538  blockman_.zero_block(nblock);
4539  break;
4540  }
4541  if (!acc)
4542  blockman_.zero_block(nblock);
4543  }
4544 
4545  } while (++j < bm::set_sub_array_size);
4546  j0 = 0;
4547  } // for i
4548  return carry_over;
4549 
4550 }
4551 
4552 //---------------------------------------------------------------------
4553 
4554 template<class Alloc>
4556 {
4557  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
4558 
4559  if (!blockman_.is_init())
4560  return ;
4561 
4562  // calculate logical block number
4563  block_idx_type nb = (n >> bm::set_block_shift);
4564 
4565  if (!n ) // regular shift-left by 1 bit
4566  {}
4567  else // process target block bit erase
4568  {
4569  unsigned i, j;
4570  bm::get_block_coord(nb, i, j);
4571  bm::word_t* block = blockman_.get_block_ptr(i, j);
4572  bool carry_over = test_first_block_bit(nb+1);
4573  if (!block)
4574  {
4575  if (carry_over)
4576  {
4577  block = blockman_.check_allocate_block(nb, BM_BIT);
4578  block[bm::set_block_size-1] = (1u << 31u);
4579  }
4580  }
4581  else
4582  {
4583  if (BM_IS_GAP(block) || IS_FULL_BLOCK(block))
4584  block = blockman_.deoptimize_block(nb);
4585  BM_ASSERT(IS_VALID_ADDR(block));
4586  unsigned nbit = unsigned(n & bm::set_block_mask);
4587  bm::bit_block_erase(block, nbit, carry_over);
4588  }
4589  ++nb;
4590  }
4591  // left shifting of all other blocks
4592  //
4593  unsigned i0, j0;
4594  bm::get_block_coord(nb, i0, j0);
4595 
4596  unsigned top_blocks = blockman_.top_block_size();
4597  bm::word_t*** blk_root = blockman_.top_blocks_root();
4598  bm::word_t** blk_blk;
4599  bm::word_t* block;
4600 
4601  for (unsigned i = i0; i < bm::set_top_array_size; ++i)
4602  {
4603  if (i >= top_blocks)
4604  break;
4605  else
4606  blk_blk = blk_root[i];
4607 
4608  if (!blk_blk) // top level group of blocks missing
4609  {
4610  bool found = bm::find_not_null_ptr(blk_root, i+1, top_blocks, &i);
4611  if (!found)
4612  break;
4613  --i;
4614  continue;
4615  }
4616  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
4617  {
4618  bool carry_over = 0;
4619  if (i + 1 < bm::set_top_array_size)
4620  {
4622  carry_over = this->test(co_idx);
4623  if (carry_over)
4624  continue; // nothing to do (1 in)
4625  else
4626  blk_blk = blockman_.check_alloc_top_subblock(i);
4627  }
4628  else
4629  {
4630  blk_blk = blockman_.check_alloc_top_subblock(i);
4631  }
4632  }
4633 
4634  unsigned j = j0;
4635  do
4636  {
4638  bool carry_over = 0; // test_first_block_bit(nblock+1); // look ahead for CO
4639  block = blk_blk[j];
4640  if (!block)
4641  {
4642  // no CO: tight loop scan for the next available block (if any)
4643  bool no_blocks = (j == 0);
4644  for (++j; j < bm::set_sub_array_size; ++j)
4645  {
4646  if (0 != (block = blk_blk[j]))
4647  {
4648  nblock = (block_idx_type(i) * bm::set_sub_array_size) + j;
4649  break;
4650  }
4651  } // for j
4652  if (!block) // no more blocks in this j-dimention ?
4653  {
4654  if (j == bm::set_sub_array_size && no_blocks)
4655  {
4656  blockman_.zero_block(i, j-1); // free the top level
4657  }
4658  continue;
4659  }
4660  }
4661  BM_ASSERT(block);
4662  if (IS_FULL_BLOCK(block))
4663  {
4664  carry_over = test_first_block_bit(nblock+1); // look ahead for CO
4665  // 1 in 1 out, block is still all 0xFFFF..
4666  // 0 into 1 -> carry in 0, carry out 1
4667  if (!carry_over)
4668  {
4669  block = blockman_.deoptimize_block(nblock);
4670  block[bm::set_block_size-1] >>= 1;
4671  }
4672  carry_over = 1;
4673  }
4674  else
4675  if (BM_IS_GAP(block))
4676  {
4677  carry_over = test_first_block_bit(nblock+1); // look ahead for CO
4678  unsigned new_block_len;
4679  bm::gap_word_t* gap_blk = BMGAP_PTR(block);
4680 
4681  carry_over = bm::gap_shift_l1(gap_blk, carry_over, &new_block_len);
4682  unsigned threshold = bm::gap_limit(gap_blk, blockman_.glen());
4683  if (new_block_len > threshold)
4684  blockman_.extend_gap_block(nblock, gap_blk);
4685  else
4686  {
4687  if (bm::gap_is_all_zero(gap_blk))
4688  blockman_.zero_block(i, j);
4689  }
4690  }
4691  else // bit-block
4692  {
4693  bm::word_t acc;
4694  carry_over = bm::bit_block_shift_l1_unr(block, &acc, carry_over);
4695  if (!acc)
4696  blockman_.zero_block(i, j);
4697  }
4698 
4699  if (carry_over && nblock)
4700  {
4702  }
4703 
4704  } while (++j < bm::set_sub_array_size);
4705  j0 = 0;
4706  } // for i
4707 
4708 }
4709 
4710 //---------------------------------------------------------------------
4711 
4712 template<class Alloc>
4714 {
4715  if (nb >= bm::set_total_blocks) // last possible block
4716  return false;
4717  return test(nb * bm::gap_max_bits);
4718 }
4719 
4720 
4721 //---------------------------------------------------------------------
4722 
4723 template<class Alloc>
4725 {
4726  if (!bv.blockman_.is_init())
4727  {
4728  this->move_from(bv);
4729  return;
4730  }
4731 
4732  unsigned top_blocks = blockman_.top_block_size();
4733  if (size_ < bv.size_) // this vect shorter than the arg.
4734  {
4735  size_ = bv.size_;
4736  }
4737  unsigned arg_top_blocks = bv.blockman_.top_block_size();
4738  top_blocks = blockman_.reserve_top_blocks(arg_top_blocks);
4739 
4740 
4741  bm::word_t*** blk_root = blockman_.top_blocks_root();
4742  bm::word_t*** blk_root_arg = bv.blockman_.top_blocks_root();
4743 
4744  for (unsigned i = 0; i < top_blocks; ++i)
4745  {
4746  bm::word_t** blk_blk = blk_root[i];
4747  bm::word_t** blk_blk_arg = (i < arg_top_blocks) ? blk_root_arg[i] : 0;
4748  if (blk_blk == blk_blk_arg || !blk_blk_arg) // nothing to do (0 OR 0 == 0)
4749  continue;
4750  if (!blk_blk && blk_blk_arg) // top block transfer
4751  {
4752  BM_ASSERT(i < arg_top_blocks);
4753 
4754  blk_root[i] = blk_root_arg[i];
4755  blk_root_arg[i] = 0;
4756  continue;
4757  }
4758  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
4759  continue;
4760  if ((bm::word_t*)blk_blk_arg == FULL_BLOCK_FAKE_ADDR)
4761  {
4762  blockman_.deallocate_top_subblock(i);
4763  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
4764  continue;
4765  }
4766 
4767  unsigned j = 0;
4768  bm::word_t* blk;
4769  bm::word_t* arg_blk;
4770  do
4771  {
4772  blk = blk_blk[j]; arg_blk = blk_blk_arg[j];
4773  if (blk != arg_blk)
4774  {
4775  if (!blk && arg_blk) // block transfer
4776  {
4777  blockman_.set_block_ptr(i, j, arg_blk);
4778  bv.blockman_.set_block_ptr(i, j, 0);
4779  }
4780  else // need full OR
4781  {
4782  combine_operation_block_or(i, j, blk, arg_blk);
4783  }
4784  }
4785  } while (++j < bm::set_sub_array_size);
4786  } // for i
4787 }
4788 
4789 //---------------------------------------------------------------------
4790 
4791 template<class Alloc>
4793  const bm::word_t* arg_blk,
4794  bool arg_gap,
4795  bm::operation opcode)
4796 {
4797  unsigned i0, j0;
4798  bm::get_block_coord(nb, i0, j0);
4799  bm::word_t* blk = blockman_.get_block_ptr(i0, j0);
4800 
4801  bool gap = BM_IS_GAP(blk);
4802  combine_operation_with_block(nb, gap, blk, arg_blk, arg_gap, opcode);
4803 }
4804 
4805 //---------------------------------------------------------------------
4806 
4807 template<class Alloc>
4810  const bm::bvector<Alloc>& bv2,
4811  typename bm::bvector<Alloc>::optmode opt_mode)
4812 {
4813  if (blockman_.is_init())
4814  blockman_.deinit_tree();
4815 
4816  if (&bv1 == &bv2)
4817  {
4818  this->bit_or(bv2);
4819  return *this;
4820  }
4821  if (this == &bv1)
4822  {
4823  this->bit_or(bv2);
4824  return *this;
4825  }
4826  if (this == &bv2)
4827  {
4828  this->bit_or(bv1);
4829  return *this;
4830  }
4831 
4832  const blocks_manager_type& bman1 = bv1.get_blocks_manager();
4833  const blocks_manager_type& bman2 = bv2.get_blocks_manager();
4834 
4835  unsigned top_blocks1 = bman1.top_block_size();
4836  unsigned top_blocks2 = bman2.top_block_size();
4837  unsigned top_blocks = (top_blocks2 > top_blocks1) ? top_blocks2 : top_blocks1;
4838  top_blocks = blockman_.reserve_top_blocks(top_blocks);
4839 
4840  size_ = bv1.size_;
4841  if (size_ < bv2.size_)
4842  size_ = bv2.size_;
4843 
4844  bm::word_t*** blk_root_arg1 = bv1.blockman_.top_blocks_root();
4845  if (!blk_root_arg1)
4846  {
4847  this->bit_or(bv2);
4848  return *this;
4849  }
4850  bm::word_t*** blk_root_arg2 = bv2.blockman_.top_blocks_root();
4851  if (!blk_root_arg2)
4852  {
4853  this->bit_or(bv1);
4854  return *this;
4855  }
4856 
4857  for (unsigned i = 0; i < top_blocks; ++i)
4858  {
4859  bm::word_t** blk_blk_arg1 = (i < top_blocks1) ? blk_root_arg1[i] : 0;
4860  bm::word_t** blk_blk_arg2 = (i < top_blocks2) ? blk_root_arg2[i] : 0;
4861 
4862  if (blk_blk_arg1 == blk_blk_arg2)
4863  {
4864  BM_ASSERT(!blk_blk_arg1 || (bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR);
4865  bm::word_t*** blk_root = blockman_.top_blocks_root();
4866  blk_root[i] = blk_blk_arg1;
4867  continue;
4868  }
4869  if ((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR ||
4870  (bm::word_t*)blk_blk_arg2 == FULL_BLOCK_FAKE_ADDR)
4871  {
4872  bm::word_t*** blk_root = blockman_.top_blocks_root();
4873  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
4874  continue;
4875  }
4876  bm::word_t** blk_blk = blockman_.alloc_top_subblock(i);
4877  bool any_blocks = false;
4878  unsigned j = 0;
4879  do
4880  {
4881  const bm::word_t* arg_blk1 = blk_blk_arg1 ? blk_blk_arg1[j] : 0;
4882  const bm::word_t* arg_blk2 = blk_blk_arg2 ? blk_blk_arg2[j] : 0;
4883  if (arg_blk1 == arg_blk2 && !arg_blk1)
4884  continue;
4885  bool need_opt = combine_operation_block_or(i, j, arg_blk1, arg_blk2);
4886  if (need_opt && opt_mode == opt_compress)
4887  blockman_.optimize_bit_block(i, j);
4888  any_blocks |= bool(blk_blk[j]);
4889  } while (++j < bm::set_sub_array_size);
4890 
4891  if (!any_blocks)
4892  blockman_.free_top_subblock(i);
4893 
4894  } // for i
4895 
4896  if (opt_mode != opt_none)
4897  blockman_.free_temp_block();
4898 
4899  return *this;
4900 }
4901 
4902 //---------------------------------------------------------------------
4903 
4904 template<class Alloc>
4907  const bm::bvector<Alloc>& bv2,
4908  typename bm::bvector<Alloc>::optmode opt_mode)
4909 {
4910  if (blockman_.is_init())
4911  blockman_.deinit_tree();
4912 
4913  if (&bv1 == &bv2)
4914  return *this; // nothing to do empty result
4915 
4916  if (this == &bv1)
4917  {
4918  this->bit_xor(bv2);
4919  return *this;
4920  }
4921  if (this == &bv2)
4922  {
4923  this->bit_xor(bv1);
4924  return *this;
4925  }
4926 
4927  const blocks_manager_type& bman1 = bv1.get_blocks_manager();
4928  if (!bman1.is_init())
4929  {
4930  *this = bv2;
4931  return *this;
4932  }
4933  const blocks_manager_type& bman2 = bv2.get_blocks_manager();
4934  if (!bman2.is_init())
4935  {
4936  *this = bv1;
4937  return *this;
4938  }
4939 
4940  unsigned top_blocks1 = bman1.top_block_size();
4941  unsigned top_blocks2 = bman2.top_block_size();
4942  unsigned top_blocks = (top_blocks2 > top_blocks1) ? top_blocks2 : top_blocks1;
4943  top_blocks = blockman_.reserve_top_blocks(top_blocks);
4944 
4945  size_ = bv1.size_;
4946  if (size_ < bv2.size_)
4947  size_ = bv2.size_;
4948 
4949  bm::word_t*** blk_root_arg1 = bv1.blockman_.top_blocks_root();
4950  bm::word_t*** blk_root_arg2 = bv2.blockman_.top_blocks_root();
4951 
4952  for (unsigned i = 0; i < top_blocks; ++i)
4953  {
4954  bm::word_t** blk_blk_arg1 = (i < top_blocks1) ? blk_root_arg1[i] : 0;
4955  bm::word_t** blk_blk_arg2 = (i < top_blocks2) ? blk_root_arg2[i] : 0;
4956 
4957  if (blk_blk_arg1 == blk_blk_arg2)
4958  {
4959  if (!blk_blk_arg1)
4960  continue;
4961  BM_ASSERT((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR);
4962  blockman_.deallocate_top_subblock(i);
4963  continue;
4964  }
4965  if ((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR)
4966  {
4967  if (!blk_blk_arg2)
4968  {
4969  set_full_sb:
4970  bm::word_t*** blk_root= blockman_.top_blocks_root();
4971  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
4972  continue;
4973  }
4974  blk_blk_arg1 = FULL_SUB_BLOCK_REAL_ADDR;
4975  }
4976  if ((bm::word_t*)blk_blk_arg2 == FULL_BLOCK_FAKE_ADDR)
4977  {
4978  if (!blk_blk_arg1)
4979  goto set_full_sb;
4980  blk_blk_arg2 = FULL_SUB_BLOCK_REAL_ADDR;
4981  }
4982 
4983  bm::word_t** blk_blk = blockman_.alloc_top_subblock(i);
4984  bool any_blocks = false;
4985  unsigned j = 0;
4986  do
4987  {
4988  const bm::word_t* arg_blk1; const bm::word_t* arg_blk2;
4989  arg_blk1 = blk_blk_arg1 ? blk_blk_arg1[j] : 0;
4990  arg_blk2 = blk_blk_arg2 ? blk_blk_arg2[j] : 0;
4991 
4992  if ((arg_blk1 == arg_blk2) &&
4993  (!arg_blk1 || arg_blk1 == FULL_BLOCK_FAKE_ADDR))
4994  continue; // 0 ^ 0 == 0 , 1 ^ 1 == 0 (nothing to do)
4995 
4996  bool need_opt = combine_operation_block_xor(i, j, arg_blk1, arg_blk2);
4997  if (need_opt && opt_mode == opt_compress)
4998  blockman_.optimize_bit_block(i, j);
4999  any_blocks |= bool(blk_blk[j]);
5000  } while (++j < bm::set_sub_array_size);
5001 
5002  if (!any_blocks)
5003  blockman_.free_top_subblock(i);
5004 
5005  } // for i
5006 
5007  if (opt_mode != opt_none)
5008  blockman_.free_temp_block();
5009 
5010  return *this;
5011 }
5012 
5013 //---------------------------------------------------------------------
5014 
5015 template<class Alloc>
5018  const bm::bvector<Alloc>& bv2,
5019  typename bm::bvector<Alloc>::optmode opt_mode)
5020 {
5021  if (&bv1 == &bv2)
5022  {
5023  this->bit_or(bv1);
5024  return *this;
5025  }
5026  if (this == &bv1)
5027  {
5028  this->bit_and(bv2);
5029  return *this;
5030  }
5031  if (this == &bv2)
5032  {
5033  this->bit_and(bv1);
5034  return *this;
5035  }
5036  if (blockman_.is_init())
5037  blockman_.deinit_tree();
5038 
5039  const blocks_manager_type& bman1 = bv1.get_blocks_manager();
5040  const blocks_manager_type& bman2 = bv2.get_blocks_manager();
5041  if (!bman1.is_init() || !bman2.is_init())
5042  return *this;
5043 
5044  unsigned top_blocks1 = bman1.top_block_size();
5045  unsigned top_blocks2 = bman2.top_block_size();
5046  unsigned top_blocks = (top_blocks2 > top_blocks1) ? top_blocks2 : top_blocks1;
5047  top_blocks = blockman_.reserve_top_blocks(top_blocks);
5048 
5049  size_ = bv1.size_;
5050  if (size_ < bv2.size_)
5051  size_ = bv2.size_;
5052 
5053  bm::word_t*** blk_root_arg1 = bv1.blockman_.top_blocks_root();
5054  bm::word_t*** blk_root_arg2 = bv2.blockman_.top_blocks_root();
5055 
5056  for (unsigned i = 0; i < top_blocks; ++i)
5057  {
5058  bm::word_t** blk_blk_arg1 = (i < top_blocks1) ? blk_root_arg1[i] : 0;
5059  bm::word_t** blk_blk_arg2 = (i < top_blocks2) ? blk_root_arg2[i] : 0;
5060 
5061  if (blk_blk_arg1 == blk_blk_arg2)
5062  {
5063  if (!blk_blk_arg1)
5064  continue; // 0 & 0 == 0
5065  if ((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR)
5066  {
5067  bm::word_t*** blk_root = blockman_.top_blocks_root();
5068  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
5069  continue;
5070  }
5071  }
5072  if ((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR)
5073  blk_blk_arg1 = FULL_SUB_BLOCK_REAL_ADDR;
5074  if ((bm::word_t*)blk_blk_arg2 == FULL_BLOCK_FAKE_ADDR)
5075  blk_blk_arg2 = FULL_SUB_BLOCK_REAL_ADDR;
5076 
5077  bm::word_t** blk_blk = blockman_.alloc_top_subblock(i);
5078  bool any_blocks = false;
5079  unsigned j = 0;
5080  do
5081  {
5082  const bm::word_t* arg_blk1; const bm::word_t* arg_blk2;
5083  arg_blk1 = blk_blk_arg1 ? blk_blk_arg1[j] : 0;
5084  arg_blk2 = blk_blk_arg2 ? blk_blk_arg2[j] : 0;
5085 
5086  if ((arg_blk1 == arg_blk2) && !arg_blk1)
5087  continue; // 0 & 0 == 0
5088 
5089  bool need_opt = combine_operation_block_and(i, j, arg_blk1, arg_blk2);
5090  if (need_opt && opt_mode == opt_compress)
5091  blockman_.optimize_bit_block(i, j);
5092  any_blocks |= bool(blk_blk[j]);
5093  } while (++j < bm::set_sub_array_size);
5094 
5095  if (!any_blocks)
5096  blockman_.free_top_subblock(i);
5097 
5098  } // for i
5099 
5100  if (opt_mode != opt_none)
5101  blockman_.free_temp_block();
5102 
5103  return *this;
5104 }
5105 
5106 
5107 //---------------------------------------------------------------------
5108 
5109 template<class Alloc>
5112  const bm::bvector<Alloc>& bv2,
5113  typename bm::bvector<Alloc>::optmode opt_mode)
5114 {
5115  if (blockman_.is_init())
5116  blockman_.deinit_tree();
5117 
5118  if (&bv1 == &bv2)
5119  return *this; // nothing to do empty result
5120 
5121  if (this == &bv1)
5122  {
5123  this->bit_sub(bv2);
5124  return *this;
5125  }
5126  if (this == &bv2)
5127  {
5128  this->bit_sub(bv1);
5129  return *this;
5130  }
5131 
5132  const blocks_manager_type& bman1 = bv1.get_blocks_manager();
5133  const blocks_manager_type& bman2 = bv2.get_blocks_manager();
5134  if (!bman1.is_init())
5135  {
5136  return *this;
5137  }
5138  if (!bman2.is_init())
5139  {
5140  this->bit_or(bv1);
5141  return *this;
5142  }
5143 
5144  unsigned top_blocks1 = bman1.top_block_size();
5145  unsigned top_blocks2 = bman2.top_block_size();
5146  unsigned top_blocks = (top_blocks2 > top_blocks1) ? top_blocks2 : top_blocks1;
5147  top_blocks = blockman_.reserve_top_blocks(top_blocks);
5148 
5149  size_ = bv1.size_;
5150  if (size_ < bv2.size_)
5151  size_ = bv2.size_;
5152 
5153  bm::word_t*** blk_root_arg1 = bv1.blockman_.top_blocks_root();
5154  bm::word_t*** blk_root_arg2 = bv2.blockman_.top_blocks_root();
5155 
5156  for (unsigned i = 0; i < top_blocks; ++i)
5157  {
5158  bm::word_t** blk_blk_arg1 = (i < top_blocks1) ? blk_root_arg1[i] : 0;
5159  bm::word_t** blk_blk_arg2 = (i < top_blocks2) ? blk_root_arg2[i] : 0;
5160 
5161  if (blk_blk_arg1 == blk_blk_arg2)
5162  continue; // 0 AND NOT 0 == 0
5163  if ((bm::word_t*)blk_blk_arg2 == FULL_BLOCK_FAKE_ADDR)
5164  continue;
5165  if ((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR)
5166  blk_blk_arg1 = FULL_SUB_BLOCK_REAL_ADDR;
5167 
5168  bm::word_t** blk_blk = blockman_.alloc_top_subblock(i);
5169  bool any_blocks = false;
5170  unsigned j = 0;
5171  do
5172  {
5173  const bm::word_t* arg_blk1 = blk_blk_arg1 ? blk_blk_arg1[j] : 0;
5174  const bm::word_t* arg_blk2 = blk_blk_arg2 ? blk_blk_arg2[j] : 0;
5175  if ((arg_blk1 == arg_blk2) && !arg_blk1)
5176  continue; // 0 & ~0 == 0
5177 
5178  bool need_opt = combine_operation_block_sub(i, j, arg_blk1, arg_blk2);
5179  if (need_opt && opt_mode == opt_compress)
5180  blockman_.optimize_bit_block(i, j);
5181  any_blocks |= bool(blk_blk[j]);
5182  } while (++j < bm::set_sub_array_size);
5183 
5184  if (!any_blocks)
5185  blockman_.free_top_subblock(i);
5186 
5187  } // for i
5188 
5189  if (opt_mode != opt_none)
5190  blockman_.free_temp_block();
5191 
5192  return *this;
5193 }
5194 
5195 
5196 //---------------------------------------------------------------------
5197 
5198 #define BM_OR_OP(x) \
5199  { \
5200  blk = blk_blk[j+x]; arg_blk = blk_blk_arg[j+x]; \
5201  if (blk != arg_blk) \
5202  combine_operation_block_or(i, j+x, blk, arg_blk); \
5203  }
5204 
5205 template<class Alloc>
5207 {
5208  if (!bv.blockman_.is_init())
5209  return;
5210 
5211  unsigned top_blocks = blockman_.top_block_size();
5212  if (size_ < bv.size_)
5213  size_ = bv.size_;
5214 
5215  unsigned arg_top_blocks = bv.blockman_.top_block_size();
5216  top_blocks = blockman_.reserve_top_blocks(arg_top_blocks);
5217 
5218  bm::word_t*** blk_root = blockman_.top_blocks_root();
5219  bm::word_t*** blk_root_arg = bv.blockman_.top_blocks_root();
5220 
5221  for (unsigned i = 0; i < top_blocks; ++i)
5222  {
5223  bm::word_t** blk_blk = blk_root[i];
5224  bm::word_t** blk_blk_arg = (i < arg_top_blocks) ? blk_root_arg[i] : 0;
5225  if (blk_blk == blk_blk_arg || !blk_blk_arg) // nothing to do (0 OR 0 == 0)
5226  continue;
5227  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5228  continue;
5229  if ((bm::word_t*)blk_blk_arg == FULL_BLOCK_FAKE_ADDR)
5230  {
5231  blockman_.deallocate_top_subblock(i);
5232  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
5233  continue;
5234  }
5235  if (!blk_blk)
5236  blk_blk = blockman_.alloc_top_subblock(i);
5237 
5238  unsigned j = 0;
5239  bm::word_t* blk;
5240  const bm::word_t* arg_blk;
5241  do
5242  {
5243  #if defined(BM64_AVX2) || defined(BM64_AVX512)
5244  if (!avx2_test_all_eq_wave2(blk_blk + j, blk_blk_arg + j))
5245  {
5246  BM_OR_OP(0)
5247  BM_OR_OP(1)
5248  BM_OR_OP(2)
5249  BM_OR_OP(3)
5250  }
5251  j += 4;
5252  #elif defined(BM64_SSE4)
5253  if (!sse42_test_all_eq_wave2(blk_blk + j, blk_blk_arg + j))
5254  {
5255  BM_OR_OP(0)
5256  BM_OR_OP(1)
5257  }
5258  j += 2;
5259  #else
5260  BM_OR_OP(0)
5261  ++j;
5262  #endif
5263  } while (j < bm::set_sub_array_size);
5264  } // for i
5265 }
5266 
5267 #undef BM_OR_OP
5268 
5269 //---------------------------------------------------------------------
5270 
5271 #define BM_XOR_OP(x) \
5272  { \
5273  blk = blk_blk[j+x]; arg_blk = blk_blk_arg[j+x]; \
5274  combine_operation_block_xor(i, j+x, blk, arg_blk); \
5275  }
5276 
5277 template<class Alloc>
5279 {
5280  if (!bv.blockman_.is_init())
5281  return;
5282  if (!blockman_.is_init())
5283  {
5284  *this = bv;
5285  return;
5286  }
5287 
5288  unsigned top_blocks = blockman_.top_block_size();
5289  if (size_ < bv.size_) // this vect shorter than the arg.
5290  {
5291  size_ = bv.size_;
5292  }
5293  unsigned arg_top_blocks = bv.blockman_.top_block_size();
5294  top_blocks = blockman_.reserve_top_blocks(arg_top_blocks);
5295 
5296  bm::word_t*** blk_root = blockman_.top_blocks_root();
5297  bm::word_t*** blk_root_arg = bv.blockman_.top_blocks_root();
5298 
5299  for (unsigned i = 0; i < top_blocks; ++i)
5300  {
5301  bm::word_t** blk_blk_arg = (i < arg_top_blocks) ? blk_root_arg[i] : 0;
5302  if (!blk_blk_arg)
5303  continue;
5304  bm::word_t** blk_blk = blk_root[i];
5305  if (blk_blk == blk_blk_arg) // nothing to do (any XOR 0 == 0)
5306  {
5307  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5308  blk_root[i] = 0;
5309  continue;
5310  }
5311  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5312  {
5313  if (!blk_blk_arg)
5314  continue;
5315  blk_blk = blockman_.check_alloc_top_subblock(i);
5316  }
5317  if ((bm::word_t*)blk_blk_arg == FULL_BLOCK_FAKE_ADDR)
5318  {
5319  if (!blk_blk)
5320  {
5321  blk_root[i] = (bm::word_t**) FULL_BLOCK_FAKE_ADDR;
5322  continue;
5323  }
5324  blk_blk_arg = FULL_SUB_BLOCK_REAL_ADDR;
5325  }
5326 
5327  if (!blk_blk)
5328  blk_blk = blockman_.alloc_top_subblock(i);
5329 
5330  unsigned j = 0;
5331  bm::word_t* blk;
5332  const bm::word_t* arg_blk;
5333  do
5334  {
5335  #if defined(BM64_AVX2) || defined(BM64_AVX512)
5336  if (!avx2_test_all_zero_wave2(blk_blk + j, blk_blk_arg + j))
5337  {
5338  BM_XOR_OP(0)
5339  BM_XOR_OP(1)
5340  BM_XOR_OP(2)
5341  BM_XOR_OP(3)
5342  }
5343  j += 4;
5344  #elif defined(BM64_SSE4)
5345  if (!sse42_test_all_zero_wave2(blk_blk + j, blk_blk_arg + j))
5346  {
5347  BM_XOR_OP(0)
5348  BM_XOR_OP(1)
5349  }
5350  j += 2;
5351  #else
5352  BM_XOR_OP(0)
5353  ++j;
5354  #endif
5355  } while (j < bm::set_sub_array_size);
5356  } // for i
5357 }
5358 
5359 #undef BM_XOR_OP
5360 
5361 
5362 //---------------------------------------------------------------------
5363 
5364 #define BM_AND_OP(x) if (0 != (blk = blk_blk[j+x])) \
5365  { \
5366  if (0 != (arg_blk = blk_blk_arg[j+x])) \
5367  { \
5368  combine_operation_block_and(i, j+x, blk, arg_blk); \
5369  if (opt_mode == opt_compress) \
5370  blockman_.optimize_bit_block(i, j+x); \
5371  } \
5372  else \
5373  blockman_.zero_block(i, j+x); \
5374  }
5375 
5376 template<class Alloc>
5378  typename bm::bvector<Alloc>::optmode opt_mode)
5379 {
5380  if (!blockman_.is_init())
5381  return; // nothing to do, already empty
5382  if (!bv.blockman_.is_init())
5383  {
5384  clear(true);
5385  return;
5386  }
5387 
5388  unsigned top_blocks = blockman_.top_block_size();
5389  if (size_ < bv.size_) // this vect shorter than the arg.
5390  size_ = bv.size_;
5391 
5392  unsigned arg_top_blocks = bv.blockman_.top_block_size();
5393  top_blocks = blockman_.reserve_top_blocks(arg_top_blocks);
5394 
5395 
5396  bm::word_t*** blk_root = blockman_.top_blocks_root();
5397  bm::word_t*** blk_root_arg = bv.blockman_.top_blocks_root();
5398 
5399  for (unsigned i = 0; i < top_blocks; ++i)
5400  {
5401  bm::word_t** blk_blk = blk_root[i];
5402  if (!blk_blk) // nothing to do (0 AND 1 == 0)
5403  continue;
5404  bm::word_t** blk_blk_arg = (i < arg_top_blocks) ? blk_root_arg[i] : 0;
5405  if (!blk_blk_arg) // free a whole group of blocks
5406  {
5407  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5408  {
5409  blk_root[i] = 0;
5410  }
5411  else
5412  {
5413  for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
5414  blockman_.zero_block(i, j);
5415  blockman_.deallocate_top_subblock(i);
5416  }
5417  continue;
5418  }
5419  if ((bm::word_t*)blk_blk_arg == FULL_BLOCK_FAKE_ADDR)
5420  continue; // any & 1 == any
5421 
5422  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5423  blk_blk = blockman_.check_alloc_top_subblock(i);
5424 
5425  unsigned j = 0;
5426  bm::word_t* blk;
5427  const bm::word_t* arg_blk;
5428  do
5429  {
5430  #if defined(BM64_AVX2) || defined(BM64_AVX512)
5431  if (!avx2_test_all_zero_wave(blk_blk + j))
5432  {
5433  BM_AND_OP(0)
5434  BM_AND_OP(1)
5435  BM_AND_OP(2)
5436  BM_AND_OP(3)
5437  }
5438  j += 4;
5439  #elif defined(BM64_SSE4)
5440  if (!sse42_test_all_zero_wave(blk_blk + j))
5441  {
5442  BM_AND_OP(0)
5443  BM_AND_OP(1)
5444  }
5445  j += 2;
5446  #else
5447  BM_AND_OP(0)
5448  ++j;
5449  #endif
5450  } while (j < bm::set_sub_array_size);
5451  } // for i
5452 }
5453 
5454 #undef BM_AND_OP
5455 
5456 
5457 //---------------------------------------------------------------------
5458 
5459 #define BM_SUB_OP(x) \
5460  if ((0 != (blk = blk_blk[j+x])) && (0 != (arg_blk = blk_blk_arg[j+x]))) \
5461  combine_operation_block_sub(i, j+x, blk, arg_blk);
5462 
5463 
5464 template<class Alloc>
5466 {
5467  if (!blockman_.is_init() || !bv.blockman_.is_init())
5468  return;
5469 
5470  unsigned top_blocks = blockman_.top_block_size();
5471  if (size_ < bv.size_) // this vect shorter than the arg.
5472  size_ = bv.size_;
5473 
5474  unsigned arg_top_blocks = bv.blockman_.top_block_size();
5475  top_blocks = blockman_.reserve_top_blocks(arg_top_blocks);
5476 
5477  bm::word_t*** blk_root = blockman_.top_blocks_root();
5478  bm::word_t*** blk_root_arg = bv.blockman_.top_blocks_root();
5479 
5480  for (unsigned i = 0; i < top_blocks; ++i)
5481  {
5482  bm::word_t** blk_blk = blk_root[i];
5483  bm::word_t** blk_blk_arg = (i < arg_top_blocks) ? blk_root_arg[i] : 0;
5484  if (!blk_blk || !blk_blk_arg) // nothing to do (0 AND NOT 1 == 0)
5485  continue;
5486 
5487  if ((bm::word_t*)blk_blk_arg == FULL_BLOCK_FAKE_ADDR) // zero result
5488  {
5489  blockman_.deallocate_top_subblock(i);
5490  continue;
5491  }
5492  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5493  blk_blk = blockman_.check_alloc_top_subblock(i);
5494 
5495  bm::word_t* blk;
5496  const bm::word_t* arg_blk;
5497  unsigned j = 0;
5498  do
5499  {
5500  #if defined(BM64_AVX2) || defined(BM64_AVX512)
5501  if (!avx2_test_all_zero_wave(blk_blk + j))
5502  {
5503  BM_SUB_OP(0)
5504  BM_SUB_OP(1)
5505  BM_SUB_OP(2)
5506  BM_SUB_OP(3)
5507  }
5508  j += 4;
5509  #elif defined(BM64_SSE4)
5510  if (!sse42_test_all_zero_wave(blk_blk + j))
5511  {
5512  BM_SUB_OP(0)
5513  BM_SUB_OP(1)
5514  }
5515  j += 2;
5516  #else
5517  BM_SUB_OP(0)
5518  ++j;
5519  #endif
5520  } while (j < bm::set_sub_array_size);
5521  } // for i
5522 }
5523 
5524 #undef BM_SUB_OP
5525 
5526 //---------------------------------------------------------------------
5527 
5528 template<class Alloc>
5530  const bm::bvector<Alloc>& bv,
5531  bm::operation opcode)
5532 {
5533  if (!blockman_.is_init())
5534  {
5535  if (opcode == BM_AND || opcode == BM_SUB)
5536  return;
5537  blockman_.init_tree();
5538  }
5539 
5540  unsigned top_blocks = blockman_.top_block_size();
5541  unsigned arg_top_blocks = bv.blockman_.top_block_size();
5542 
5543  if (arg_top_blocks > top_blocks)
5544  top_blocks = blockman_.reserve_top_blocks(arg_top_blocks);
5545 
5546  if (size_ < bv.size_) // this vect shorter than the arg.
5547  {
5548  size_ = bv.size_;
5549  // stretch our capacity
5550  blockman_.reserve_top_blocks(arg_top_blocks);
5551  top_blocks = blockman_.top_block_size();
5552  }
5553  else
5554  if (size_ > bv.size_) // this vector larger
5555  {
5556  if (opcode == BM_AND) // clear the tail with zeros
5557  {
5558  set_range(bv.size_, size_ - 1, false);
5559  if (arg_top_blocks < top_blocks)
5560  {
5561  // not to scan blocks we already swiped
5562  top_blocks = arg_top_blocks;
5563  }
5564  }
5565  }
5566 
5567  bm::word_t*** blk_root = blockman_.top_blocks_root();
5568  unsigned block_idx = 0;
5569  unsigned i, j;
5570 
5571  // calculate effective top size to avoid overscan
5572  top_blocks = blockman_.top_block_size();
5573  if (top_blocks < bv.blockman_.top_block_size())
5574  {
5575  if (opcode != BM_AND)
5576  {
5577  top_blocks = bv.blockman_.top_block_size();
5578  }
5579  }
5580 
5581  for (i = 0; i < top_blocks; ++i)
5582  {
5583  bm::word_t** blk_blk = blk_root[i];
5584  if (blk_blk == 0) // not allocated
5585  {
5586  if (opcode == BM_AND) // 0 AND anything == 0
5587  {
5588  block_idx += bm::set_sub_array_size;
5589  continue;
5590  }
5591  const bm::word_t* const* bvbb = bv.blockman_.get_topblock(i);
5592  if (bvbb == 0) // skip it because 0 OP 0 == 0
5593  {
5594  block_idx += bm::set_sub_array_size;
5595  continue;
5596  }
5597  // 0 - self, non-zero argument
5599  for (j = 0; j < bm::set_sub_array_size; ++j)
5600  {
5601  const bm::word_t* arg_blk = bv.blockman_.get_block(i, j);
5602  if (arg_blk )
5604  0, 0,
5605  arg_blk, BM_IS_GAP(arg_blk),
5606  opcode);
5607  } // for j
5608  continue;
5609  }
5610 
5611  if (opcode == BM_AND)
5612  {
5614  for (j = 0; j < bm::set_sub_array_size; ++j)
5615  {
5616  bm::word_t* blk = blk_blk[j];
5617  if (blk)
5618  {
5619  const bm::word_t* arg_blk = bv.blockman_.get_block(i, j);
5620  if (arg_blk)
5622  BM_IS_GAP(blk), blk,
5623  arg_blk, BM_IS_GAP(arg_blk),
5624  opcode);
5625  else
5626  blockman_.zero_block(i, j);
5627  }
5628 
5629  } // for j
5630  }
5631  else // OR, SUB, XOR
5632  {
5634  for (j = 0; j < bm::set_sub_array_size; ++j)
5635  {
5636  bm::word_t* blk = blk_blk[j];
5637  const bm::word_t* arg_blk = bv.blockman_.get_block(i, j);
5638  if (arg_blk || blk)
5639  combine_operation_with_block(r + j, BM_IS_GAP(blk), blk,
5640  arg_blk, BM_IS_GAP(arg_blk),
5641  opcode);
5642  } // for j
5643  }
5644  } // for i
5645 
5646 }
5647 
5648 //---------------------------------------------------------------------
5649 
5650 template<class Alloc>
5652  unsigned j,
5653  const bm::word_t* arg_blk1,
5654  const bm::word_t* arg_blk2)
5655 {
5656  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
5657  if (!arg_blk1)
5658  {
5659  blockman_.clone_assign_block(i, j, arg_blk2);
5660  return 0;
5661  }
5662  if (!arg_blk2)
5663  {
5664  blockman_.clone_assign_block(i, j, arg_blk1);
5665  return 0;
5666  }
5667  if ((arg_blk1==FULL_BLOCK_FAKE_ADDR) || (arg_blk2==FULL_BLOCK_FAKE_ADDR))
5668  {
5669  blockman_.set_block_ptr(i, j, FULL_BLOCK_FAKE_ADDR);
5670  return 0;
5671  }
5672 
5673  bool is_gap1 = BM_IS_GAP(arg_blk1);
5674  bool is_gap2 = BM_IS_GAP(arg_blk2);
5675 
5676  if (is_gap1 | is_gap2) // at least one GAP
5677  {
5678  if (is_gap1 & is_gap2) // both GAPS
5679  {
5680  unsigned res_len;
5681  bm::gap_operation_or(BMGAP_PTR(arg_blk1),
5682  BMGAP_PTR(arg_blk2),
5683  tmp_buf, res_len);
5684  blockman_.clone_gap_block(i, j, tmp_buf, res_len);
5685  return 0;
5686  }
5687  // one GAP one bit block
5688  const bm::word_t* arg_block;
5689  const bm::gap_word_t* arg_gap;
5690  if (is_gap1) // arg1 is GAP -> clone arg2(bit)
5691  {
5692  arg_block = arg_blk2;
5693  arg_gap = BMGAP_PTR(arg_blk1);
5694  }
5695  else // arg2 is GAP
5696  {
5697  arg_block = arg_blk1;
5698  arg_gap = BMGAP_PTR(arg_blk2);
5699  }
5700  bm::word_t* block = blockman_.clone_assign_block(i, j, arg_block);
5701  bm::gap_add_to_bitset(block, arg_gap);
5702 
5703  return true; // optimization may be needed
5704  }
5705 
5706  // 2 bit-blocks
5707  //
5708  bm::word_t* block = blockman_.borrow_tempblock();
5709  blockman_.set_block_ptr(i, j, block);
5710 
5711  bool all_one = bm::bit_block_or_2way(block, arg_blk1, arg_blk2);
5712  if (all_one)
5713  {
5714  blockman_.set_block_ptr(i, j, FULL_BLOCK_FAKE_ADDR);
5715  blockman_.return_tempblock(block);
5716  return 0;
5717  }
5718  return true;
5719 }
5720 
5721 //---------------------------------------------------------------------
5722 
5723 template<class Alloc>
5724 bool bvector<Alloc>::combine_operation_block_xor(unsigned i,
5725  unsigned j,
5726  const bm::word_t* arg_blk1,
5727  const bm::word_t* arg_blk2)
5728 {
5729  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
5730 
5731  if (!arg_blk1)
5732  {
5733  blockman_.clone_assign_block(i, j, arg_blk2);
5734  return 0;
5735  }
5736  if (!arg_blk2)
5737  {
5738  blockman_.clone_assign_block(i, j, arg_blk1);
5739  return 0;
5740  }
5741  if (arg_blk1==FULL_BLOCK_FAKE_ADDR)
5742  {
5743  BM_ASSERT(!IS_FULL_BLOCK(arg_blk2));
5744  blockman_.clone_assign_block(i, j, arg_blk2, true); // invert
5745  return 0;
5746  }
5747  if (arg_blk2==FULL_BLOCK_FAKE_ADDR)
5748  {
5749  BM_ASSERT(!IS_FULL_BLOCK(arg_blk1));
5750  blockman_.clone_assign_block(i, j, arg_blk1, true); // invert
5751  return 0;
5752  }
5753 
5754  bool is_gap1 = BM_IS_GAP(arg_blk1);
5755  bool is_gap2 = BM_IS_GAP(arg_blk2);
5756 
5757  if (is_gap1 | is_gap2) // at least one GAP
5758  {
5759  if (is_gap1 & is_gap2) // both GAPS
5760  {
5761  unsigned res_len;
5762  bm::gap_operation_xor(BMGAP_PTR(arg_blk1),
5763  BMGAP_PTR(arg_blk2),
5764  tmp_buf, res_len);
5765  blockman_.clone_gap_block(i, j, tmp_buf, res_len);
5766  return 0;
5767  }
5768  // one GAP one bit block
5769  const bm::word_t* arg_block;
5770  const bm::gap_word_t* arg_gap;
5771  if (is_gap1) // arg1 is GAP -> clone arg2(bit)
5772  {
5773  arg_block = arg_blk2;
5774  arg_gap = BMGAP_PTR(arg_blk1);
5775  }
5776  else // arg2 is GAP
5777  {
5778  arg_block = arg_blk1;
5779  arg_gap = BMGAP_PTR(arg_blk2);
5780  }
5781  bm::word_t* block = blockman_.clone_assign_block(i, j, arg_block);
5782  bm::gap_xor_to_bitset(block, arg_gap);
5783 
5784  return true; // optimization may be needed
5785  }
5786 
5787  // 2 bit-blocks
5788  //
5789  bm::word_t* block = blockman_.borrow_tempblock();
5790  blockman_.set_block_ptr(i, j, block);
5791 
5792  bm::id64_t or_mask = bm::bit_block_xor_2way(block, arg_blk1, arg_blk2);
5793  if (!or_mask)
5794  {
5795  blockman_.set_block_ptr(i, j, 0);
5796  blockman_.return_tempblock(block);
5797  return 0;
5798  }
5799 
5800  return true;
5801 }
5802 
5803 //---------------------------------------------------------------------
5804 
5805 template<class Alloc>
5806 bool bvector<Alloc>::combine_operation_block_and(unsigned i,
5807  unsigned j,
5808  const bm::word_t* arg_blk1,
5809  const bm::word_t* arg_blk2)
5810 {
5811  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
5812 
5813  if (!arg_blk1 || !arg_blk2)
5814  {
5815  return 0;
5816  }
5817  if ((arg_blk1==FULL_BLOCK_FAKE_ADDR) && (arg_blk2==FULL_BLOCK_FAKE_ADDR))
5818  {
5819  blockman_.set_block_ptr(i, j, FULL_BLOCK_FAKE_ADDR);
5820  return 0;
5821  }
5822  if (arg_blk1==FULL_BLOCK_FAKE_ADDR)
5823  {
5824  blockman_.clone_assign_block(i, j, arg_blk2);
5825  return 0;
5826  }
5827  if (arg_blk2==FULL_BLOCK_FAKE_ADDR)
5828  {
5829  blockman_.clone_assign_block(i, j, arg_blk1);
5830  return 0;
5831  }
5832 
5833  bool is_gap1 = BM_IS_GAP(arg_blk1);
5834  bool is_gap2 = BM_IS_GAP(arg_blk2);
5835 
5836  if (is_gap1 | is_gap2) // at least one GAP
5837  {
5838  if (is_gap1 & is_gap2) // both GAPS
5839  {
5840  unsigned res_len;
5841  bm::gap_operation_and(BMGAP_PTR(arg_blk1),
5842  BMGAP_PTR(arg_blk2),
5843  tmp_buf, res_len);
5844  blockman_.clone_gap_block(i, j, tmp_buf, res_len);
5845  return 0;
5846  }
5847  // one GAP one bit block
5848  const bm::word_t* arg_block;
5849  const bm::gap_word_t* arg_gap;
5850  if (is_gap1) // arg1 is GAP -> clone arg2(bit)
5851  {
5852  arg_block = arg_blk2;
5853  arg_gap = BMGAP_PTR(arg_blk1);
5854  }
5855  else // arg2 is GAP
5856  {
5857  arg_block = arg_blk1;
5858  arg_gap = BMGAP_PTR(arg_blk2);
5859  }
5860  bm::word_t* block = blockman_.clone_assign_block(i, j, arg_block);
5861  bm::gap_and_to_bitset(block, arg_gap);
5862 
5863  return true; // optimization may be needed
5864  }
5865 
5866  // 2 bit-blocks
5867  //
5868  bm::word_t* block = blockman_.borrow_tempblock();
5869  blockman_.set_block_ptr(i, j, block);
5870 
5871  bm::id64_t digest = bm::bit_block_and_2way(block, arg_blk1, arg_blk2, ~0ull);
5872  if (!digest)
5873  {
5874  blockman_.set_block_ptr(i, j, 0);
5875  blockman_.return_tempblock(block);
5876  return 0;
5877  }
5878 
5879  return true;
5880 }
5881 
5882 //---------------------------------------------------------------------
5883 
5884 template<class Alloc>
5885 bool bvector<Alloc>::combine_operation_block_sub(unsigned i,
5886  unsigned j,
5887  const bm::word_t* arg_blk1,
5888  const bm::word_t* arg_blk2)
5889 {
5890  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
5891 
5892  if (!arg_blk1)
5893  return 0;
5894  if (!arg_blk2)
5895  {
5896  blockman_.clone_assign_block(i, j, arg_blk1);
5897  return 0;
5898  }
5899  if (arg_blk2==FULL_BLOCK_FAKE_ADDR)
5900  return 0;
5901  if (arg_blk1==FULL_BLOCK_FAKE_ADDR)
5902  arg_blk1 = FULL_BLOCK_REAL_ADDR;
5903 
5904  bool is_gap1 = BM_IS_GAP(arg_blk1);
5905  bool is_gap2 = BM_IS_GAP(arg_blk2);
5906 
5907  if (is_gap1 | is_gap2) // at least one GAP
5908  {
5909  if (is_gap1 & is_gap2) // both GAPS
5910  {
5911  unsigned res_len;
5912  bm::gap_operation_sub(BMGAP_PTR(arg_blk1),
5913  BMGAP_PTR(arg_blk2),
5914  tmp_buf, res_len);
5915  blockman_.clone_gap_block(i, j, tmp_buf, res_len);
5916  return 0;
5917  }
5918 
5919  if (is_gap1)
5920  {
5921  bm::word_t* block = blockman_.borrow_tempblock();
5922  blockman_.set_block_ptr(i, j, block);
5923  bm::gap_convert_to_bitset(block, BMGAP_PTR(arg_blk1));
5924  bm::id64_t acc = bm::bit_block_sub(block, arg_blk2);
5925  if (!acc)
5926  {
5927  blockman_.set_block_ptr(i, j, 0);
5928  blockman_.return_tempblock(block);
5929  return 0;
5930  }
5931  return true;
5932  }
5933  BM_ASSERT(is_gap2);
5934  bm::word_t* block = blockman_.clone_assign_block(i, j, arg_blk1);
5935  bm::gap_sub_to_bitset(block, BMGAP_PTR(arg_blk2));
5936 
5937  return true; // optimization may be needed
5938  }
5939 
5940  // 2 bit-blocks:
5941  //
5942  bm::word_t* block = blockman_.borrow_tempblock();
5943  blockman_.set_block_ptr(i, j, block);
5944 
5945  bm::id64_t digest = bm::bit_block_sub_2way(block, arg_blk1, arg_blk2, ~0ull);
5946  if (!digest)
5947  {
5948  blockman_.set_block_ptr(i, j, 0);
5949  blockman_.return_tempblock(block);
5950  return 0;
5951  }
5952  return true;
5953 }
5954 
5955 
5956 //---------------------------------------------------------------------
5957 
5958 template<class Alloc>
5959 void bvector<Alloc>::combine_operation_block_or(
5960  unsigned i, unsigned j,
5961  bm::word_t* blk, const bm::word_t* arg_blk)
5962 {
5963  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
5964  if (IS_FULL_BLOCK(blk) || !arg_blk) // all bits are set
5965  return; // nothing to do
5966 
5967  if (IS_FULL_BLOCK(arg_blk))
5968  {
5969  if (blk)
5970  blockman_.zero_block(i, j); // free target block and assign FULL
5971  blockman_.set_block_ptr(i, j, FULL_BLOCK_FAKE_ADDR);
5972  return;
5973  }
5974 
5975  if (BM_IS_GAP(blk)) // our block GAP-type
5976  {
5977  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
5978  if (BM_IS_GAP(arg_blk)) // both blocks GAP-type
5979  {
5980  const bm::gap_word_t* res; unsigned res_len;
5981  res = bm::gap_operation_or(gap_blk, BMGAP_PTR(arg_blk),
5982  tmp_buf, res_len);
5983  BM_ASSERT(res == tmp_buf);
5984  blockman_.assign_gap_check(i, j, res, ++res_len, blk, tmp_buf);
5985  return;
5986  }
5987  // GAP or BIT
5988  //
5989  bm::word_t* new_blk = blockman_.get_allocator().alloc_bit_block();
5990  bm::bit_block_copy(new_blk, arg_blk);
5991  bm::gap_add_to_bitset(new_blk, gap_blk);
5992 
5993  blockman_.get_allocator().free_gap_block(gap_blk, blockman_.glen());
5994  blockman_.set_block_ptr(i, j, new_blk);
5995 
5996  return;
5997  }
5998  else // our block is BITSET-type (but NOT FULL_BLOCK we checked it)
5999  {
6000  if (BM_IS_GAP(arg_blk)) // argument block is GAP-type
6001  {
6002  const bm::gap_word_t* arg_gap = BMGAP_PTR(arg_blk);
6003  if (!blk)
6004  {
6005  bool gap = true;
6006  blk = blockman_.clone_gap_block(arg_gap, gap);
6007  blockman_.set_block(i, j, blk, gap);
6008  return;
6009  }
6010 
6011  // BIT & GAP
6012  bm::gap_add_to_bitset(blk, arg_gap);
6013  return;
6014  } // if arg_gap
6015  }
6016 
6017  if (!blk)
6018  {
6019  blk = blockman_.alloc_.alloc_bit_block();
6020  bm::bit_block_copy(blk, arg_blk);
6021  blockman_.set_block_ptr(i, j, blk);
6022  return;
6023  }
6024 
6025  bool all_one = bm::bit_block_or(blk, arg_blk);
6026  if (all_one)
6027  {
6029  blockman_.get_allocator().free_bit_block(blk);
6030  blockman_.set_block_ptr(i, j, FULL_BLOCK_FAKE_ADDR);
6031  }
6032 
6033 }
6034 
6035 //---------------------------------------------------------------------
6036 
6037 template<class Alloc>
6038 void bvector<Alloc>::combine_operation_block_xor(
6039  unsigned i, unsigned j,
6040  bm::word_t* blk, const bm::word_t* arg_blk)
6041 {
6042  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
6043  if (!arg_blk) // all bits are set
6044  return; // nothing to do
6045 
6046  if (IS_FULL_BLOCK(arg_blk))
6047  {
6048  if (blk)
6049  {
6050  if (BM_IS_GAP(blk))
6051  bm::gap_invert(BMGAP_PTR(blk));
6052  else
6053  {
6054  if (IS_FULL_BLOCK(blk)) // 1 xor 1 = 0
6055  blockman_.set_block_ptr(i, j, 0);
6056  else
6057  bm::bit_invert((wordop_t*) blk);
6058  }
6059  }
6060  else // blk == 0
6061  {
6062  blockman_.set_block_ptr(i, j, FULL_BLOCK_FAKE_ADDR);
6063  }
6064  return;
6065  }
6066  if (IS_FULL_BLOCK(blk))
6067  {
6068  if (!arg_blk)
6069  return;
6070  // deoptimize block
6071  blk = blockman_.get_allocator().alloc_bit_block();
6072  bm::bit_block_set(blk, ~0u);
6073  blockman_.set_block_ptr(i, j, blk);
6074  }
6075 
6076 
6077  if (BM_IS_GAP(blk)) // our block GAP-type
6078  {
6079  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
6080  if (BM_IS_GAP(arg_blk)) // both blocks GAP-type
6081  {
6082  const bm::gap_word_t* res;
6083  unsigned res_len;
6084  res = bm::gap_operation_xor(gap_blk,
6085  BMGAP_PTR(arg_blk),
6086  tmp_buf,
6087  res_len);
6088  BM_ASSERT(res == tmp_buf);
6089  blockman_.assign_gap_check(i, j, res, ++res_len, blk, tmp_buf);
6090  return;
6091  }
6092  // GAP or BIT
6093  //
6094  bm::word_t* new_blk = blockman_.get_allocator().alloc_bit_block();
6095  bm::bit_block_copy(new_blk, arg_blk);
6096  bm::gap_xor_to_bitset(new_blk, gap_blk);
6097 
6098  blockman_.get_allocator().free_gap_block(gap_blk, blockman_.glen());
6099  blockman_.set_block_ptr(i, j, new_blk);
6100 
6101  return;
6102  }
6103  else // our block is BITSET-type (but NOT FULL_BLOCK we checked it)
6104  {
6105  if (BM_IS_GAP(arg_blk)) // argument block is GAP-type
6106  {
6107  const bm::gap_word_t* arg_gap = BMGAP_PTR(arg_blk);
6108  if (!blk)
6109  {
6110  bool gap = true;
6111  blk = blockman_.clone_gap_block(arg_gap, gap);
6112  blockman_.set_block(i, j, blk, gap);
6113  return;
6114  }
6115  // BIT & GAP
6116  bm::gap_xor_to_bitset(blk, arg_gap);
6117  return;
6118  } // if arg_gap
6119  }
6120 
6121  if (!blk)
6122  {
6123  blk = blockman_.alloc_.alloc_bit_block();
6124  bm::bit_block_copy(blk, arg_blk);
6125  blockman_.set_block_ptr(i, j, blk);
6126  return;
6127  }
6128 
6129  auto any_bits = bm::bit_block_xor(blk, arg_blk);
6130  if (!any_bits)
6131  {
6132  blockman_.get_allocator().free_bit_block(blk);
6133  blockman_.set_block_ptr(i, j, 0);
6134  }
6135 }
6136 
6137 
6138 //---------------------------------------------------------------------
6139 
6140 
6141 template<class Alloc>
6142 void bvector<Alloc>::combine_operation_block_and(
6143  unsigned i, unsigned j, bm::word_t* blk, const bm::word_t* arg_blk)
6144 {
6145  BM_ASSERT(arg_blk && blk);
6146 
6147  if (IS_FULL_BLOCK(arg_blk))
6148  return; // nothing to do
6149 
6150  gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
6151 
6152  if (BM_IS_GAP(blk)) // our block GAP-type
6153  {
6154  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
6155  if (BM_IS_GAP(arg_blk)) // both blocks GAP-type
6156  {
6157  const bm::gap_word_t* res;
6158  unsigned res_len;
6159  res = bm::gap_operation_and(gap_blk,
6160  BMGAP_PTR(arg_blk),
6161  tmp_buf,
6162  res_len);
6163  BM_ASSERT(res == tmp_buf);
6164  blockman_.assign_gap_check(i, j, res, ++res_len, blk, tmp_buf);
6165  return;
6166  }
6167  // GAP & BIT
6168  //
6169  bm::word_t* new_blk = blockman_.get_allocator().alloc_bit_block();
6170  bm::bit_block_copy(new_blk, arg_blk);
6171  bm::id64_t digest = bm::calc_block_digest0(new_blk);
6172 
6173  bm::gap_and_to_bitset(new_blk, gap_blk, digest);
6174 
6175  digest = bm::update_block_digest0(new_blk, digest);
6176  if (!digest)
6177  {
6178  BM_ASSERT(bm::bit_is_all_zero(new_blk));
6179  blockman_.get_allocator().free_bit_block(new_blk);
6180  new_blk = 0;
6181  }
6182  else
6183  {
6184  BM_ASSERT(!bm::bit_is_all_zero(new_blk));
6185  }
6186  blockman_.get_allocator().free_gap_block(gap_blk, blockman_.glen());
6187  blockman_.set_block_ptr(i, j, new_blk);
6188 
6189  return;
6190  }
6191  else // our block is BITSET-type or FULL_BLOCK
6192  {
6193  if (BM_IS_GAP(arg_blk)) // argument block is GAP-type
6194  {
6195  const bm::gap_word_t* arg_gap = BMGAP_PTR(arg_blk);
6196  if (bm::gap_is_all_zero(arg_gap))
6197  {
6198  blockman_.zero_block(i, j);
6199  return;
6200  }
6201  // FULL & GAP is common when AND with set_range() mask
6202  //
6203  if (IS_FULL_BLOCK(blk)) // FULL & gap = gap
6204  {
6205  bool is_new_gap;
6206  bm::word_t* new_blk = blockman_.clone_gap_block(arg_gap, is_new_gap);
6207  if (is_new_gap)
6208  BMSET_PTRGAP(new_blk);
6209 
6210  blockman_.set_block_ptr(i, j, new_blk);
6211 
6212  return;
6213  }
6214  // BIT & GAP
6215  bm::gap_and_to_bitset(blk, arg_gap);
6216  bool empty = bm::bit_is_all_zero(blk);
6217  if (empty) // operation converged bit-block to empty
6218  blockman_.zero_block(i, j);
6219 
6220  return;
6221  } // if arg_gap
6222  }
6223 
6224  // FULL & bit is common when AND with set_range() mask
6225  //
6226  if (IS_FULL_BLOCK(blk)) // FULL & bit = bit
6227  {
6228  bm::word_t* new_blk = blockman_.get_allocator().alloc_bit_block();
6229  bm::bit_block_copy(new_blk, arg_blk);
6230  blockman_.set_block_ptr(i, j, new_blk);
6231 
6232  return;
6233  }
6234  auto any_bits = bm::bit_block_and(blk, arg_blk);
6235  if (!any_bits)
6236  {
6237  blockman_.get_allocator().free_bit_block(blk);
6238  blockman_.set_block_ptr(i, j, 0);
6239  }
6240 }
6241 
6242 //---------------------------------------------------------------------
6243 
6244 template<class Alloc>
6245 void bvector<Alloc>::combine_operation_block_sub(
6246  unsigned i, unsigned j, bm::word_t* blk, const bm::word_t* arg_blk)
6247 {
6248  BM_ASSERT(arg_blk && blk);
6249 
6250  if (IS_FULL_BLOCK(arg_blk))
6251  {
6252  blockman_.zero_block(i, j);
6253  return;
6254  }
6255 
6256  gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
6257 
6258  if (BM_IS_GAP(blk)) // our block GAP-type
6259  {
6260  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
6261  if (BM_IS_GAP(arg_blk)) // both blocks GAP-type
6262  {
6263  const bm::gap_word_t* res;
6264  unsigned res_len;
6265  res = bm::gap_operation_sub(gap_blk,
6266  BMGAP_PTR(arg_blk),
6267  tmp_buf,
6268  res_len);
6269 
6270  BM_ASSERT(res == tmp_buf);
6271  BM_ASSERT(!(res == tmp_buf && res_len == 0));
6272 
6273  blockman_.assign_gap_check(i, j, res, ++res_len, blk, tmp_buf);
6274  return;
6275  }
6276  // else: argument is BITSET-type (own block is GAP)
6277  blk = blockman_.convert_gap2bitset(i, j, gap_blk);
6278  // fall through to bit-block to bit-block operation
6279  }
6280  else // our block is BITSET-type or FULL_BLOCK
6281  {
6282  if (BM_IS_GAP(arg_blk)) // argument block is GAP-type
6283  {
6284  if (!IS_FULL_BLOCK(blk)) // gap combined to bitset
6285  {
6286  bm::gap_sub_to_bitset(blk, BMGAP_PTR(arg_blk));
6287  bool empty = bm::bit_is_all_zero(blk);
6288  if (empty) // operation converged bit-block to empty
6289  blockman_.zero_block(i, j);
6290  return;
6291  }
6292  // the worst case: convert arg block to bitset
6293  arg_blk =
6294  gap_convert_to_bitset_smart(blockman_.check_allocate_tempblock(),
6295  BMGAP_PTR(arg_blk),
6297  }
6298  }
6299 
6300  // Now here we combine two plain bitblocks using supplied bit function.
6301  bm::word_t* dst = blk;
6302 
6303  bm::word_t* ret;
6304  if (!dst || !arg_blk)
6305  return;
6306 
6307  ret = bm::bit_operation_sub(dst, arg_blk);
6308  if (ret && ret == arg_blk)
6309  {
6310  ret = blockman_.get_allocator().alloc_bit_block();
6311  bm::bit_andnot_arr_ffmask(ret, arg_blk);
6312  }
6313 
6314  if (ret != dst) // block mutation
6315  {
6316  blockman_.set_block_ptr(i, j, ret);
6317  if (IS_VALID_ADDR(dst))
6318  blockman_.get_allocator().free_bit_block(dst);
6319  }
6320 }
6321 
6322 //---------------------------------------------------------------------
6323 
6324 template<class Alloc>
6325 void
6327  bool gap,
6328  bm::word_t* blk,
6329  const bm::word_t* arg_blk,
6330  bool arg_gap,
6331  bm::operation opcode)
6332 {
6333  gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
6334  const bm::gap_word_t* res;
6335  unsigned res_len;
6336 
6337  if (opcode == BM_OR || opcode == BM_XOR)
6338  {
6339  if (!blk && arg_gap)
6340  {
6341  blk = blockman_.clone_gap_block(BMGAP_PTR(arg_blk), gap);
6342  blockman_.set_block(nb, blk, gap);
6343  return;
6344  }
6345  }
6346 
6347  if (gap) // our block GAP-type
6348  {
6349  if (arg_gap) // both blocks GAP-type
6350  {
6351  {
6352  gap_operation_func_type gfunc =
6354  BM_ASSERT(gfunc);
6355  res = (*gfunc)(BMGAP_PTR(blk),
6356  BMGAP_PTR(arg_blk),
6357  tmp_buf,
6358  res_len);
6359  }
6360  BM_ASSERT(res == tmp_buf);
6361  BM_ASSERT(!(res == tmp_buf && res_len == 0));
6362 
6363  // if as a result of the operation gap block turned to zero
6364  // we can now replace it with NULL
6365  if (bm::gap_is_all_zero(res))
6366  blockman_.zero_block(nb);
6367  else
6368  blockman_.assign_gap(nb, res, ++res_len, blk, tmp_buf);
6369  return;
6370  }
6371  else // argument is BITSET-type (own block is GAP)
6372  {
6373  // since we can not combine blocks of mixed type
6374  // we need to convert our block to bitset
6375 
6376  if (arg_blk == 0) // Combining against an empty block
6377  {
6378  switch (opcode)
6379  {
6380  case BM_AND: // ("Value" AND 0) == 0
6381  blockman_.zero_block(nb);
6382  return;
6383  case BM_OR: case BM_SUB: case BM_XOR:
6384  return; // nothing to do
6385  default:
6386  return; // nothing to do
6387  }
6388  }
6389  gap_word_t* gap_blk = BMGAP_PTR(blk);
6390  blk = blockman_.convert_gap2bitset(nb, gap_blk);
6391  }
6392  }
6393  else // our block is BITSET-type
6394  {
6395  if (arg_gap) // argument block is GAP-type
6396  {
6397  if (IS_VALID_ADDR(blk))
6398  {
6399  // special case, maybe we can do the job without
6400  // converting the GAP argument to bitblock
6403  BM_ASSERT(gfunc);
6404  (*gfunc)(blk, BMGAP_PTR(arg_blk));
6405 
6406  // TODO: commented out optimization, because it can be very slow
6407  // need to take into account previous operation not to make
6408  // fruitless attempts here
6409  //blockman_.optimize_bit_block(nb);
6410  return;
6411  }
6412 
6413  // the worst case we need to convert argument block to
6414  // bitset type.
6415  gap_word_t* temp_blk = (gap_word_t*) blockman_.check_allocate_tempblock();
6416  arg_blk =
6418  BMGAP_PTR(arg_blk),
6420  }
6421  }
6422 
6423  // Now here we combine two plain bitblocks using supplied bit function.
6424  bm::word_t* dst = blk;
6425 
6426  bm::word_t* ret;
6427  if (dst == 0 && arg_blk == 0)
6428  return;
6429 
6430  switch (opcode)
6431  {
6432  case BM_AND:
6433  ret = bm::bit_operation_and(dst, arg_blk);
6434  goto copy_block;
6435  case BM_XOR:
6436  ret = bm::bit_operation_xor(dst, arg_blk);
6437  if (ret && (ret == arg_blk) && IS_FULL_BLOCK(dst))
6438  {
6439  ret = blockman_.get_allocator().alloc_bit_block();
6440 #ifdef BMVECTOPT
6441  VECT_XOR_ARR_2_MASK(ret,
6442  arg_blk,
6443  arg_blk + bm::set_block_size,
6444  ~0u);
6445 #else
6446  bm::wordop_t* dst_ptr = (wordop_t*)ret;
6447  const bm::wordop_t* wrd_ptr = (wordop_t*) arg_blk;
6448  const bm::wordop_t* wrd_end =
6449  (wordop_t*) (arg_blk + bm::set_block_size);
6450 
6451  do
6452  {
6453  dst_ptr[0] = bm::all_bits_mask ^ wrd_ptr[0];
6454  dst_ptr[1] = bm::all_bits_mask ^ wrd_ptr[1];
6455  dst_ptr[2] = bm::all_bits_mask ^ wrd_ptr[2];
6456  dst_ptr[3] = bm::all_bits_mask ^ wrd_ptr[3];
6457 
6458  dst_ptr+=4;
6459  wrd_ptr+=4;
6460 
6461  } while (wrd_ptr < wrd_end);
6462 #endif
6463  break;
6464  }
6465  goto copy_block;
6466  case BM_OR:
6467  ret = bm::bit_operation_or(dst, arg_blk);
6468  copy_block:
6469  if (ret && (ret == arg_blk) && !IS_FULL_BLOCK(ret))
6470  {
6471  ret = blockman_.get_allocator().alloc_bit_block();
6472  bm::bit_block_copy(ret, arg_blk);
6473  }
6474  break;
6475 
6476  case BM_SUB:
6477  ret = bit_operation_sub(dst, arg_blk);
6478  if (ret && ret == arg_blk)
6479  {
6480  ret = blockman_.get_allocator().alloc_bit_block();
6481  bm::bit_andnot_arr_ffmask(ret, arg_blk);
6482  }
6483  break;
6484  default:
6485  BM_ASSERT(0);
6486  ret = 0;
6487  }
6488 
6489  if (ret != dst) // block mutation
6490  {
6491  blockman_.set_block(nb, ret);
6492  if (IS_VALID_ADDR(dst))
6493  {
6494  blockman_.get_allocator().free_bit_block(dst);
6495  }
6496  }
6497 }
6498 
6499 //---------------------------------------------------------------------
6500 
6501 template<class Alloc>
6502 void bvector<Alloc>::set_range_no_check(size_type left,
6503  size_type right)
6504 {
6505  block_idx_type nblock_left = left >> bm::set_block_shift;
6506  block_idx_type nblock_right = right >> bm::set_block_shift;
6507 
6508  unsigned nbit_right = unsigned(right & bm::set_block_mask);
6509 
6510  unsigned r =
6511  (nblock_left == nblock_right) ? nbit_right :(bm::bits_in_block-1);
6512 
6513  bm::gap_word_t tmp_gap_blk[5];
6514  tmp_gap_blk[0] = 0; // just to silence GCC warning on uninit var
6515 
6516  // Set bits in the starting block
6517  //
6518  block_idx_type nb;
6519  unsigned i, j;
6520  bm::word_t* block;
6521  unsigned nbit_left = unsigned(left & bm::set_block_mask);
6522  if ((nbit_left == 0) && (r == bm::bits_in_block - 1)) // full block
6523  {
6524  nb = nblock_left;
6525  }
6526  else
6527  {
6528  gap_init_range_block<gap_word_t>(tmp_gap_blk,
6529  (gap_word_t)nbit_left,
6530  (gap_word_t)r,
6531  (gap_word_t)1);
6532  bm::get_block_coord(nblock_left, i, j);
6533  block = blockman_.get_block_ptr(i, j);
6534  combine_operation_with_block(nblock_left,
6535  BM_IS_GAP(block),
6536  block,
6537  (bm::word_t*) tmp_gap_blk,
6538  1, BM_OR);
6539 
6540  if (nblock_left == nblock_right) // in one block
6541  return;
6542  nb = nblock_left+1;
6543  }
6544 
6545  // Set all full blocks between left and right
6546  //
6547  block_idx_type nb_to = nblock_right + (nbit_right ==(bm::bits_in_block-1));
6548  BM_ASSERT(nb_to >= nblock_right);
6549  if (nb < nb_to)
6550  {
6551  BM_ASSERT(nb_to);
6552  blockman_.set_all_set(nb, nb_to-1);
6553  }
6554 
6555  if (nb_to > nblock_right)
6556  return;
6557 
6558  bm::get_block_coord(nblock_right, i, j);
6559  block = blockman_.get_block_ptr(i, j);
6560 
6561  gap_init_range_block<gap_word_t>(tmp_gap_blk,
6562  (gap_word_t)0,
6563  (gap_word_t)nbit_right,
6564  (gap_word_t)1);
6565 
6566  combine_operation_with_block(nblock_right,
6567  BM_IS_GAP(block),
6568  block,
6569  (bm::word_t*) tmp_gap_blk,
6570  1, BM_OR);
6571 }
6572 
6573 //---------------------------------------------------------------------
6574 
6575 template<class Alloc>
6576 void bvector<Alloc>::clear_range_no_check(size_type left,
6577  size_type right)
6578 {
6579  block_idx_type nb;
6580  unsigned i, j;
6581 
6582  // calculate logical number of start and destination blocks
6583  block_idx_type nblock_left = left >> bm::set_block_shift;
6584  block_idx_type nblock_right = right >> bm::set_block_shift;
6585 
6586  unsigned nbit_right = unsigned(right & bm::set_block_mask);
6587  unsigned r =
6588  (nblock_left == nblock_right) ? nbit_right : (bm::bits_in_block - 1);
6589 
6590  bm::gap_word_t tmp_gap_blk[5];
6591  tmp_gap_blk[0] = 0; // just to silence GCC warning on uninit var
6592 
6593  // Set bits in the starting block
6594  bm::word_t* block;
6595 
6596  unsigned nbit_left = unsigned(left & bm::set_block_mask);
6597  if ((nbit_left == 0) && (r == bm::bits_in_block - 1)) // full block
6598  {
6599  nb = nblock_left;
6600  }
6601  else
6602  {
6603  bm::gap_init_range_block<gap_word_t>(tmp_gap_blk,
6604  (gap_word_t)nbit_left,
6605  (gap_word_t)r,
6606  (gap_word_t)0);
6607  bm::get_block_coord(nblock_left, i, j);
6608  block = blockman_.get_block_ptr(i, j);
6609  combine_operation_with_block(nblock_left,
6610  BM_IS_GAP(block),
6611  block,
6612  (bm::word_t*) tmp_gap_blk,
6613  1,
6614  BM_AND);
6615 
6616  if (nblock_left == nblock_right) // in one block
6617  return;
6618  nb = nblock_left + 1;
6619  }
6620 
6621  // Clear all full blocks between left and right
6622 
6623  block_idx_type nb_to = nblock_right + (nbit_right == (bm::bits_in_block - 1));
6624  BM_ASSERT(nb_to >= nblock_right);
6625  if (nb < nb_to)
6626  {
6627  BM_ASSERT(nb_to);
6628  blockman_.set_all_zero(nb, nb_to - 1u);
6629  }
6630 
6631  if (nb_to > nblock_right)
6632  return;
6633 
6634  bm::get_block_coord(nblock_right, i, j);
6635  block = blockman_.get_block_ptr(i, j);
6636  gap_init_range_block<gap_word_t>(tmp_gap_blk,
6637  (gap_word_t)0,
6638  (gap_word_t)nbit_right,
6639  (gap_word_t)0);
6640 
6641  combine_operation_with_block(nblock_right,
6642  BM_IS_GAP(block),
6643  block,
6644  (bm::word_t*) tmp_gap_blk,
6645  1,
6646  BM_AND);
6647 }
6648 
6649 
6650 //---------------------------------------------------------------------
6651 
6652 template<class Alloc>
6654  size_type left,
6655  size_type right)
6656 {
6657  if (!bvect.blockman_.is_init())
6658  {
6659  clear();
6660  return;
6661  }
6662 
6663  if (blockman_.is_init())
6664  {
6665  blockman_.deinit_tree();
6666  }
6667  if (left > right)
6668  bm::xor_swap(left, right);
6669 
6670  copy_range_no_check(bvect, left, right);
6671 }
6672 
6673 //---------------------------------------------------------------------
6674 
6675 template<class Alloc>
6677 {
6678  BM_ASSERT(left <= right);
6679  BM_ASSERT_THROW(right < bm::id_max, BM_ERR_RANGE);
6680 
6681  if (left)
6682  {
6683  clear_range_no_check(0, left - 1); // TODO: optimize clear from
6684  }
6685  if (right < bm::id_max - 1)
6686  {
6687  size_type last;
6688  bool found = find_reverse(last);
6689  if (found && (last > right))
6690  clear_range_no_check(right + 1, last);
6691  }
6692  BM_ASSERT(count() == count_range(left, right));
6693 }
6694 
6695 //---------------------------------------------------------------------
6696 
6697 template<class Alloc>
6698 void bvector<Alloc>::copy_range_no_check(const bvector<Alloc>& bvect,
6699  size_type left,
6700  size_type right)
6701 {
6702  BM_ASSERT(left <= right);
6703  BM_ASSERT_THROW(right < bm::id_max, BM_ERR_RANGE);
6704 
6705  // copy all block(s) belonging to our range
6706  block_idx_type nblock_left = (left >> bm::set_block_shift);
6707  block_idx_type nblock_right = (right >> bm::set_block_shift);
6708 
6709  blockman_.copy(bvect.blockman_, nblock_left, nblock_right);
6710 
6711  if (left)
6712  {
6713  size_type from =
6714  (left < bm::gap_max_bits) ? 0 : (left - bm::gap_max_bits);
6715  clear_range_no_check(from, left-1); // TODO: optimize clear from
6716  }
6717  if (right < bm::id_max-1)
6718  {
6719  size_type last;
6720  bool found = find_reverse(last);
6721  if (found && (last > right))
6722  clear_range_no_check(right+1, last);
6723  }
6724  //keep_range_no_check(left, right); // clear the flanks
6725 }
6726 
6727 //---------------------------------------------------------------------
6728 
6729 template<class Alloc>
6731 {
6732 #ifndef BM_NO_STL
6733  throw std::bad_alloc();
6734 #else
6735  BM_THROW(BM_ERR_BADALLOC);
6736 #endif
6737 }
6738 
6739 //---------------------------------------------------------------------
6740 //
6741 //---------------------------------------------------------------------
6742 
6743 template<class Alloc>
6745 {
6746  BM_ASSERT(this->valid());
6747 
6748  block_descr_type* bdescr = &(this->bdescr_);
6749  if (this->block_type_) // GAP
6750  {
6751  BM_ASSERT(this->block_type_ == 1);
6752  ++this->position_;
6753  if (--(bdescr->gap_.gap_len))
6754  return true;
6755  // next gap is "OFF" by definition.
6756  if (*(bdescr->gap_.ptr) != bm::gap_max_bits - 1)
6757  {
6758  gap_word_t prev = *(bdescr->gap_.ptr);
6759  unsigned val = *(++(bdescr->gap_.ptr));
6760  this->position_ += val - prev;
6761  // next gap is now "ON"
6762  if (*(bdescr->gap_.ptr) != bm::gap_max_bits - 1)
6763  {
6764  prev = *(bdescr->gap_.ptr);
6765  val = *(++(bdescr->gap_.ptr));
6766  bdescr->gap_.gap_len = (gap_word_t)(val - prev);
6767  return true; // next "ON" found;
6768  }
6769  }
6770  }
6771  else // BIT
6772  {
6773  unsigned short idx = ++(bdescr->bit_.idx);
6774  if (idx < bdescr->bit_.cnt)
6775  {
6776  this->position_ = bdescr->bit_.pos + bdescr->bit_.bits[idx];
6777  return true;
6778  }
6779  this->position_ +=
6780  (bm::set_bitscan_wave_size * 32) - bdescr->bit_.bits[--idx];
6781  bdescr->bit_.ptr += bm::set_bitscan_wave_size;
6782  if (decode_bit_group(bdescr))
6783  return true;
6784  }
6785 
6786  if (search_in_blocks())
6787  return true;
6788 
6789  this->invalidate();
6790  return false;
6791 }
6792 
6793 //---------------------------------------------------------------------
6794 
6795 
6796 template<class Alloc>
6798 {
6799  if (!this->valid())
6800  return false;
6801  if (!rank)
6802  return this->valid(); // nothing to do
6803 
6804  for (; rank; --rank)
6805  {
6806  block_descr_type* bdescr = &(this->bdescr_);
6807  switch (this->block_type_)
6808  {
6809  case 0: // BitBlock
6810  for (; rank; --rank)
6811  {
6812  unsigned short idx = ++(bdescr->bit_.idx);
6813  if (idx < bdescr->bit_.cnt)
6814  {
6815  this->position_ = bdescr->bit_.pos + bdescr->bit_.bits[idx];
6816  continue;
6817  }
6818  this->position_ +=
6819  (bm::set_bitscan_wave_size * 32) - bdescr->bit_.bits[--idx];
6820  bdescr->bit_.ptr += bm::set_bitscan_wave_size;
6821 
6822  if (!decode_bit_group(bdescr, rank))
6823  break;
6824  } // for rank
6825  break;
6826  case 1: // DGAP Block
6827  for (; rank; --rank) // TODO: better skip logic
6828  {
6829  ++this->position_;
6830  if (--(bdescr->gap_.gap_len))
6831  continue;
6832 
6833  // next gap is "OFF" by definition.
6834  if (*(bdescr->gap_.ptr) == bm::gap_max_bits - 1)
6835  break;
6836  gap_word_t prev = *(bdescr->gap_.ptr);
6837  unsigned int val = *(++(bdescr->gap_.ptr));
6838 
6839  this->position_ += val - prev;
6840  // next gap is now "ON"
6841  if (*(bdescr->gap_.ptr) == bm::gap_max_bits - 1)
6842  break;
6843  prev = *(bdescr->gap_.ptr);
6844  val = *(++(bdescr->gap_.ptr));
6845  bdescr->gap_.gap_len = (gap_word_t)(val - prev);
6846  } // for rank
6847  break;
6848  default:
6849  BM_ASSERT(0);
6850  } // switch
6851 
6852  if (!rank)
6853  return true;
6854 
6855  if (!search_in_blocks())
6856  {
6857  this->invalidate();
6858  return false;
6859  }
6860  } // for rank
6861 
6862  return this->valid();
6863 }
6864 
6865 
6866 //---------------------------------------------------------------------
6867 
6868 
6869 template<class Alloc>
6871 {
6872  if (pos == 0)
6873  {
6874  go_first();
6875  return this->valid();
6876  }
6877 
6878  size_type new_pos = this->bv_->check_or_next(pos); // find the true pos
6879  if (!new_pos) // no bits available
6880  {
6881  this->invalidate();
6882  return false;
6883  }
6884  BM_ASSERT(new_pos >= pos);
6885  pos = new_pos;
6886 
6887 
6888  this->position_ = pos;
6889  size_type nb = this->block_idx_ = (pos >> bm::set_block_shift);
6891  this->bv_->get_blocks_manager();
6892  unsigned i0, j0;
6893  bm::get_block_coord(nb, i0, j0);
6894  this->block_ = bman.get_block(i0, j0);
6895 
6896  BM_ASSERT(this->block_);
6897 
6898  this->block_type_ = (bool)BM_IS_GAP(this->block_);
6899 
6900  block_descr_type* bdescr = &(this->bdescr_);
6901  unsigned nbit = unsigned(pos & bm::set_block_mask);
6902 
6903  if (this->block_type_) // gap
6904  {
6905  this->position_ = nb * bm::set_block_size * 32;
6906  search_in_gapblock();
6907 
6908  if (this->position_ == pos)
6909  return this->valid();
6910  this->position_ = pos;
6911 
6912  gap_word_t* gptr = BMGAP_PTR(this->block_);
6913  unsigned is_set;
6914  unsigned gpos = bm::gap_bfind(gptr, nbit, &is_set);
6915  BM_ASSERT(is_set);
6916 
6917  bdescr->gap_.ptr = gptr + gpos;
6918  if (gpos == 1)
6919  {
6920  bdescr->gap_.gap_len = bm::gap_word_t(gptr[gpos] - (nbit - 1));
6921  }
6922  else
6923  {
6924  bm::gap_word_t interval = bm::gap_word_t(gptr[gpos] - gptr[gpos - 1]);
6925  bm::gap_word_t interval2 = bm::gap_word_t(nbit - gptr[gpos - 1]);
6926  bdescr->gap_.gap_len = bm::gap_word_t(interval - interval2 + 1);
6927  }
6928  }
6929  else // bit
6930  {
6931  if (nbit == 0)
6932  {
6933  search_in_bitblock();
6934  return this->valid();
6935  }
6936 
6937  unsigned nword = unsigned(nbit >> bm::set_word_shift);
6938 
6939  // check if we need to step back to match the wave
6940  unsigned parity = nword % bm::set_bitscan_wave_size;
6941  bdescr->bit_.ptr = this->block_ + (nword - parity);
6942  bdescr->bit_.cnt = bm::bitscan_wave(bdescr->bit_.ptr, bdescr->bit_.bits);
6943  BM_ASSERT(bdescr->bit_.cnt);
6944  bdescr->bit_.pos = (nb * bm::set_block_size * 32) + ((nword - parity) * 32);
6945  bdescr->bit_.idx = 0;
6946  nbit &= bm::set_word_mask;
6947  nbit += 32 * parity;
6948  for (unsigned i = 0; i < bdescr->bit_.cnt; ++i)
6949  {
6950  if (bdescr->bit_.bits[i] == nbit)
6951  return this->valid();
6952  bdescr->bit_.idx++;
6953  } // for
6954  BM_ASSERT(0);
6955  }
6956  return this->valid();
6957 }
6958 
6959 //---------------------------------------------------------------------
6960 
6961 template<class Alloc>
6963 {
6964  BM_ASSERT(this->bv_);
6965 
6966  blocks_manager_type* bman = &(this->bv_->blockman_);
6967  if (!bman->is_init())
6968  {
6969  this->invalidate();
6970  return;
6971  }
6972 
6973  bm::word_t*** blk_root = bman->top_blocks_root();
6974  this->block_idx_ = this->position_= 0;
6975  unsigned i, j;
6976 
6977  for (i = 0; i < bman->top_block_size(); ++i)
6978  {
6979  bm::word_t** blk_blk = blk_root[i];
6980  if (blk_blk == 0) // not allocated
6981  {
6982  this->block_idx_ += bm::set_sub_array_size;
6983  this->position_ += bm::bits_in_array;
6984  continue;
6985  }
6986 
6987  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
6988  blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
6989 
6990  for (j = 0; j < bm::set_sub_array_size; ++j,++(this->block_idx_))
6991  {
6992  this->block_ = blk_blk[j];
6993  if (this->block_ == 0)
6994  {
6995  this->position_ += bits_in_block;
6996  continue;
6997  }
6998  if (BM_IS_GAP(this->block_))
6999  {
7000  this->block_type_ = 1;
7001  if (search_in_gapblock())
7002  return;
7003  }
7004  else
7005  {
7006  if (this->block_ == FULL_BLOCK_FAKE_ADDR)
7007  this->block_ = FULL_BLOCK_REAL_ADDR;
7008  this->block_type_ = 0;
7009  if (search_in_bitblock())
7010  return;
7011  }
7012  } // for j
7013  } // for i
7014 
7015  this->invalidate();
7016 }
7017 
7018 //---------------------------------------------------------------------
7019 
7020 template<class Alloc>
7021 bool
7022 bvector<Alloc>::enumerator::decode_wave(block_descr_type* bdescr) BMNOEXCEPT
7023 {
7024  bdescr->bit_.cnt = bm::bitscan_wave(bdescr->bit_.ptr, bdescr->bit_.bits);
7025  if (bdescr->bit_.cnt) // found
7026  {
7027  bdescr->bit_.idx = 0;
7028  return true;
7029  }
7030  return false;
7031 }
7032 
7033 //---------------------------------------------------------------------
7034 
7035 template<class Alloc>
7036 bool
7037 bvector<Alloc>::enumerator::decode_bit_group(block_descr_type* bdescr) BMNOEXCEPT
7038 {
7039  const word_t* block_end = this->block_ + bm::set_block_size;
7040  for (; bdescr->bit_.ptr < block_end;)
7041  {
7042  if (decode_wave(bdescr))
7043  {
7044  bdescr->bit_.pos = this->position_;
7045  this->position_ += bdescr->bit_.bits[0];
7046  return true;
7047  }
7048  this->position_ += bm::set_bitscan_wave_size * 32; // wave size
7049  bdescr->bit_.ptr += bm::set_bitscan_wave_size;
7050  } // for
7051  return false;
7052 }
7053 
7054 //---------------------------------------------------------------------
7055 
7056 template<class Alloc>
7057 bool
7058 bvector<Alloc>::enumerator::decode_bit_group(block_descr_type* bdescr,
7060 {
7061  const word_t* block_end = this->block_ + bm::set_block_size;
7062  for (; bdescr->bit_.ptr < block_end;)
7063  {
7064  const bm::id64_t* w64_p = (bm::id64_t*)bdescr->bit_.ptr;
7065  BM_ASSERT(bm::set_bitscan_wave_size == 4); // TODO: better handle this
7066 
7067  unsigned cnt = bm::word_bitcount64(w64_p[0]);
7068  cnt += bm::word_bitcount64(w64_p[1]);
7069  if (rank > cnt)
7070  {
7071  rank -= cnt;
7072  }
7073  else
7074  {
7075  if (decode_wave(bdescr))
7076  {
7077  bdescr->bit_.pos = this->position_;
7078  this->position_ += bdescr->bit_.bits[0];
7079  return true;
7080  }
7081  }
7082  this->position_ += bm::set_bitscan_wave_size * 32; // wave size
7083  bdescr->bit_.ptr += bm::set_bitscan_wave_size;
7084  } // for
7085  return false;
7086 }
7087 
7088 //---------------------------------------------------------------------
7089 
7090 template<class Alloc>
7091 bool bvector<Alloc>::enumerator::search_in_bitblock() BMNOEXCEPT
7092 {
7093  BM_ASSERT(this->block_type_ == 0);
7094 
7095  block_descr_type* bdescr = &(this->bdescr_);
7096  bdescr->bit_.ptr = this->block_;
7097  return decode_bit_group(bdescr);
7098 }
7099 
7100 //---------------------------------------------------------------------
7101 
7102 template<class Alloc>
7103 bool bvector<Alloc>::enumerator::search_in_gapblock() BMNOEXCEPT
7104 {
7105  BM_ASSERT(this->block_type_ == 1);
7106 
7107  block_descr_type* bdescr = &(this->bdescr_);
7108  bdescr->gap_.ptr = BMGAP_PTR(this->block_);
7109  unsigned bitval = *(bdescr->gap_.ptr) & 1;
7110 
7111  ++(bdescr->gap_.ptr);
7112 
7113  for (;true;)
7114  {
7115  unsigned val = *(bdescr->gap_.ptr);
7116  if (bitval)
7117  {
7118  gap_word_t* first = BMGAP_PTR(this->block_) + 1;
7119  if (bdescr->gap_.ptr == first)
7120  {
7121  bdescr->gap_.gap_len = (gap_word_t)(val + 1);
7122  }
7123  else
7124  {
7125  bdescr->gap_.gap_len =
7126  (gap_word_t)(val - *(bdescr->gap_.ptr-1));
7127  }
7128  return true;
7129  }
7130  this->position_ += val + 1;
7131  if (val == bm::gap_max_bits - 1)
7132  break;
7133  bitval ^= 1;
7134  ++(bdescr->gap_.ptr);
7135  }
7136  return false;
7137 }
7138 
7139 //---------------------------------------------------------------------
7140 
7141 template<class Alloc>
7142 bool bvector<Alloc>::enumerator::search_in_blocks() BMNOEXCEPT
7143 {
7144  ++(this->block_idx_);
7145  const blocks_manager_type& bman = this->bv_->blockman_;
7146  block_idx_type i = this->block_idx_ >> bm::set_array_shift;
7147  block_idx_type top_block_size = bman.top_block_size();
7148  bm::word_t*** blk_root = bman.top_blocks_root();
7149  for (; i < top_block_size; ++i)
7150  {
7151  bm::word_t** blk_blk = blk_root[i];
7152  if (blk_blk == 0)
7153  {
7154  // fast scan fwd in top level
7155  size_type bn = this->block_idx_ + bm::set_sub_array_size;
7156  size_type pos = this->position_ + bm::bits_in_array;
7157  for (++i; i < top_block_size; ++i)
7158  {
7159  if (blk_root[i])
7160  break;
7161  bn += bm::set_sub_array_size;
7162  pos += bm::bits_in_array;
7163  } // for i
7164  this->block_idx_ = bn;
7165  this->position_ = pos;
7166  if ((i < top_block_size) && blk_root[i])
7167  --i;
7168  continue;
7169  }
7170  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
7171  blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
7172 
7173  block_idx_type j = this->block_idx_ & bm::set_array_mask;
7174 
7175  for(; j < bm::set_sub_array_size; ++j, ++(this->block_idx_))
7176  {
7177  this->block_ = blk_blk[j];
7178  if (this->block_ == 0)
7179  {
7180  this->position_ += bm::bits_in_block;
7181  continue;
7182  }
7183  this->block_type_ = BM_IS_GAP(this->block_);
7184  if (this->block_type_)
7185  {
7186  if (search_in_gapblock())
7187  return true;
7188  }
7189  else
7190  {
7191  if (this->block_ == FULL_BLOCK_FAKE_ADDR)
7192  this->block_ = FULL_BLOCK_REAL_ADDR;
7193  if (search_in_bitblock())
7194  return true;
7195  }
7196  } // for j
7197  } // for i
7198  return false;
7199 }
7200 
7201 //---------------------------------------------------------------------
7202 
7203 
7204 } // namespace
7205 
7206 #include "bmundef.h"
7207 
7208 #ifdef _MSC_VER
7209 #pragma warning( pop )
7210 #endif
7211 
7212 
7213 #endif
bm::bvector::insert_iterator::insert_iterator
insert_iterator(bvector< Alloc > &bvect) BMNOEXCEPT
Definition: bm.h:392
bm::gap_shift_l1
bool gap_shift_l1(T *BMRESTRICT buf, unsigned co_flag, unsigned *BMRESTRICT new_len) BMNOEXCEPT
Left shift GAP block by 1 bit.
Definition: bmfunc.h:2946
bm::bvector::inc
bool inc(size_type n)
Increment the specified element.
Definition: bm.h:3800
bm::bvector::operator=
bvector & operator=(const bvector< Alloc > &bvect)
Copy assignment operator.
Definition: bm.h:915
bm::bvector::const_reference
bool const_reference
Definition: bm.h:230
bm::bit_andnot_arr_ffmask
void bit_andnot_arr_ffmask(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
bitblock AND NOT with constant ~0 mask operation.
Definition: bmfunc.h:7276
bm::operation_functions::gap_operation
static gap_operation_func_type gap_operation(unsigned i)
Definition: bmfunc.h:8366
bm::bvector::bit_and
bm::bvector< Alloc > & bit_and(const bm::bvector< Alloc > &bv, optmode opt_mode=opt_none)
2 operand logical AND
Definition: bm.h:1704
bm::bvector::iterator_base::dgap_descr::gap_len
gap_word_t gap_len
Current dgap length.
Definition: bm.h:342
bm::find_not_null_ptr
bool find_not_null_ptr(bm::word_t ***arr, N start, N size, N *pos) BMNOEXCEPT
Definition: bmfunc.h:923
bm::bvector::get_allocator_pool
allocator_pool_type * get_allocator_pool() BMNOEXCEPT
Get curent allocator pool (if set)
Definition: bm.h:1027
bm::gap_equiv_len
const unsigned gap_equiv_len
Definition: bmconst.h:81
bm::bvector::counted_enumerator::iterator_category
std::input_iterator_tag iterator_category
Definition: bm.h:719
bm::bvector::set_range
bvector< Alloc > & set_range(size_type left, size_type right, bool value=true)
Sets all bits in the specified closed interval [left,right] Interval must be inside the bvector's siz...
Definition: bm.h:2158
bm::bvector::bulk_insert_iterator::get_bvector
bvector_type * get_bvector() const BMNOEXCEPT
Definition: bm.h:574
bm::bvector::combine_operation_and
void combine_operation_and(const bm::bvector< Alloc > &bvect, optmode opt_mode)
perform a set-algebra operation AND
Definition: bm.h:5377
VECT_XOR_ARR_2_MASK
#define VECT_XOR_ARR_2_MASK(dst, src, src_end, mask)
Definition: bmsse4.h:1713
bmconst.h
Constants, tables and typedefs.
bm::bvector::calc_stat
void calc_stat(struct bm::bvector< Alloc >::statistics *st) const BMNOEXCEPT
Calculates bitvector statistics.
Definition: bm.h:3393
bm::bvector::mem_pool_guard
Definition: bm.h:771
bm::bvector::opt_free_01
@ opt_free_01
Free unused 0 and 1 blocks.
Definition: bm.h:133
bm::bvector::sync_size
void sync_size()
Syncronize size if it got extended due to bulk import.
Definition: bm.h:2277
bm::bvector::iterator_base::compare_state
bool compare_state(const iterator_base &ib) const BMNOEXCEPT
Compare FSMs for testing purposes.
Definition: bm.h:292
bm::bit_block_sub
bm::id64_t bit_block_sub(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Plain bitblock SUB (AND NOT) operation. Function does not analyse availability of source and destinat...
Definition: bmfunc.h:7019
bm::bit_block_xor_2way
bm::id64_t bit_block_xor_2way(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
2 way (target := source1 ^ source2) bitblock XOR operation.
Definition: bmfunc.h:6825
bm::bit_is_all_zero
bool bit_is_all_zero(const bm::word_t *BMRESTRICT start) BMNOEXCEPT
Returns "true" if all bits in the block are 0.
Definition: bmfunc.h:1045
bm::bvector::bvector
bvector(strategy strat=BM_BIT, const gap_word_t *glevel_len=bm::gap_len_table< true >::_len, size_type bv_size=bm::id_max, const Alloc &alloc=Alloc())
Constructs bvector class.
Definition: bm.h:858
bm::bvector::enumerator::go_first
void go_first() BMNOEXCEPT
Position enumerator to the first available bit.
Definition: bm.h:6962
bm::bvector::bit_or
bm::bvector< Alloc > & bit_or(const bm::bvector< Alloc > &bv)
2 operand logical OR
Definition: bm.h:1693
bm::bvector::bit_xor
bm::bvector< Alloc > & bit_xor(const bm::bvector< Alloc > &bv)
2 operand logical XOR
Definition: bm.h:1715
bm::bvector::bit_sub
bm::bvector< Alloc > & bit_sub(const bm::bvector< Alloc > &bv)
2 operand logical SUB(AND NOT). Also known as MINUS.
Definition: bm.h:1725
bm::bvector::get_blocks_manager
const blocks_manager_type & get_blocks_manager() const BMNOEXCEPT
get access to memory manager (internal) Use only if you are BitMagic library
Definition: bm.h:1924
bm::gap_operation_sub
gap_word_t * gap_operation_sub(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2, gap_word_t *BMRESTRICT tmp_buf, unsigned &dsize) BMNOEXCEPT
GAP SUB (AND NOT) operation.
Definition: bmfunc.h:5835
bm::bvector::operator^=
void operator^=(const bvector< Alloc > &bv)
Definition: bm.h:1003
bm::bvector::rs_index_type
rs_index< allocator_type > rs_index_type
Definition: bm.h:831
bmfunc.h
Bit manipulation primitives (internal)
bm::bvector::enumerator::skip
bool skip(size_type rank) BMNOEXCEPT
Skip specified number of bits from enumeration.
Definition: bm.h:6797
bm::bvector::insert_iterator::bvector_type
bm::bvector< Alloc > bvector_type
Definition: bm.h:384
BM_IS_GAP
#define BM_IS_GAP(ptr)
Definition: bmdef.h:181
bm::bvector::get_enumerator
enumerator get_enumerator(size_type pos) const
Returns enumerator pointing on specified or the next available bit.
Definition: bm.h:1782
bm::gapcmp
int gapcmp(const T *buf1, const T *buf2) BMNOEXCEPT
Lexicographical comparison of GAP buffers.
Definition: bmfunc.h:2256
bm::bvector::set_new_blocks_strat
void set_new_blocks_strat(strategy strat)
Sets new blocks allocation strategy.
Definition: bm.h:1810
bm::bvector::bvector
bvector(size_type bv_size, strategy strat=BM_BIT, const gap_word_t *glevel_len=bm::gap_len_table< true >::_len, const Alloc &alloc=Alloc())
Constructs bvector class.
Definition: bm.h:870
bm::bvector::counted_enumerator::counted_enumerator
counted_enumerator() BMNOEXCEPT
Definition: bm.h:721
bm::bits_in_array
const unsigned bits_in_array
Definition: bmconst.h:114
BM_XOR_OP
#define BM_XOR_OP(x)
Definition: bm.h:5271
bm::set_block_bits_u32
void set_block_bits_u32(bm::word_t *BMRESTRICT block, const unsigned *BMRESTRICT idx, unsigned start, unsigned stop) BMNOEXCEPT
set bits in a bit-block using global index
Definition: bmfunc.h:8635
bm::set_block_size
const unsigned set_block_size
Definition: bmconst.h:54
bm::gap_operation_func_type
gap_word_t *(* gap_operation_func_type)(const gap_word_t *BMRESTRICT, const gap_word_t *BMRESTRICT, gap_word_t *BMRESTRICT, unsigned &)
Definition: bmfunc.h:8339
bm::BM_AND
@ BM_AND
Definition: bmconst.h:177
bm::bvector<>::optmode
optmode
Optimization mode Every next level means additional checks (better compression vs time)
Definition: bm.h:129
bm::bvector::get_bit
bool get_bit(size_type n) const BMNOEXCEPT
returns true if bit n is set and false is bit n is 0.
Definition: bm.h:3037
bm::gap_xor_to_bitset
void gap_xor_to_bitset(unsigned *BMRESTRICT dest, const T *BMRESTRICT pcurr) BMNOEXCEPT
XOR GAP block to bitblock.
Definition: bmfunc.h:3408
bm::bvector::flip
bvector< Alloc > & flip(size_type n)
Flips bit n.
Definition: bm.h:1231
bm::bvector::mem_pool_guard::mem_pool_guard
mem_pool_guard(allocator_pool_type &pool, bvector< Alloc > &bv) BMNOEXCEPT
Definition: bm.h:777
bm::bit_find_first
bool bit_find_first(const bm::word_t *BMRESTRICT block, unsigned *BMRESTRICT pos) BMNOEXCEPT
BIT block find the first set bit.
Definition: bmfunc.h:7552
bm::bvector::operator&=
void operator&=(const bvector< Alloc > &bv)
Definition: bm.h:1002
bm::bvector::enumerator::skip_to_rank
bool skip_to_rank(size_type rank) BMNOEXCEPT
Skip to specified relative rank.
Definition: bm.h:672
bm::bvector::insert_iterator
Output iterator iterator designed to set "ON" bits based on input sequence of integers (bit indeces).
Definition: bm.h:377
bm::bvector::size
size_type size() const BMNOEXCEPT
Returns bvector's capacity (number of bits it can store)
Definition: bm.h:1258
bm::bvector::enumerator::operator*
size_type operator*() const BMNOEXCEPT
Get current position (value)
Definition: bm.h:638
bm::bvector::bulk_insert_iterator::bvector_type
bm::bvector< Alloc > bvector_type
Definition: bm.h:467
bm::bvector::bulk_insert_iterator::iterator_category
std::output_iterator_tag iterator_category
Definition: bm.h:465
bm::bvector::insert_iterator::operator++
insert_iterator & operator++()
Definition: bm.h:431
bm::bits_in_block
const unsigned bits_in_block
Definition: bmconst.h:113
bm::bvector::reference::operator|=
const reference & operator|=(bool value) const
Definition: bm.h:190
bm::bvector::bulk_insert_iterator::difference_type
void difference_type
Definition: bm.h:470
bm::bvector::set_gap_levels
void set_gap_levels(const gap_word_t *glevel_len)
Sets new GAP lengths table. All GAP blocks will be reallocated to match the new scheme.
Definition: bm.h:3143
bm::bvector::reset
bvector< Alloc > & reset()
Clears every bit in the bitvector.
Definition: bm.h:1225
bm::bvector::reference::operator=
const reference & operator=(bool value) const BMNOEXCEPT
Definition: bm.h:171
bm::block_find_rank
SIZE_TYPE block_find_rank(const bm::word_t *const block, SIZE_TYPE rank, unsigned nbit_from, unsigned &nbit_pos) BMNOEXCEPT
Find rank in block (GAP or BIT)
Definition: bmfunc.h:7761
bm::set_block_bits_u64
void set_block_bits_u64(bm::word_t *BMRESTRICT block, const bm::id64_t *BMRESTRICT idx, bm::id64_t start, bm::id64_t stop) BMNOEXCEPT
set bits in a bit-block using global index
Definition: bmfunc.h:8605
bm::operator^
bvector< Alloc > operator^(const bvector< Alloc > &bv1, const bvector< Alloc > &bv2)
Definition: bm.h:2100
bm::set_total_blocks
const unsigned set_total_blocks
Definition: bmconst.h:110
bm::bvector::bulk_insert_iterator::bulk_insert_iterator
bulk_insert_iterator(bvector< Alloc > &bvect, bm::sort_order so=BM_UNKNOWN) BMNOEXCEPT
Definition: bm.h:484
bm::bvector::insert_iterator::operator=
insert_iterator & operator=(size_type n)
Definition: bm.h:411
bm::bvector::bulk_insert_iterator::bulk_insert_iterator
bulk_insert_iterator(const insert_iterator &iit)
Definition: bm.h:503
bm::bvector::bit_or
bm::bvector< Alloc > & bit_or(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode)
3-operand OR : this := bv1 OR bv2
Definition: bm.h:4809
bm::bit_invert
void bit_invert(T *start) BMNOEXCEPT
Definition: bmfunc.h:5253
BM_DECLARE_TEMP_BLOCK
#define BM_DECLARE_TEMP_BLOCK(x)
Definition: bm.h:47
bm::bvector::bit_and
bm::bvector< Alloc > & bit_and(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode)
3-operand AND : this := bv1 AND bv2
Definition: bm.h:5017
bm::bvector::count_range
size_type count_range(size_type left, size_type right, const rs_index_type &rs_idx) const BMNOEXCEPT
Returns count of 1 bits in the given range [left..right] Uses rank-select index to accelerate the sea...
Definition: bm.h:2959
bm::for_each_nzblock_range
void for_each_nzblock_range(T ***root, N top_size, N nb_from, N nb_to, F &f) BMNOEXCEPT
Definition: bmfunc.h:1325
FULL_SUB_BLOCK_REAL_ADDR
#define FULL_SUB_BLOCK_REAL_ADDR
Definition: bmdef.h:150
bm::bvector::combine_operation_xor
void combine_operation_xor(const bm::bvector< Alloc > &bvect)
perform a set-algebra operation XOR
Definition: bm.h:5278
bm::bvector::flip
bvector< Alloc > & flip()
Flips all bits.
Definition: bm.h:1238
bm::is_bits_one
bool is_bits_one(const bm::wordop_t *start) BMNOEXCEPT
Returns "true" if all bits in the block are 1.
Definition: bmfunc.h:5277
bm::bvector::insert_iterator::value_type
size_type value_type
Definition: bm.h:385
bm::bvector::counted_enumerator::counted_enumerator
counted_enumerator(const enumerator &en) BMNOEXCEPT
Definition: bm.h:723
bm::bvector::bulk_insert_iterator::value_type
bvector_type::size_type value_type
Definition: bm.h:469
bm::for_each_nzblock_if
bool for_each_nzblock_if(T ***root, BI size1, F &f) BMNOEXCEPT
Definition: bmfunc.h:1613
encoding.h
Encoding utilities for serialization (internal)
bm::bvector::erase
void erase(size_type n)
Erase bit in the specified position All the vector content after erase position is shifted left.
Definition: bm.h:4555
BMGAP_PTR
#define BMGAP_PTR(ptr)
Definition: bmdef.h:179
bm::bvector::bulk_insert_iterator::operator=
bulk_insert_iterator & operator=(const bulk_insert_iterator &ii)
Definition: bm.h:519
bm::bvector::bulk_insert_iterator::bvect_
bvector_type * bvect_
target bvector
Definition: bm.h:588
bm::bvector::any
bool any() const BMNOEXCEPT
Returns true if any bits in this bitset are set, and otherwise returns false.
Definition: bm.h:2244
bm::bvector::find_rank
bool find_rank(size_type rank, size_type from, size_type &pos) const BMNOEXCEPT
Find bit-vector position for the specified rank(bitcount)
Definition: bm.h:4101
bm::gap_capacity
unsigned gap_capacity(const T *BMRESTRICT buf, const T *BMRESTRICT glevel_len) BMNOEXCEPT
Returs GAP block capacity.
Definition: bmfunc.h:1114
bm::bvector::bulk_insert_iterator::buf_size_max
static size_type buf_size_max() BMNOEXCEPT
Definition: bm.h:578
bm::bvector::set_bit_no_check
void set_bit_no_check(size_type n)
Set bit without checking preconditions (size, etc)
Definition: bm.h:3468
bm::get_block_coord
void get_block_coord(BI_TYPE nb, unsigned &i, unsigned &j) BMNOEXCEPT
Recalc linear bvector block index into 2D matrix coordinates.
Definition: bmfunc.h:147
bm::gap_operation_to_bitset_func_type
void(* gap_operation_to_bitset_func_type)(unsigned *, const gap_word_t *)
Definition: bmfunc.h:8335
bm::bvector::iterator_base::position_
size_type position_
Bit position (bit idx)
Definition: bm.h:347
bm::BM_SORTED
@ BM_SORTED
input set is sorted (ascending order)
Definition: bmconst.h:191
BMSET_PTRGAP
#define BMSET_PTRGAP(ptr)
Definition: bmdef.h:180
bm::bvector::none
bool none() const BMNOEXCEPT
Returns true if no bits are set, otherwise returns false.
Definition: bm.h:1494
bm::rs3_border0
const unsigned rs3_border0
Definition: bmconst.h:118
bm::bvector::counted_enumerator::count
size_type count() const BMNOEXCEPT
Number of bits ON starting from the .
Definition: bm.h:757
bm::bvector::iterator_base::block_idx_
block_idx_type block_idx_
Block index.
Definition: bm.h:350
bm::bvector::import_block
void import_block(const size_type *ids, block_idx_type nblock, size_type start, size_type stop)
Definition: bm.h:3685
bm::bvector::enumerator
friend class enumerator
Definition: bm.h:809
bm::bvector::iterator_base::bitblock_descr::bits
unsigned char bits[set_bitscan_wave_size *32]
bit list
Definition: bm.h:330
bm::id64_t
unsigned long long int id64_t
Definition: bmconst.h:34
bm::bvector::bulk_insert_iterator::bulk_insert_iterator
bulk_insert_iterator() BMNOEXCEPT
Definition: bm.h:474
bm::bvector::enumerator::iterator_category
std::input_iterator_tag iterator_category
Definition: bm.h:603
bm::bvector::bulk_insert_iterator::buf_size_
size_type buf_size_
current buffer size
Definition: bm.h:590
bm::bvector::keep_range
void keep_range(size_type left, size_type right)
Sets all bits to zero outside of the closed interval [left,right] Expected result: 00000....
Definition: bm.h:2145
bm::aggregator
Algorithms for fast aggregation of a group of bit-vectors.
Definition: bmaggregator.h:58
bm::bit_block_shift_l1_unr
bool bit_block_shift_l1_unr(bm::word_t *block, bm::word_t *empty_acc, bm::word_t co_flag) BMNOEXCEPT
Left bit-shift of bit-block by 1 bit (loop unrolled)
Definition: bmfunc.h:5010
bm::bvector::allocation_policy::strat
bm::strategy strat
Definition: bm.h:821
bm::gap_invert
void gap_invert(T *buf) BMNOEXCEPT
Inverts all bits in the GAP buffer.
Definition: bmfunc.h:4001
bm::bvector::enumerator
Constant iterator designed to enumerate "ON" bits.
Definition: bm.h:599
bm::bvector::compare
int compare(const bvector< Alloc > &bvect) const BMNOEXCEPT
Lexicographical comparison with a bitvector.
Definition: bm.h:3159
bm::gap_sub_to_bitset
void gap_sub_to_bitset(unsigned *BMRESTRICT dest, const T *BMRESTRICT pcurr) BMNOEXCEPT
SUB (AND NOT) GAP block to bitblock.
Definition: bmfunc.h:3320
bm::bvector::get_new_blocks_strat
strategy get_new_blocks_strat() const BMNOEXCEPT
Returns blocks allocation strategy.
Definition: bm.h:1818
bm::bvector::insert_iterator::max_bit_
size_type max_bit_
Definition: bm.h:439
bm::bvector::enumerator::go_to
bool go_to(size_type pos) BMNOEXCEPT
go to a specific position in the bit-vector (or next)
Definition: bm.h:6870
bm::bvector::enumerator::enumerator
enumerator() BMNOEXCEPT
Definition: bm.h:611
BM_ASSERT_THROW
#define BM_ASSERT_THROW(x, xerrcode)
Definition: bmdef.h:401
bm::bvector::iterator_base::dgap_descr
Information about current DGAP block.
Definition: bm.h:339
bm::word_bitcount64
BMFORCEINLINE unsigned word_bitcount64(bm::id64_t x) BMNOEXCEPT
Definition: bmfunc.h:230
bm::bvector::forget_count
void forget_count() BMNOEXCEPT
Definition: bm.h:1420
bm::gap_convert_to_bitset_smart
unsigned * gap_convert_to_bitset_smart(unsigned *BMRESTRICT dest, const T *BMRESTRICT buf, id_t set_max) BMNOEXCEPT
Smart GAP block to bitblock conversion.
Definition: bmfunc.h:3881
bm::set_word_shift
const unsigned set_word_shift
Definition: bmconst.h:71
bm::bvector::select
bool select(size_type rank, size_type &pos, const rs_index_type &rs_idx) const BMNOEXCEPT
select bit-vector position for the specified rank(bitcount)
Definition: bm.h:4225
bm::bvector::throw_bad_alloc
static void throw_bad_alloc()
Definition: bm.h:6730
bm::bvector::allocation_policy::glevel_len
const gap_word_t * glevel_len
Definition: bm.h:822
bm::bvector::insert_iterator::iterator_category
std::output_iterator_tag iterator_category
Definition: bm.h:382
bm::bvector::allocator_type
Alloc allocator_type
Definition: bm.h:110
bm::gap_and_to_bitset
void gap_and_to_bitset(unsigned *BMRESTRICT dest, const T *BMRESTRICT pcurr) BMNOEXCEPT
ANDs GAP block to bitblock.
Definition: bmfunc.h:3486
bm::bvector::enumerator::operator++
enumerator & operator++() BMNOEXCEPT
Advance enumerator forward to the next available bit.
Definition: bm.h:644
bm::set_sub_array_size
const unsigned set_sub_array_size
Definition: bmconst.h:94
bm::gap_find_first
unsigned gap_find_first(const T *BMRESTRICT buf, unsigned *BMRESTRICT first) BMNOEXCEPT
GAP block find the first set bit.
Definition: bmfunc.h:1193
bm::wordop_t
id64_t wordop_t
Definition: bmconst.h:127
bm::bvector::move_from
void move_from(bvector< Alloc > &bvect) BMNOEXCEPT
Move bvector content from another bvector.
Definition: bm.h:2132
bm::check_block_one
bool check_block_one(const bm::word_t *blk, bool deep_scan) BMNOEXCEPT
Checks if block has only 1 bits.
Definition: bmfunc.h:7882
bm::bit_block_insert
bm::word_t bit_block_insert(bm::word_t *BMRESTRICT block, unsigned bitpos, bool value) BMNOEXCEPT
insert bit into position and shift the rest right with carryover
Definition: bmfunc.h:4876
bm::operator|
bvector< Alloc > operator|(const bvector< Alloc > &bv1, const bvector< Alloc > &bv2)
Definition: bm.h:2089
bm::bvector::bulk_insert_iterator::operator=
bulk_insert_iterator & operator=(bulk_insert_iterator &&ii) BMNOEXCEPT
Definition: bm.h:530
bm::bvector::iterator_base::bitblock_descr::cnt
unsigned short cnt
Number of ON bits.
Definition: bm.h:332
bm::bitcmp
int bitcmp(const T *buf1, const T *buf2, unsigned len) BMNOEXCEPT
Lexicographical comparison of BIT buffers.
Definition: bmfunc.h:4081
bm::bvector::iterator_base::block_descr::bit_
bitblock_descr bit_
BitBlock related info.
Definition: bm.h:355
bm::bvector::swap
void swap(bvector< Alloc > &bvect) BMNOEXCEPT
Exchanges content of bv and this bvector.
Definition: bm.h:3381
BM_OR_OP
#define BM_OR_OP(x)
Definition: bm.h:5198
bm::bvector::reference::operator&=
const reference & operator&=(bool value) const
Definition: bm.h:183
bm::set_top_array_size
const unsigned set_top_array_size
Definition: bmconst.h:109
bm::bvector::iterator_base::bitblock_descr::idx
unsigned short idx
Current position in the bit list.
Definition: bm.h:331
bm::set_bitscan_wave_size
const unsigned short set_bitscan_wave_size
Size of bit decode wave in words.
Definition: bmfunc.h:8421
bm::bvector::bulk_insert_iterator::operator=
bulk_insert_iterator & operator=(size_type n)
Definition: bm.h:541
bm::bvector::find_first_mismatch
bool find_first_mismatch(const bvector< Alloc > &bvect, size_type &pos, size_type search_to=bm::id_max) const BMNOEXCEPT
Find index of first bit different between this and the agr vector.
Definition: bm.h:3277
bm::bvector::iterator_base::operator<=
bool operator<=(const iterator_base &it) const BMNOEXCEPT
Definition: bm.h:260
bm::bvector::bulk_insert_iterator::pointer
void pointer
Definition: bm.h:471
bm::strategy
strategy
Block allocation strategies.
Definition: bmconst.h:141
bm::bvector::operator~
bvector< Alloc > operator~() const
Definition: bm.h:1014
bm::bvector::bulk_insert_iterator::operator++
bulk_insert_iterator & operator++()
Definition: bm.h:558
bm::bit_block_and
bm::id64_t bit_block_and(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Plain bitblock AND operation. Function does not analyse availability of source and destination blocks...
Definition: bmfunc.h:5940
bm::bvector
Bitvector Bit-vector container with runtime compression of bits.
Definition: bm.h:107
bm::bvector::set
bvector< Alloc > & set()
Sets every bit in this bitset to 1.
Definition: bm.h:3572
bmundef.h
pre-processor un-defines to avoid global space pollution (internal)
bm::bit_block_or
bool bit_block_or(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Plain bitblock OR operation. Function does not analyse availability of source and destination blocks.
Definition: bmfunc.h:6749
bm::all_bits_mask
const id64_t all_bits_mask
Definition: bmconst.h:128
bm::bvector::insert_iterator::insert_iterator
insert_iterator() BMNOEXCEPT
Definition: bm.h:390
bm::bvector::enumerator::value_type
size_type value_type
Definition: bm.h:605
bm::idx_arr_block_lookup_u64
bm::id64_t idx_arr_block_lookup_u64(const bm::id64_t *idx, bm::id64_t size, bm::id64_t nb, bm::id64_t start) BMNOEXCEPT
block boundaries look ahead U32
Definition: bmfunc.h:8546
bm::bvector::set
bvector< Alloc > & set(size_type n, bool val=true)
Sets bit n if val is true, clears bit n if val is false.
Definition: bm.h:3581
bm::BM_UNKNOWN
@ BM_UNKNOWN
sort order unknown
Definition: bmconst.h:193
bm::operator&
bvector< Alloc > operator&(const bvector< Alloc > &bv1, const bvector< Alloc > &bv2)
Definition: bm.h:2078
bm::id_max
const unsigned id_max
Definition: bmconst.h:108
bm::set_block_mask
const unsigned set_block_mask
Definition: bmconst.h:56
bm::bvector::shift_left
bool shift_left()
Shift left by 1 bit, fill with zero return carry out.
Definition: bm.h:4368
bm::set_array_mask
const unsigned set_array_mask
Definition: bmconst.h:96
bm::bvector::count
size_type count() const BMNOEXCEPT
population cout (count of ON bits)
Definition: bm.h:2194
bm::bvector::copy_range
void copy_range(const bvector< Alloc > &bvect, size_type left, size_type right)
Copy all bits in the specified closed interval [left,right].
Definition: bm.h:6653
bm::bvector::operator=
bvector & operator=(bvector< Alloc > &&bvect) BMNOEXCEPT
Move assignment operator.
Definition: bm.h:957
bm::xor_swap
void xor_swap(W &x, W &y) BMNOEXCEPT
XOR swap two scalar variables.
Definition: bmfunc.h:909
bm::gap_find_last
unsigned gap_find_last(const T *BMRESTRICT buf, unsigned *BMRESTRICT last) BMNOEXCEPT
GAP block find the last set bit.
Definition: bmfunc.h:1162
bm::bvector::allocator_pool_type
allocator_type::allocator_pool_type allocator_pool_type
Definition: bm.h:111
bm::bvector::iterator_base::valid
bool valid() const BMNOEXCEPT
Checks if iterator is still valid. Analog of != 0 comparison for pointers.
Definition: bm.h:280
bm::BM_BIT
@ BM_BIT
No GAP compression strategy. All new blocks are bit blocks.
Definition: bmconst.h:143
bm::idx_arr_block_lookup_u32
unsigned idx_arr_block_lookup_u32(const unsigned *idx, unsigned size, unsigned nb, unsigned start) BMNOEXCEPT
block boundaries look ahead U32
Definition: bmfunc.h:8572
bm::gap_block_find
unsigned gap_block_find(const T *BMRESTRICT buf, unsigned nbit, bm::id_t *BMRESTRICT prev) BMNOEXCEPT
Searches for the next 1 bit in the GAP block.
Definition: bmfunc.h:3098
bm::gap_bit_count_to
unsigned gap_bit_count_to(const T *const buf, T right, bool is_corrected=false) BMNOEXCEPT
Counts 1 bits in GAP buffer in the closed [0, right] range.
Definition: bmfunc.h:2101
bm::bvector::iterator_base
Base class for all iterators.
Definition: bm.h:236
bm::bvector::enumerator::enumerator
enumerator(const bvector< Alloc > *bv) BMNOEXCEPT
Construct enumerator associated with a vector. This construction creates unpositioned iterator with s...
Definition: bm.h:618
bm::bvector::iterator_base::iterator_base
iterator_base() BMNOEXCEPT
Definition: bm.h:240
bm::bvector::enumerator::reference
unsigned & reference
Definition: bm.h:608
BMNOEXCEPT
#define BMNOEXCEPT
Definition: bmdef.h:79
bm::gap_bit_count_range
unsigned gap_bit_count_range(const T *const buf, unsigned left, unsigned right) BMNOEXCEPT
Counts 1 bits in GAP buffer in the closed [left, right] range.
Definition: bmfunc.h:1867
bm::bvector::opt_compress
@ opt_compress
compress blocks when possible (GAP/prefix sum)
Definition: bm.h:134
bm::bvector::allocation_policy
memory allocation policy
Definition: bm.h:819
bm::bvector::equal
bool equal(const bvector< Alloc > &bvect) const BMNOEXCEPT
Equal comparison with an agr bit-vector.
Definition: bm.h:1883
bm::bvector::iterator_base::bitblock_descr
Bit-block descriptor.
Definition: bm.h:327
bm::bvector::insert_iterator::operator++
insert_iterator & operator++(int)
Definition: bm.h:433
bm::bvector::bit_sub
bm::bvector< Alloc > & bit_sub(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode)
3-operand SUB : this := bv1 MINUS bv2 SUBtraction is also known as AND NOT
Definition: bm.h:5111
bm::update_block_digest0
bm::id64_t update_block_digest0(const bm::word_t *const block, bm::id64_t digest) BMNOEXCEPT
Compute digest for 64 non-zero areas based on existing digest (function revalidates zero areas)
Definition: bmfunc.h:776
bm::gap_set_value
unsigned gap_set_value(unsigned val, T *BMRESTRICT buf, unsigned pos, unsigned *BMRESTRICT is_set) BMNOEXCEPT
Sets or clears bit in the GAP buffer.
Definition: bmfunc.h:2661
bm::calc_block_digest0
bm::id64_t calc_block_digest0(const bm::word_t *const block) BMNOEXCEPT
Compute digest for 64 non-zero areas.
Definition: bmfunc.h:734
bm::bvector::opt_none
@ opt_none
no optimization
Definition: bm.h:131
FULL_BLOCK_FAKE_ADDR
#define FULL_BLOCK_FAKE_ADDR
Definition: bmdef.h:149
bm::bvector::init
void init()
Explicit post-construction initialization.
Definition: bm.h:2123
bm::bit_operation_xor
bm::word_t * bit_operation_xor(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
bitblock XOR operation.
Definition: bmfunc.h:7311
bm::rs3_half_span
const unsigned rs3_half_span
Definition: bmconst.h:120
bm::bvector::set_allocator_pool
void set_allocator_pool(allocator_pool_type *pool_ptr) BMNOEXCEPT
Set allocator pool for local (non-th readed) memory cyclic(lots of alloc-free ops) opertations.
Definition: bm.h:1022
bm::gap_word_t
unsigned short gap_word_t
Definition: bmconst.h:77
bm::rs3_border1
const unsigned rs3_border1
Definition: bmconst.h:119
bm::bvector::operator[]
bool operator[](size_type n) const BMNOEXCEPT
Definition: bm.h:996
bm::bit_operation_or
bm::word_t * bit_operation_or(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Block OR operation. Makes analysis if block is 0 or FULL.
Definition: bmfunc.h:6959
bm::bvector::bulk_insert_iterator::buf_
size_type * buf_
bulk insert buffer
Definition: bm.h:589
bm::set_array_shift
const unsigned set_array_shift
Definition: bmconst.h:95
bm::block_any
bool block_any(const bm::word_t *const BMRESTRICT block) BMNOEXCEPT
Returns "true" if one bit is set in the block Function check for block varieties.
Definition: bmfunc.h:5584
bm::bvector::enumerator::operator++
enumerator operator++(int) BMNOEXCEPT
Advance enumerator forward to the next available bit. Possibly do NOT use this operator it is slower ...
Definition: bm.h:649
bm::bvector::is_init
bool is_init() const BMNOEXCEPT
Return true if bvector is initialized at all.
Definition: bm.h:1858
bm::gap_convert_to_bitset
void gap_convert_to_bitset(unsigned *BMRESTRICT dest, const T *BMRESTRICT buf) BMNOEXCEPT
GAP block to bitblock conversion.
Definition: bmfunc.h:3859
bm::bvector::keep
void keep(const size_type *ids, size_type ids_size, bm::sort_order so=bm::BM_UNKNOWN)
Keep list of bits in this bitset, others are cleared.
Definition: bm.h:3518
bm::bvector::bulk_insert_iterator::bulk_insert_iterator
bulk_insert_iterator(bulk_insert_iterator &&iit) BMNOEXCEPT
Definition: bm.h:511
BM_ASSERT
#define BM_ASSERT
Definition: bmdef.h:130
bm::bvector::counted_enumerator::operator++
counted_enumerator & operator++() BMNOEXCEPT
Definition: bm.h:737
bm::bvector::bulk_insert_iterator::~bulk_insert_iterator
~bulk_insert_iterator()
Definition: bm.h:477
bm::bvector::enumerator::pointer
unsigned * pointer
Definition: bm.h:607
bm::bvector::iterator_base::bdescr_
union bm::bvector::iterator_base::block_descr bdescr_
BM_SUB_OP
#define BM_SUB_OP(x)
Definition: bm.h:5459
bm::bvector::bulk_insert_iterator::operator++
bulk_insert_iterator & operator++(int)
Definition: bm.h:560
bm::id_t
unsigned int id_t
Definition: bmconst.h:37
bm::bvector::mem_pool_guard::~mem_pool_guard
~mem_pool_guard()
Definition: bm.h:782
bm::bvector::import
void import(const size_type *ids, size_type ids_size, bm::sort_order sorted_idx)
Import integers (set bits).
Definition: bm.h:3634
bm::bvector::combine_operation_sub
void combine_operation_sub(const bm::bvector< Alloc > &bvect)
perform a set-algebra operation MINUS (AND NOT)
Definition: bm.h:5465
bm::bvector::counted_enumerator::operator++
counted_enumerator operator++(int)
Definition: bm.h:744
bm::bvector::any_range
bool any_range(size_type left, size_type right) const BMNOEXCEPT
Returns true if any bits in the range are 1s (non-empty interval) Function uses closed interval [left...
Definition: bm.h:2865
bm::bvector::set_bit_conditional
bool set_bit_conditional(size_type n, bool val, bool condition)
Sets bit n only if current value equals the condition.
Definition: bm.h:3590
bm::gap_is_all_zero
BMFORCEINLINE bool gap_is_all_zero(const bm::gap_word_t *BMRESTRICT buf) BMNOEXCEPT
Checks if GAP block is all-zero.
Definition: bmfunc.h:1072
bm::bvector::get_blocks_manager
blocks_manager_type & get_blocks_manager() BMNOEXCEPT
get access to memory manager (internal) Use only if you are BitMagic library
Definition: bm.h:1932
bm::bvector::reference::reference
reference(const reference &ref) BMNOEXCEPT
Definition: bm.h:153
bm::operator-
bvector< Alloc > operator-(const bvector< Alloc > &bv1, const bvector< Alloc > &bv2)
Definition: bm.h:2111
bm::operation
operation
Bit operations.
Definition: bmconst.h:175
bm::bvector::insert
bool insert(size_type n, bool value)
Insert bit into specified position All the vector content after insert position is shifted right.
Definition: bm.h:4378
bm::bvector::find
bool find(size_type &pos) const BMNOEXCEPT
Finds index of first 1 bit.
Definition: bm.h:4035
bm::operation_deserializer
Deserializer, performs logical operations between bit-vector and serialized bit-vector.
Definition: bmserial.h:824
bmalloc.h
Default SIMD friendly allocator.
bm::bvector::bulk_insert_iterator::operator*
bulk_insert_iterator & operator*()
Definition: bm.h:556
bm::bvector::clear
void clear(const size_type *ids, size_type ids_size, bm::sort_order so=bm::BM_UNKNOWN)
clear list of bits in this bitset
Definition: bm.h:3546
bm::bvector::clear
void clear(bool free_mem=false)
Clears every bit in the bitvector.
Definition: bm.h:1219
bmdef.h
Definitions(internal)
bm::bvector::insert_iterator::get_bvector
bvector_type * get_bvector() const
Definition: bm.h:435
bm::bvector::operator|=
void operator|=(const bvector< Alloc > &bv)
Definition: bm.h:1004
bm::bvector::bvector
bvector(const bvector< Alloc > &bvect, size_type left, size_type right)
Copy constructor for range copy [left..right].
Definition: bm.h:893
bm::bvector::combine_operation_with_block
void combine_operation_with_block(block_idx_type nb, const bm::word_t *arg_blk, bool arg_gap, bm::operation opcode)
Definition: bm.h:4792
bm::bvector::iterator_base::block_descr::gap_
dgap_descr gap_
DGAP block related info.
Definition: bm.h:356
bm::gap_operation_and
BMFORCEINLINE gap_word_t * gap_operation_and(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2, gap_word_t *BMRESTRICT tmp_buf, unsigned &dsize) BMNOEXCEPT
GAP AND operation.
Definition: bmfunc.h:5646
bm::bvector::insert_iterator::bvect_
bvector_type * bvect_
Definition: bm.h:438
bm::bvector::bulk_insert_iterator::size_type
bvector_type::size_type size_type
Definition: bm.h:468
bm::bvector::iterator_base::operator>
bool operator>(const iterator_base &it) const BMNOEXCEPT
Definition: bm.h:265
bm::bit_block_shift_r1_unr
bool bit_block_shift_r1_unr(bm::word_t *BMRESTRICT block, bm::word_t *BMRESTRICT empty_acc, bm::word_t co_flag) BMNOEXCEPT
Right bit-shift of bit-block by 1 bit (loop unrolled)
Definition: bmfunc.h:4955
bm::bvector::resize
void resize(size_type new_size)
Change size of the bvector.
Definition: bm.h:2256
bm::bvector::reference
Class reference implements an object for bit assignment.
Definition: bm.h:145
bm::bvector::iterator_base::block_type_
unsigned block_type_
Type of block. 0-Bit, 1-GAP.
Definition: bm.h:349
bm::bit_operation_sub
bm::word_t * bit_operation_sub(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
bitblock SUB operation.
Definition: bmfunc.h:7182
bm::bvector::find_range
bool find_range(size_type &first, size_type &last) const BMNOEXCEPT
Finds dynamic range of bit-vector [first, last].
Definition: bm.h:4081
bm::bit_find_last
unsigned bit_find_last(const bm::word_t *BMRESTRICT block, unsigned *BMRESTRICT last) BMNOEXCEPT
BIT block find the last set bit (backward search)
Definition: bmfunc.h:7518
bm::gap_test_unr
unsigned gap_test_unr(const T *BMRESTRICT buf, const unsigned pos) BMNOEXCEPT
Tests if bit = pos is true. Analog of bm::gap_test with SIMD unrolling.
Definition: bmfunc.h:1298
bm::block_any_range
bool block_any_range(const bm::word_t *const BMRESTRICT block, unsigned left, unsigned right) BMNOEXCEPT
Returns "true" if one bit is set in the block [left, right] Function check for block varieties.
Definition: bmfunc.h:5563
bm::BM_OR
@ BM_OR
Definition: bmconst.h:178
bm::gap_max_bits
const unsigned gap_max_bits
Definition: bmconst.h:80
bm::bvector::shift_right
bool shift_right()
Shift right by 1 bit, fill with zero return carry out.
Definition: bm.h:4360
bm::bvector::invert
bvector< Alloc > & invert()
Invert/NEG all bits It should be noted, invert is affected by size() if size is set - it only inverts...
Definition: bm.h:2987
bm::improve_gap_levels
bool improve_gap_levels(const T *length, const T *length_end, T *glevel_len) BMNOEXCEPT
Finds optimal gap blocks lengths.
Definition: bmfunc.h:7932
bm::bvector::test
bool test(size_type n) const BMNOEXCEPT
returns true if bit n is set and false is bit n is 0.
Definition: bm.h:1440
bm::bvector::iterator_base::operator==
bool operator==(const iterator_base &it) const BMNOEXCEPT
Definition: bm.h:245
bm::gap_add_to_bitset
void gap_add_to_bitset(unsigned *BMRESTRICT dest, const T *BMRESTRICT pcurr, unsigned len) BMNOEXCEPT
Adds(OR) GAP block to bitblock.
Definition: bmfunc.h:3436
bm::bvector::bvector
bvector(std::initializer_list< size_type > il)
Brace constructor.
Definition: bm.h:940
IS_VALID_ADDR
#define IS_VALID_ADDR(addr)
Definition: bmdef.h:152
bm::bvector::get_allocator
Alloc get_allocator() const
Definition: bm.h:1016
bm::bvector::mem_pool_guard::mem_pool_guard
mem_pool_guard() BMNOEXCEPT
Definition: bm.h:774
bm::bvector::enumerator::value
size_type value() const BMNOEXCEPT
Get current position (value)
Definition: bm.h:641
bm::bvector::insert_iterator::reference
void reference
Definition: bm.h:388
bm::block_is_all_one_range
bool block_is_all_one_range(const bm::word_t *const BMRESTRICT block, unsigned left, unsigned right) BMNOEXCEPT
Returns "true" if all bits are 1 in the block [left, right] Function check for block varieties.
Definition: bmfunc.h:5303
FULL_BLOCK_REAL_ADDR
#define FULL_BLOCK_REAL_ADDR
Definition: bmdef.h:148
bm::bvector::clear_range
void clear_range(size_type left, size_type right)
Sets all bits to zero in the specified closed interval [left,right] Interval must be inside the bvect...
Definition: bm.h:1174
bm::bvector::blocks_count
rs_index< allocator_type > blocks_count
Definition: bm.h:830
bm::gap_bfind
unsigned gap_bfind(const T *BMRESTRICT buf, unsigned pos, unsigned *BMRESTRICT is_set) BMNOEXCEPT
Definition: bmfunc.h:1220
bm::bvector::recalc_count
size_type recalc_count() BMNOEXCEPT
Definition: bm.h:1415
bm::bvector::inserter
insert_iterator inserter()
Definition: bm.h:1245
bm::bvector::clear_bit_no_check
void clear_bit_no_check(size_type n)
Clears bit n without precondiion checks.
Definition: bm.h:1211
bm::bvector::count_to_test
size_type count_to_test(size_type n, const rs_index_type &rs_idx) const BMNOEXCEPT
popcount in [0..right] range if test(right) == true
Definition: bm.h:2587
bm::bvector::end
enumerator end() const
Returns enumerator pointing on the next bit after the last.
Definition: bm.h:1776
bm::bit_block_find
unsigned bit_block_find(const bm::word_t *BMRESTRICT block, unsigned nbit, unsigned *BMRESTRICT pos) BMNOEXCEPT
Searches for the next 1 bit in the BIT block.
Definition: bmfunc.h:7467
bm::bit_operation_and
bm::word_t * bit_operation_and(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
bitblock AND operation.
Definition: bmfunc.h:6476
bm::bvector::reference::operator!
bool operator!() const BMNOEXCEPT
Definition: bm.h:207
bm::bvector::reference::operator~
bool operator~() const BMNOEXCEPT
Definition: bm.h:213
bm::bvector::bit_xor
bm::bvector< Alloc > & bit_xor(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode)
3-operand XOR : this := bv1 XOR bv2
Definition: bm.h:4906
bm::bvector::bulk_insert_iterator::bulk_insert_iterator
bulk_insert_iterator(const bulk_insert_iterator &iit)
Definition: bm.h:494
bm::bvector::iterator_base::operator>=
bool operator>=(const iterator_base &it) const BMNOEXCEPT
Definition: bm.h:270
bm::set_block_shift
const unsigned set_block_shift
Definition: bmconst.h:55
bm::gap_limit
unsigned gap_limit(const T *BMRESTRICT buf, const T *BMRESTRICT glevel_len) BMNOEXCEPT
Returs GAP block capacity limit.
Definition: bmfunc.h:1130
bm::bvector::count_blocks
block_idx_type count_blocks(unsigned *arr) const BMNOEXCEPT
Computes bitcount values for all bvector blocks.
Definition: bm.h:2405
bm::bvector::rank
size_type rank(size_type n, const rs_index_type &rs_idx) const BMNOEXCEPT
Returns rank of specified bit position (same as count_to())
Definition: bm.h:1371
bmsimd.h
SIMD target version definitions.
bm::bit_block_erase
void bit_block_erase(bm::word_t *block, unsigned bitpos, bool carry_over) BMNOEXCEPT
erase bit from position and shift the rest right with carryover
Definition: bmfunc.h:5033
bm::bvector::iterator_base::bitblock_descr::pos
size_type pos
Last bit position decode before.
Definition: bm.h:333
bm
Definition: bm.h:76
bm::bvector::block_idx_type
blocks_manager_type::block_idx_type block_idx_type
Definition: bm.h:113
BM_AND_OP
#define BM_AND_OP(x)
Definition: bm.h:5364
IS_FULL_BLOCK
#define IS_FULL_BLOCK(addr)
Definition: bmdef.h:153
bm::bvector::merge
void merge(bm::bvector< Alloc > &bvect)
Merge/move content from another vector.
Definition: bm.h:4724
bm::sse42_test_all_zero_wave2
BMFORCEINLINE bool sse42_test_all_zero_wave2(const void *ptr0, const void *ptr1)
check if 2 waves of pointers are all NULL
Definition: bmsse4.h:606
bm::sort_order
sort_order
Sort order declaration.
Definition: bmconst.h:188
bm::gap_operation_xor
gap_word_t * gap_operation_xor(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2, gap_word_t *BMRESTRICT tmp_buf, unsigned &dsize) BMNOEXCEPT
GAP XOR operation.
Definition: bmfunc.h:5712
bm::bvector::opt_free_0
@ opt_free_0
Free unused 0 blocks.
Definition: bm.h:132
bm::bvector::optimize_gap_size
void optimize_gap_size()
Optimize sizes of GAP blocks.
Definition: bm.h:3117
bm::bvector::operator[]
reference operator[](size_type n)
Definition: bm.h:986
bm::bvector::bulk_insert_iterator::flush
void flush()
Definition: bm.h:563
bm::operation_functions::gap_op_to_bit
static gap_operation_to_bitset_func_type gap_op_to_bit(unsigned i)
Definition: bmfunc.h:8360
bm::bvector::counted_enumerator::operator=
counted_enumerator & operator=(const enumerator &en) BMNOEXCEPT
Definition: bm.h:728
bm::bvector::insert_iterator::pointer
void pointer
Definition: bm.h:387
bm::bvector::~bvector
~bvector() BMNOEXCEPT
Definition: bm.h:906
bm::bvector::build_rs_index
void build_rs_index(rs_index_type *rs_idx, bvector< Alloc > *bv_blocks=0) const
compute running total of all blocks in bit vector (rank-select index)
Definition: bm.h:2290
bm::bvector::combine_operation
void combine_operation(const bm::bvector< Alloc > &bvect, bm::operation opcode)
perform a set-algebra operation by operation code
Definition: bm.h:5529
bm::bvector::get_next
size_type get_next(size_type prev) const BMNOEXCEPT
Finds the number of the next bit ON.
Definition: bm.h:1540
bm::set_block_size_op
const unsigned set_block_size_op
Definition: bmconst.h:129
bm::block_find_first_diff
bool block_find_first_diff(const bm::word_t *BMRESTRICT blk, const bm::word_t *BMRESTRICT arg_blk, unsigned *BMRESTRICT pos) BMNOEXCEPT
Find first bit which is different between two blocks (GAP or bit)
Definition: bmfunc.h:8030
bm::bvector::first
enumerator first() const
Returns enumerator pointing on the first non-zero bit.
Definition: bm.h:1770
bm::bvector::iterator_base::operator!=
bool operator!=(const iterator_base &it) const BMNOEXCEPT
Definition: bm.h:250
bm::BM_XOR
@ BM_XOR
Definition: bmconst.h:180
bm::bitscan_wave
unsigned short bitscan_wave(const bm::word_t *BMRESTRICT w_ptr, unsigned char *BMRESTRICT bits) BMNOEXCEPT
Unpacks word wave (Nx 32-bit words)
Definition: bmfunc.h:8433
bm::bvector::bvector
bvector(const bvector< Alloc > &bvect)
Copy constructor.
Definition: bm.h:882
bm::bvector::bulk_insert_iterator
Output iterator iterator designed to set "ON" bits based on input sequence of integers.
Definition: bm.h:461
bm::bvector::insert_iterator::operator=
insert_iterator & operator=(const insert_iterator &ii)
Definition: bm.h:405
bm::bvector::clear_bit
bool clear_bit(size_type n)
Clears bit n.
Definition: bm.h:1205
bm::bvector::iterator_base::bitblock_descr::ptr
const bm::word_t * ptr
Word pointer.
Definition: bm.h:329
bm::bvector::iterator_base::block_descr
Definition: bm.h:353
bm::bit_block_and_2way
bm::id64_t bit_block_and_2way(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2, bm::id64_t digest) BMNOEXCEPT
digest based bit-block AND
Definition: bmfunc.h:6101
bm::bit_block_xor
bm::id64_t bit_block_xor(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Plain bitblock XOR operation. Function does not analyse availability of source and destination blocks...
Definition: bmfunc.h:7240
bm::set_word_mask
const unsigned set_word_mask
Definition: bmconst.h:72
bm::bvector::bulk_insert_iterator::reference
void reference
Definition: bm.h:472
bm::bit_block_copy
void bit_block_copy(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src) BMNOEXCEPT
Bitblock copy operation.
Definition: bmfunc.h:5898
bm::bit_block_calc_count_to
bm::id_t bit_block_calc_count_to(const bm::word_t *block, bm::word_t right) BMNOEXCEPT
Definition: bmfunc.h:4767
bm::word_t
unsigned int word_t
Definition: bmconst.h:38
bm::bvector::iterator_base::block_
const bm::word_t * block_
Block pointer.(NULL-invalid)
Definition: bm.h:348
bm::bvector::get_first
size_type get_first() const BMNOEXCEPT
find first 1 bit in vector. Function may return 0 and this requires an extra check if bit 0 is actual...
Definition: bm.h:1531
bm::bvector::blocks_manager_type
blocks_manager< Alloc > blocks_manager_type
Definition: bm.h:112
bm::gap_len_table
Default GAP lengths table.
Definition: bmconst.h:374
bm::gap_length
BMFORCEINLINE bm::gap_word_t gap_length(const bm::gap_word_t *BMRESTRICT buf) BMNOEXCEPT
Returs GAP block length.
Definition: bmfunc.h:1098
BLOCK_ADDR_SAN
#define BLOCK_ADDR_SAN(addr)
Definition: bmdef.h:151
bm::bit_block_calc_count_range
bm::id_t bit_block_calc_count_range(const bm::word_t *block, bm::word_t left, bm::word_t right) BMNOEXCEPT
Definition: bmfunc.h:4698
bm::bvector::extract_next
size_type extract_next(size_type prev)
Finds the number of the next bit ON and sets it to 0.
Definition: bm.h:1550
bm::bvector::iterator_base::dgap_descr::ptr
const gap_word_t * ptr
Word pointer.
Definition: bm.h:341
bm::bit_block_or_2way
bool bit_block_or_2way(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2) BMNOEXCEPT
2 way (target := source1 | source2) bitblock OR operation.
Definition: bmfunc.h:6786
bm::bvector::size_type
bm::id_t size_type
Definition: bm.h:117
bm::bvector::reference::operator==
bool operator==(const reference &ref) const BMNOEXCEPT
Definition: bm.h:177
bm::bvector::counted_enumerator
Constant iterator designed to enumerate "ON" bits counted_enumerator keeps bitcount,...
Definition: bm.h:715
bm::BM_SUB
@ BM_SUB
Definition: bmconst.h:179
bm::bvector::enumerator::enumerator
enumerator(const bvector< Alloc > *bv, size_type pos) BMNOEXCEPT
Construct enumerator for bit vector.
Definition: bm.h:630
bm::gap_shift_r1
bool gap_shift_r1(T *BMRESTRICT buf, unsigned co_flag, unsigned *BMRESTRICT new_len) BMNOEXCEPT
Right shift GAP block by 1 bit.
Definition: bmfunc.h:2897
bm::bvector::rank_corrected
size_type rank_corrected(size_type n, const rs_index_type &rs_idx) const BMNOEXCEPT
Returns rank corrceted by the requested border value (as -1)
Definition: bm.h:2644
bm::bvector::insert_iterator::difference_type
void difference_type
Definition: bm.h:386
bm::bvector::insert_iterator::insert_iterator
insert_iterator(const insert_iterator &iit)
Definition: bm.h:399
bm::bvector::set_bit_and
bool set_bit_and(size_type n, bool val=true)
Sets bit n using bit AND with the provided value.
Definition: bm.h:3604
bm::bvector::iterator_base::operator<
bool operator<(const iterator_base &it) const BMNOEXCEPT
Definition: bm.h:255
bm::bvector::insert_iterator::operator*
insert_iterator & operator*()
Definition: bm.h:429
bm::bvector::set_bit
bool set_bit(size_type n, bool val=true)
Sets bit n.
Definition: bm.h:3617
bm::bvector::enumerator::go_up
bool go_up() BMNOEXCEPT
Advance enumerator to the next available bit.
Definition: bm.h:6744
bm::bvector::enumerator::advance
bool advance() BMNOEXCEPT
Definition: bm.h:662
bit_visitor_callback_type
int(* bit_visitor_callback_type)(void *handle_ptr, bm::id_t bit_idx)
Callback type to visit (callback style) bits in bit-vector(s)
Definition: bm.h:71
bm::bvector::optimize
void optimize(bm::word_t *temp_block=0, optmode opt_mode=opt_compress, statistics *stat=0)
Optimize memory bitvector's memory allocation.
Definition: bm.h:3071
bm::for_each_nzblock
void for_each_nzblock(T ***root, unsigned size1, F &f)
Definition: bmfunc.h:1382
bm::bvector::reference::reference
reference(bvector< Alloc > &bv, size_type position) BMNOEXCEPT
Definition: bm.h:148
bm::bvector::iterator_base::invalidate
void invalidate() BMNOEXCEPT
Turns iterator into an invalid state.
Definition: bm.h:286
bm::bv_statistics
Structure with statistical information about memory allocation footprint, serialization projection,...
Definition: bmfunc.h:54
bm::bit_block_sub_2way
bm::id64_t bit_block_sub_2way(bm::word_t *BMRESTRICT dst, const bm::word_t *BMRESTRICT src1, const bm::word_t *BMRESTRICT src2, bm::id64_t digest) BMNOEXCEPT
digest based bitblock SUB (AND NOT) operation (3 operand)
Definition: bmfunc.h:7115
bm::bvector::allocation_policy::allocation_policy
allocation_policy(bm::strategy s=BM_BIT, const gap_word_t *glevels=bm::gap_len_table< true >::_len) BMNOEXCEPT
Definition: bm.h:824
bm::bvector::count_to
size_type count_to(size_type n, const rs_index_type &rs_idx) const BMNOEXCEPT
Returns count of 1 bits (population) in [0..right] range.
Definition: bm.h:2533
bm::bvector::bvector
bvector(bvector< Alloc > &&bvect) BMNOEXCEPT
Move constructor.
Definition: bm.h:930
bm::bvector::reference::operator=
const reference & operator=(const reference &ref) const
Definition: bm.h:165
bm::bvector::reference::operator^=
const reference & operator^=(bool value) const
Definition: bm.h:200
bm::sse42_test_all_eq_wave2
BMFORCEINLINE bool sse42_test_all_eq_wave2(const void *ptr0, const void *ptr1)
check if wave of 2 pointers are the same (null or FULL)
Definition: bmsse4.h:619
bm::sse42_test_all_zero_wave
BMFORCEINLINE bool sse42_test_all_zero_wave(const void *ptr)
check if wave of pointers is all NULL
Definition: bmsse4.h:595
bm::gap_levels
const unsigned gap_levels
Definition: bmconst.h:84
bm::bvector::statistics
Statistical information about bitset's memory allocation details.
Definition: bm.h:121
bm::gap_operation_or
gap_word_t * gap_operation_or(const gap_word_t *BMRESTRICT vect1, const gap_word_t *BMRESTRICT vect2, gap_word_t *BMRESTRICT tmp_buf, unsigned &dsize) BMNOEXCEPT
GAP OR operation.
Definition: bmfunc.h:5790
bm::bvector::bulk_insert_iterator::sorted_
bm::sort_order sorted_
sort order hint
Definition: bm.h:591
bm::bit_block_set
void bit_block_set(bm::word_t *BMRESTRICT dst, bm::word_t value) BMNOEXCEPT
Bitblock memset operation.
Definition: bmfunc.h:3841
bm::bvector::enumerator::difference_type
unsigned difference_type
Definition: bm.h:606
bm::bvector::iterator_base::bv_
bm::bvector< Alloc > * bv_
Pointer on parent bitvector.
Definition: bm.h:346
bm::bvector::combine_operation_or
void combine_operation_or(const bm::bvector< Alloc > &bvect)
perform a set-algebra operation OR
Definition: bm.h:5206
bm::bvector::is_all_one_range
bool is_all_one_range(size_type left, size_type right) const BMNOEXCEPT
Returns true if all bits in the range are 1s (saturated interval) Function uses closed interval [left...
Definition: bm.h:2781
bm::bvector::operator-=
void operator-=(const bvector< Alloc > &bv)
Definition: bm.h:1005
bm::bvector::reference::flip
reference & flip()
Definition: bm.h:219
bm::bvector::mem_pool_guard::assign_if_not_set
void assign_if_not_set(allocator_pool_type &pool, bvector< Alloc > &bv) BMNOEXCEPT
check if vector has no assigned allocator and set one
Definition: bm.h:789
bm::bvector::find_reverse
bool find_reverse(size_type &pos) const BMNOEXCEPT
Finds last index of 1 bit.
Definition: bm.h:3978