NCBI C++ ToolKit
bm.h
Go to the documentation of this file.

Go to the SVN repository for 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  @return negative return code is recognised as a request to interrupt visiting
69 
70  @ingroup bvector
71  */
72  typedef int (*bit_visitor_callback_type)(void* handle_ptr, bm::id_t bit_idx);
73 #endif
74 }
75 
76 
77 namespace bm
78 {
79 
80 /** @defgroup bmagic BitMagic Library
81  BitMagic C++ Library
82  For more information please visit: http://bitmagic.io
83 */
84 
85 
86 /** @defgroup bvector bvector<> container
87  The Main bvector<> Group
88  bvector<> template: front end of the BitMagic library.
89 
90  @ingroup bmagic
91 */
92 
93 /** @defgroup bvit bvector<> iterators
94  Iterators for compressed bit-vector traversal
95  @ingroup bvector
96 */
97 
98 
99 
100 #ifdef BM64ADDR
102 #else
104 #endif
105 
106 
107 /*!
108  @brief Bitvector
109  Bit-vector container with runtime compression of bits
110 
111  @ingroup bvector
112 */
113 template<class Alloc>
114 class bvector
115 {
116 public:
118  typedef typename allocator_type::allocator_pool_type allocator_pool_type;
122 
123  /** Statistical information about bitset's memory allocation details. */
124  struct statistics : public bv_statistics
125  {};
126 
127  /*!
128  \brief Optimization mode
129  Every next level means additional checks (better compression vs time)
130  \sa optimize
131  */
132  enum optmode
133  {
134  opt_none = 0, ///< no optimization
135  opt_free_0 = 1, ///< Free unused 0 blocks
136  opt_free_01 = 2, ///< Free unused 0 and 1 blocks
137  opt_compress = 3 ///< compress blocks when possible (GAP/prefix sum)
138  };
139 
140 
141  /**
142  @brief Class reference implements an object for bit assignment.
143  Since C++ does not provide with build-in bit type supporting l-value
144  operations we have to emulate it.
145 
146  @ingroup bvector
147  */
148  class reference
149  {
150  public:
152  : bv_(bv),
153  position_(position)
154  {}
155 
157  : bv_(ref.bv_),
158  position_(ref.position_)
159  {
160  bv_.set(position_, ref.bv_.get_bit(position_));
161  }
162 
163  operator bool() const BMNOEXCEPT
164  {
165  return bv_.get_bit(position_);
166  }
167 
168  const reference& operator=(const reference& ref) const
169  {
170  bv_.set(position_, (bool)ref);
171  return *this;
172  }
173 
174  const reference& operator=(bool value) const BMNOEXCEPT
175  {
176  bv_.set(position_, value);
177  return *this;
178  }
179 
180  bool operator==(const reference& ref) const BMNOEXCEPT
181  {
182  return bool(*this) == bool(ref);
183  }
184 
185  /*! Bitwise AND. Performs operation: bit = bit AND value */
186  const reference& operator&=(bool value) const
187  {
188  bv_.set_bit_and(position_, value);
189  return *this;
190  }
191 
192  /*! Bitwise OR. Performs operation: bit = bit OR value */
193  const reference& operator|=(bool value) const
194  {
195  if (value != bv_.get_bit(position_))
196  {
197  bv_.set_bit(position_);
198  }
199  return *this;
200  }
201 
202  /*! Bitwise exclusive-OR (XOR). Performs operation: bit = bit XOR value */
203  const reference& operator^=(bool value) const
204  {
205  bv_.set(position_, value != bv_.get_bit(position_));
206  return *this;
207  }
208 
209  /*! Logical Not operator */
211  {
212  return !bv_.get_bit(position_);
213  }
214 
215  /*! Bit Not operator */
217  {
218  return !bv_.get_bit(position_);
219  }
220 
221  /*! Negates the bit value */
223  {
224  bv_.flip(position_);
225  return *this;
226  }
227 
228  private:
229  bvector<Alloc>& bv_; //!< Reference variable on the parent.
230  size_type position_; //!< Position in the parent bitvector.
231  };
232 
233  typedef bool const_reference;
234 
235  /*!
236  @brief Base class for all iterators.
237  @ingroup bvit
238  */
240  {
241  friend class bvector;
242  public:
244  : bv_(0), position_(bm::id_max), block_(0), block_type_(0),
245  block_idx_(0)
246  {}
247 
248  bool operator==(const iterator_base& it) const BMNOEXCEPT
249  {
250  return (position_ == it.position_) && (bv_ == it.bv_);
251  }
252 
253  bool operator!=(const iterator_base& it) const BMNOEXCEPT
254  {
255  return ! operator==(it);
256  }
257 
258  bool operator < (const iterator_base& it) const BMNOEXCEPT
259  {
260  return position_ < it.position_;
261  }
262 
263  bool operator <= (const iterator_base& it) const BMNOEXCEPT
264  {
265  return position_ <= it.position_;
266  }
267 
268  bool operator > (const iterator_base& it) const BMNOEXCEPT
269  {
270  return position_ > it.position_;
271  }
272 
273  bool operator >= (const iterator_base& it) const BMNOEXCEPT
274  {
275  return position_ >= it.position_;
276  }
277 
278  /**
279  \fn bool bm::bvector::iterator_base::valid() const
280  \brief Checks if iterator is still valid. Analog of != 0 comparison for pointers.
281  \returns true if iterator is valid.
282  */
283  bool valid() const BMNOEXCEPT { return position_ != bm::id_max; }
284 
285  /**
286  \fn bool bm::bvector::iterator_base::invalidate()
287  \brief Turns iterator into an invalid state.
288  */
290  { position_ = bm::id_max; block_type_ = ~0u;}
291 
292  /** \brief Compare FSMs for testing purposes
293  \internal
294  */
295  bool compare_state(const iterator_base& ib) const BMNOEXCEPT
296  {
297  if (this->bv_ != ib.bv_) return false;
298  if (this->position_ != ib.position_) return false;
299  if (this->block_ != ib.block_) return false;
300  if (this->block_type_ != ib.block_type_) return false;
301  if (this->block_idx_ != ib.block_idx_) return false;
302 
303  const block_descr& bd = this->bdescr_;
304  const block_descr& ib_db = ib.bdescr_;
305 
306  if (this->block_type_ == 0) // bit block
307  {
308  if (bd.bit_.ptr != ib_db.bit_.ptr) return false;
309  if (bd.bit_.idx != ib_db.bit_.idx) return false;
310  if (bd.bit_.cnt != ib_db.bit_.cnt) return false;
311  if (bd.bit_.pos != ib_db.bit_.pos) return false;
312  for (unsigned i = 0; i < bd.bit_.cnt; ++i)
313  {
314  if (bd.bit_.bits[i] != ib_db.bit_.bits[i]) return false;
315  }
316  }
317  else // GAP block
318  {
319  if (bd.gap_.ptr != ib_db.gap_.ptr) return false;
320  if (bd.gap_.gap_len != ib_db.gap_.gap_len) return false;
321  }
322  return true;
323  }
324 
325  public:
326 
327  /** Bit-block descriptor
328  @internal
329  */
331  {
332  const bm::word_t* ptr; //!< Word pointer.
333  unsigned char bits[set_bitscan_wave_size*32]; //!< bit list
334  unsigned short idx; //!< Current position in the bit list
335  unsigned short cnt; //!< Number of ON bits
336  size_type pos; //!< Last bit position decode before
337  };
338 
339  /** Information about current DGAP block.
340  @internal
341  */
342  struct dgap_descr
343  {
344  const gap_word_t* ptr; //!< Word pointer.
345  gap_word_t gap_len; //!< Current dgap length.
346  };
347 
348  protected:
349  bm::bvector<Alloc>* bv_; //!< Pointer on parent bitvector
350  size_type position_; //!< Bit position (bit idx)
351  const bm::word_t* block_; //!< Block pointer.(NULL-invalid)
352  unsigned block_type_; //!< Type of block. 0-Bit, 1-GAP
353  block_idx_type block_idx_; //!< Block index
354 
355  /*! Block type dependent information for current block. */
357  {
358  bitblock_descr bit_; //!< BitBlock related info.
359  dgap_descr gap_; //!< DGAP block related info.
361  };
362 
363  /*!
364  @brief Output iterator iterator designed to set "ON" bits based on
365  input sequence of integers (bit indeces).
366 
367  STL container can be converted to bvector using this iterator
368  Insert iterator guarantees the vector will be dynamically resized
369  (set_bit does not do that).
370 
371  @note
372  If you have many bits to set it is a good idea to use output iterator
373  instead of explicitly calling set, because iterator may implement
374  some performance specific tricks to make sure bulk insert is fast.
375 
376  @sa bulk_insert_iterator
377 
378  @ingroup bvit
379  */
381  {
382  friend class bulk_insert_iterator;
383  public:
384 #ifndef BM_NO_STL
385  typedef std::output_iterator_tag iterator_category;
386 #endif
389  typedef void difference_type;
390  typedef void pointer;
391  typedef void reference;
392 
394 
396  : bvect_(&bvect),
397  max_bit_(bvect.size())
398  {
399  bvect_->init();
400  }
401 
403  : bvect_(iit.bvect_),
404  max_bit_(iit.max_bit_)
405  {
406  }
407 
409  {
410  bvect_ = ii.bvect_; max_bit_ = ii.max_bit_;
411  return *this;
412  }
413 
415  {
417  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
418 
419  if (n >= max_bit_)
420  {
421  max_bit_ = n;
422  if (n >= bvect_->size())
423  {
424  size_type new_size = (n == bm::id_max) ? bm::id_max : n + 1;
425  bvect_->resize(new_size);
426  }
427  }
429  return *this;
430  }
431  /*! Returns *this without doing anything (no-op) */
432  insert_iterator& operator*() { return *this; }
433  /*! Returns *this. This iterator does not move (no-op) */
434  insert_iterator& operator++() { return *this; }
435  /*! Returns *this. This iterator does not move (no-op)*/
436  insert_iterator& operator++(int) { return *this; }
437 
438  bvector_type* get_bvector() const { return bvect_; }
439 
440  protected:
443  };
444 
445 
446  /*!
447  @brief Output iterator iterator designed to set "ON" bits based on
448  input sequence of integers.
449 
450  STL container can be converted to bvector using this iterator
451  Insert iterator guarantees the vector will be dynamically resized
452  (set_bit does not do that).
453 
454  The difference from the canonical insert iterator, is that
455  bulk insert implements internal buffering, which needs
456  to flushed (or flushed automatically when goes out of scope).
457  Buffering creates a delayed effect, which needs to be
458  taken into account.
459 
460  @sa insert_iterator
461 
462  @ingroup bvit
463  */
465  {
466  public:
467 #ifndef BM_NO_STL
468  typedef std::output_iterator_tag iterator_category;
469 #endif
473  typedef void difference_type;
474  typedef void pointer;
475  typedef void reference;
476 
478  : bvect_(0), buf_(0), buf_size_(0), sorted_(BM_UNKNOWN) {}
479 
481  {
482  flush();
483  if (buf_)
484  bvect_->blockman_.get_allocator().free_bit_block((bm::word_t*)buf_);
485  }
486 
489  : bvect_(&bvect), sorted_(so)
490  {
491  bvect_->init();
492 
493  buf_ = (value_type*) bvect_->blockman_.get_allocator().alloc_bit_block();
494  buf_size_ = 0;
495  }
496 
498  : bvect_(iit.bvect_)
499  {
500  buf_ = bvect_->blockman_.get_allocator().alloc_bit_block();
501  buf_size_ = iit.buf_size_;
502  sorted_ = iit.sorted_;
503  ::memcpy(buf_, iit.buf_, buf_size_ * sizeof(*buf_));
504  }
505 
506  bulk_insert_iterator(const insert_iterator& iit)
507  : bvect_(iit.get_bvector())
508  {
509  buf_ = (value_type*) bvect_->blockman_.get_allocator().alloc_bit_block();
510  buf_size_ = 0;
512  }
513 
515  : bvect_(iit.bvect_)
516  {
517  buf_ = iit.buf_; iit.buf_ = 0;
518  buf_size_ = iit.buf_size_;
519  sorted_ = iit.sorted_;
520  }
521 
523  {
524  bvect_ = ii.bvect_;
525  if (!buf_)
526  buf_ = bvect_->allocate_tempblock();
527  buf_size_ = ii.buf_size_;
528  ::memcpy(buf_, ii.buf_, buf_size_ * sizeof(*buf_));
529  sorted_ = ii.sorted_;
530  return *this;
531  }
532 
534  {
535  bvect_ = ii.bvect_;
536  if (buf_)
537  bvect_->free_tempblock(buf_);
538  buf_ = ii.buf_; ii.buf_ = 0;
539  buf_size_ = ii.buf_size_;
540  sorted_ = ii.sorted_;
541  return *this;
542  }
543 
545  {
547  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
548 
549  if (buf_size_ == buf_size_max())
550  {
552  buf_size_ = 0;
553  }
554  buf_[buf_size_++] = n;
555  return *this;
556  }
557 
558  /*! Returns *this without doing anything (no-op) */
559  bulk_insert_iterator& operator*() { return *this; }
560  /*! Returns *this. This iterator does not move (no-op) */
561  bulk_insert_iterator& operator++() { return *this; }
562  /*! Returns *this. This iterator does not move (no-op)*/
563  bulk_insert_iterator& operator++(int) { return *this; }
564 
565  /*! Flush the internal buffer into target bvector */
566  void flush()
567  {
568  BM_ASSERT(bvect_);
569  if (buf_size_)
570  {
572  buf_size_ = 0;
573  }
574  bvect_->sync_size();
575  }
576 
578 
579  protected:
580  static
582  {
583  #ifdef BM64ADDR
584  return bm::set_block_size / 2;
585  #else
586  return bm::set_block_size;
587  #endif
588  }
589 
590  protected:
591  bvector_type* bvect_; ///< target bvector
592  size_type* buf_; ///< bulk insert buffer
593  size_type buf_size_; ///< current buffer size
594  bm::sort_order sorted_; ///< sort order hint
595  };
596 
597 
598 
599  /*! @brief Constant iterator designed to enumerate "ON" bits
600  @ingroup bvit
601  */
602  class enumerator : public iterator_base
603  {
604  public:
605 #ifndef BM_NO_STL
606  typedef std::input_iterator_tag iterator_category;
607 #endif
609  typedef unsigned difference_type;
610  typedef unsigned* pointer;
611  typedef unsigned& reference;
612 
613  public:
615  {}
616 
617  /*! @brief Construct enumerator associated with a vector.
618  Important: This construction creates unpositioned iterator with status
619  valid() == false. It can be re-positioned using go_first() or go_to().
620  @sa go_to
621  */
623  : iterator_base()
624  {
625  this->bv_ = const_cast<bvector<Alloc>*>(bv);
626  }
627 
628  /*! @brief Construct enumerator for bit vector
629  @param bv bit-vector reference
630  @param pos bit position in the vector
631  if position is 0, it finds the next 1 or becomes not valid
632  (en.valid() == false)
633  */
635  : iterator_base()
636  {
637  this->bv_ = const_cast<bvector<Alloc>*>(&bv);
638  go_to(pos);
639  }
640 
641 
642  /*! @brief Construct enumerator for bit vector
643  @param bv bit-vector pointer
644  @param pos bit position in the vector
645  if position is 0, it finds the next 1 or becomes not valid
646  (en.valid() == false)
647  */
649  : iterator_base()
650  {
651  this->bv_ = const_cast<bvector<Alloc>*>(bv);
652  this->go_to(pos);
653  }
654 
655  /*! \brief Get current position (value) */
657 
658  /*! \brief Get current position (value) */
659  size_type value() const BMNOEXCEPT { return this->position_; }
660 
661  /*! \brief Advance enumerator forward to the next available bit */
662  enumerator& operator++() BMNOEXCEPT { this->go_up(); return *this; }
663 
664  /*! \brief Advance enumerator forward to the next available bit.
665  Possibly do NOT use this operator it is slower than the pre-fix increment.
666  */
667  enumerator operator++(int) BMNOEXCEPT
668  {
669  enumerator tmp = *this;
670  this->go_up();
671  return tmp;
672  }
673 
674  /*! \brief Position enumerator to the first available bit */
675  void go_first() BMNOEXCEPT;
676 
677  /*! advance iterator forward by one
678  @return true if advance was successfull and the enumerator is valid
679  */
680  bool advance() BMNOEXCEPT { return this->go_up(); }
681 
682  /*! \brief Advance enumerator to the next available bit */
683  bool go_up() BMNOEXCEPT;
684 
685  /*!
686  @brief Skip to specified relative rank
687  @param rank - number of ON bits to go for (must be: > 0)
688  @return true if skip was successfull and enumerator is valid
689  */
691  {
692  BM_ASSERT(rank);
693  --rank;
694  if (!rank)
695  return this->valid();
696  return skip(rank);
697  }
698 
699  /*!
700  @brief Skip specified number of bits from enumeration
701  @param rank - number of ON bits to skip
702  @return true if skip was successfull and enumerator is valid
703  */
704  bool skip(size_type rank) BMNOEXCEPT;
705 
706  /*!
707  @brief go to a specific position in the bit-vector (or next)
708  */
710 
711  private:
712  typedef typename iterator_base::block_descr block_descr_type;
713 
721 
722  };
723 
724  /*!
725  @brief Constant iterator designed to enumerate "ON" bits
726  counted_enumerator keeps bitcount, ie number of ON bits starting
727  from the position 0 in the bit string up to the currently enumerated bit
728 
729  When increment operator called current position is increased by 1.
730 
731  @ingroup bvit
732  */
734  {
735  public:
736 #ifndef BM_NO_STL
737  typedef std::input_iterator_tag iterator_category;
738 #endif
739  counted_enumerator() BMNOEXCEPT : bit_count_(0){}
740 
742  {
743  bit_count_ = this->valid(); // 0 || 1
744  }
745 
746  counted_enumerator& operator=(const enumerator& en) BMNOEXCEPT
747  {
748  enumerator* me = this;
749  *me = en;
750  if (this->valid())
751  this->bit_count_ = 1;
752  return *this;
753  }
754 
755  counted_enumerator& operator++() BMNOEXCEPT
756  {
757  this->go_up();
758  this->bit_count_ += this->valid();
759  return *this;
760  }
761 
762  counted_enumerator operator++(int)
763  {
764  counted_enumerator tmp(*this);
765  this->go_up();
766  this->bit_count_ += this->valid();
767  return tmp;
768  }
769 
770  /*! @brief Number of bits ON starting from the .
771 
772  Method returns number of ON bits fromn the bit 0 to the current bit
773  For the first bit in bitvector it is 1, for the second 2
774  */
775  size_type count() const BMNOEXCEPT { return bit_count_; }
776  private:
777  /*! Function closed for usage */
778  counted_enumerator& go_to(size_type pos);
779 
780  private:
782  };
783 
784  /*!
785  Resource guard for bvector<>::set_allocator_pool()
786  @ingroup bvector
787  @internal
788  */
789  typedef
791 
792  friend class iterator_base;
793  friend class enumerator;
794  template<class BV> friend class aggregator;
795  template<class BV> friend class operation_deserializer;
796  template<class BV, class DEC> friend class deserializer;
797 
798 public:
799  /*! @brief memory allocation policy
800 
801  Defualt memory allocation policy uses BM_BIT, and standard
802  GAP levels tune-ups
803  */
805  {
808 
811  : strat(s), glevel_len(glevels)
812  {}
813  };
814 
817 
818 public:
819  /*! @name Construction, initialization, assignment */
820  //@{
821 
822  /*!
823  \brief Constructs bvector class
824  \param strat - operation mode strategy,
825  BM_BIT - default strategy, bvector use plain bitset
826  blocks, (performance oriented strategy).
827  BM_GAP - memory effitent strategy, bvector allocates
828  blocks as array of intervals(gaps) and convert blocks
829  into plain bitsets only when enthropy grows.
830  \param glevel_len
831  - pointer on C-style array keeping GAP block sizes.
832  bm::gap_len_table<true>::_len - default value set
833  (use bm::gap_len_table_min<true>::_len for very sparse vectors)
834  (use bm::gap_len_table_nl<true>::_len non-linear GAP growth)
835  \param bv_size
836  - bvector size (number of bits addressable by bvector), bm::id_max means
837  "no limits" (recommended).
838  bit vector allocates this space dynamically on demand.
839  \param alloc - alllocator for this instance
840 
841  \sa bm::gap_len_table bm::gap_len_table_min set_new_blocks_strat
842  */
844  const gap_word_t* glevel_len = bm::gap_len_table<true>::_len,
845  size_type bv_size = bm::id_max,
846  const Alloc& alloc = Alloc())
847  : blockman_(glevel_len, bv_size, alloc),
848  new_blocks_strat_(strat),
849  size_(bv_size)
850  {}
851 
852  /*!
853  \brief Constructs bvector class
854  */
856  strategy strat = BM_BIT,
857  const gap_word_t* glevel_len = bm::gap_len_table<true>::_len,
858  const Alloc& alloc = Alloc())
859  : blockman_(glevel_len, bv_size, alloc),
860  new_blocks_strat_(strat),
861  size_(bv_size)
862  {}
863 
864  /*!
865  \brief Copy constructor
866  */
870  size_(bvect.size_)
871  {}
872 
873  /*!
874  \brief Copy constructor for range copy [left..right]
875  \sa copy_range
876  */
878  : blockman_(bvect.blockman_.glevel_len_, bvect.blockman_.max_bits_, bvect.blockman_.alloc_),
880  size_(bvect.size_)
881  {
882  if (!bvect.blockman_.is_init())
883  return;
884  if (left > right)
885  bm::xor_swap(left, right);
886  copy_range_no_check(bvect, left, right);
887  }
888 
889  /*!
890  \brief Copy-constructor for mutable/immutable initialization
891  */
893  : blockman_(bvect.blockman_.glevel_len_, bvect.blockman_.max_bits_, bvect.blockman_.alloc_),
895  size_(bvect.size_)
896  {
897  if (!bvect.blockman_.is_init())
898  return;
899  if (is_final == bm::finalization::READONLY)
901  else
903  }
904 
905 
907 
908  /*!
909  \brief Explicit post-construction initialization.
910  Must be caled to make sure safe use of *_no_check() methods
911  */
912  void init();
913 
914  /*!
915  \brief Explicit post-construction initialization.
916  Must be caled right after construction strickly before any modificating calls
917  to make sure safe use of *_no_check() methods.
918  This init can do pre-allocation of top level structures.
919 
920  @param top_size - request to do pre-allocation of the top level of a sparse bit-vector tree
921  (can be up to 256 for 32-bit mode)
922  @param alloc_subs - if true also allocates second level structures
923  */
924  void init(unsigned top_size, bool alloc_subs);
925 
926 
927  /*!
928  \brief Copy assignment operator
929  */
931  {
932  this->copy(bvect, bm::finalization::UNDEFINED);
933  return *this;
934  }
935 
936 #ifndef BM_NO_CXX11
937  /*!
938  \brief Move constructor
939  */
941  {
943  size_ = bvect.size_;
945  }
946 
947  /*!
948  \brief Brace constructor
949  */
950  bvector(std::initializer_list<size_type> il)
951  : blockman_(bm::gap_len_table<true>::_len, bm::id_max, Alloc()),
953  size_(bm::id_max)
954  {
955  init();
956  std::initializer_list<size_type>::const_iterator it_start = il.begin();
957  std::initializer_list<size_type>::const_iterator it_end = il.end();
958  for (; it_start < it_end; ++it_start)
959  this->set_bit_no_check(*it_start);
960  }
961 
962  /*!
963  \brief Move assignment operator
964  */
966  {
967  this->move_from(bvect);
968  return *this;
969  }
970 #endif
971 
972  /*!
973  \brief Copy bvector from the argument bvector
974  \param bvect - bit-vector to copy from
975  \param is_final - BM_READONLY - copies as immutable, BM_READWRITE - copies as mutable
976  even if the argument bvect is read-only vector,
977  BM_UNDEFINED - follow the argument type as is
978  */
979  void copy(const bvector<Alloc>& bvect, bm::finalization is_final);
980 
981  /*!
982  \brief Move bvector content from another bvector
983  */
985 
986  /*! \brief Exchanges content of bv and this bvector.
987  */
989 
990  /*! \brief Merge/move content from another vector
991 
992  Merge performs a logical OR operation, but the source vector
993  is not immutable. Source content gets destroyed (memory moved)
994  to create a union of two vectors.
995  Merge operation can be more efficient than OR if argument is
996  a temporary vector.
997 
998  @param bvect - [in, out] - source vector (NOT immutable)
999  */
1001 
1002  //@}
1003 
1005  {
1006  if (n >= size_)
1007  {
1008  size_type new_size = (n == bm::id_max) ? bm::id_max : n + 1;
1009  resize(new_size);
1010  }
1011  return reference(*this, n);
1012  }
1013 
1015  {
1016  BM_ASSERT(n < size_);
1017  return get_bit(n);
1018  }
1019 
1020  void operator &= (const bvector<Alloc>& bv) { bit_and(bv); }
1021  void operator ^= (const bvector<Alloc>& bv) { bit_xor(bv); }
1022  void operator |= (const bvector<Alloc>& bv) { bit_or(bv); }
1023  void operator -= (const bvector<Alloc>& bv) { bit_sub(bv); }
1024 
1025  bool operator < (const bvector<Alloc>& bv) const { return compare(bv)<0; }
1026  bool operator <= (const bvector<Alloc>& bv) const { return compare(bv)<=0; }
1027  bool operator > (const bvector<Alloc>& bv) const { return compare(bv)>0; }
1028  bool operator >= (const bvector<Alloc>& bv) const { return compare(bv) >= 0; }
1029  bool operator == (const bvector<Alloc>& bv) const BMNOEXCEPT { return equal(bv); }
1030  bool operator != (const bvector<Alloc>& bv) const BMNOEXCEPT { return !equal(bv); }
1031 
1032  bvector<Alloc> operator~() const { return bvector<Alloc>(*this).invert(); }
1033 
1035  { return blockman_.get_allocator(); }
1036 
1037  /// Set allocator pool for local (non-th readed)
1038  /// memory cyclic(lots of alloc-free ops) opertations
1039  ///
1041  { blockman_.get_allocator().set_pool(pool_ptr); }
1042 
1043  /// Get curent allocator pool (if set)
1044  /// @return pointer to the current pool or NULL
1046  { return blockman_.get_allocator().get_pool(); }
1047 
1048  // --------------------------------------------------------------------
1049  /*! @name Read-only / immutable vector methods */
1050  //@{
1051 
1052  /// Turn current vector to read-only (immutable vector).
1053  /// After calling this method any modification (non-const methods) will cause undefined behavior
1054  /// (likely crash or assert)
1055  ///
1056  /// \sa is_ro
1057  void freeze();
1058 
1059  /// Returns true if vector is read-only
1061 
1062  //@}
1063 
1064  // --------------------------------------------------------------------
1065  /*! @name Bit access/modification methods */
1066  //@{
1067 
1068  /*!
1069  \brief Sets bit n.
1070  \param n - index of the bit to be set.
1071  \param val - new bit value
1072  \return TRUE if bit was changed
1073  */
1074  bool set_bit(size_type n, bool val = true);
1075 
1076  /*!
1077  \brief Sets bit n using bit AND with the provided value.
1078  \param n - index of the bit to be set.
1079  \param val - new bit value
1080  \return TRUE if bit was changed
1081  */
1082  bool set_bit_and(size_type n, bool val = true);
1083 
1084  /*!
1085  \brief Increment the specified element
1086 
1087  Bit increment rules:
1088  0 + 1 = 1 (no carry over)
1089  1 + 1 = 0 (with carry over returned)
1090 
1091  \param n - index of the bit to be set
1092  \return TRUE if carry over created (1+1)
1093  */
1094  bool inc(size_type n);
1095 
1096 
1097  /*!
1098  \brief Sets bit n only if current value equals the condition
1099  \param n - index of the bit to be set.
1100  \param val - new bit value
1101  \param condition - expected current value
1102  \return TRUE if bit was changed
1103  */
1104  bool set_bit_conditional(size_type n, bool val, bool condition);
1105 
1106  /*!
1107  \brief Sets bit n if val is true, clears bit n if val is false
1108  \param n - index of the bit to be set
1109  \param val - new bit value
1110  \return *this
1111  */
1112  bvector<Alloc>& set(size_type n, bool val = true);
1113 
1114  /*!
1115  \brief Sets every bit in this bitset to 1.
1116  \return *this
1117  */
1119 
1120  /*!
1121  \brief Set list of bits in this bitset to 1.
1122 
1123  Method implements optimized bulk setting of multiple bits at once.
1124  The best results are achieved when the imput comes sorted.
1125  This is equivalent of OR (Set Union), argument set as an array.
1126 
1127  @param ids - pointer on array of indexes to set
1128  @param ids_size - size of the input (ids)
1129  @param so - sort order (use BM_SORTED for faster load)
1130 
1131  @sa keep, clear
1132  */
1133  void set(const size_type* ids, size_type ids_size,
1135 
1136  /*!
1137  \brief Keep list of bits in this bitset, others are cleared
1138 
1139  This is equivalent of AND (Set Intersect), argument set as an array.
1140 
1141  @param ids - pointer on array of indexes to set
1142  @param ids_size - size of the input (ids)
1143  @param so - sort order (use BM_SORTED for faster load)
1144 
1145  @sa set, clear
1146  */
1147  void keep(const size_type* ids, size_type ids_size,
1149 
1150  /*!
1151  \brief clear list of bits in this bitset
1152 
1153  This is equivalent of AND NOT (Set Substract), argument set as an array.
1154 
1155  @param ids - pointer on array of indexes to set
1156  @param ids_size - size of the input (ids)
1157  @param so - sort order (use BM_SORTED for faster load)
1158 
1159  @sa set, keep
1160  */
1161  void clear(const size_type* ids, size_type ids_size,
1163 
1164  /*!
1165  \brief swap values of bits
1166 
1167  @param idx1 - index of bit to swap with
1168  @param idx2 - index of bit to swap with
1169  */
1170  void swap(size_type idx1, size_type idx2);
1171 
1172 
1173  /*!
1174  \brief Set bit without checking preconditions (size, etc)
1175 
1176  Fast set bit method, without safety net.
1177  Make sure you call bvector<>::init() before setting bits with this
1178  function.
1179 
1180  \param n - bit number
1181  */
1183 
1184  /**
1185  \brief Set specified bit without checking preconditions (size, etc)
1186  */
1187  bool set_bit_no_check(size_type n, bool val);
1188 
1189  /*!
1190  \brief Sets all bits in the specified closed interval [left,right]
1191  Interval must be inside the bvector's size.
1192  This method DOES NOT resize vector.
1193 
1194  \param left - interval start
1195  \param right - interval end (closed interval)
1196  \param value - value to set interval in
1197 
1198  \return *this
1199  @sa clear_range
1200  */
1202  size_type right,
1203  bool value = true);
1204 
1205 
1206  /*!
1207  \brief Sets all bits to zero in the specified closed interval [left,right]
1208  Interval must be inside the bvector's size.
1209  This method DOES NOT resize vector.
1210 
1211  \param left - interval start
1212  \param right - interval end (closed interval)
1213 
1214  @sa set_range
1215  */
1216  void clear_range(size_type left, size_type right)
1217  { set_range(left, right, false); }
1218 
1219 
1220  /*!
1221  \brief Sets all bits to zero outside of the closed interval [left,right]
1222  Expected result: 00000...0[left, right]0....0000
1223 
1224  \param left - interval start
1225  \param right - interval end (closed interval)
1226 
1227  @sa set_range
1228  */
1229  void keep_range(size_type left, size_type right);
1230 
1231  /*!
1232  \brief Copy all bits in the specified closed interval [left,right]
1233 
1234  \param bvect - source bit-vector
1235  \param left - interval start
1236  \param right - interval end (closed interval)
1237  */
1239  size_type left,
1240  size_type right);
1241 
1242  /*!
1243  \brief Clears bit n.
1244  \param n - bit's index to be cleaned.
1245  \return true if bit was cleared
1246  */
1247  bool clear_bit(size_type n) { return set_bit(n, false); }
1248 
1249  /*!
1250  \brief Clears bit n without precondiion checks
1251  \param n - bit's index to be cleaned.
1252  */
1254 
1255  /*!
1256  \brief Clears every bit in the bitvector.
1257 
1258  \param free_mem if "true" (default) bvector frees the memory,
1259  otherwise sets blocks to 0.
1260  */
1261  void clear(bool free_mem = true) BMNOEXCEPT;
1262 
1263  /*!
1264  \brief Clears every bit in the bitvector.
1265  \return *this;
1266  */
1267  bvector<Alloc>& reset() BMNOEXCEPT { clear(true); return *this; }
1268 
1269  /*!
1270  \brief Flips bit n
1271  \return *this
1272  */
1273  bvector<Alloc>& flip(size_type n) { this->inc(n); return *this; }
1274 
1275  /*!
1276  \brief Flips all bits
1277  \return *this
1278  @sa invert
1279  */
1280  bvector<Alloc>& flip() { return invert(); }
1281 
1282  //@}
1283  // --------------------------------------------------------------------
1284 
1285 
1286  /*! Function erturns insert iterator for this bitvector */
1287  insert_iterator inserter() { return insert_iterator(*this); }
1288 
1289  // --------------------------------------------------------------------
1290  /*! @name Size and capacity
1291  By default bvector is dynamically sized, manual control methods
1292  available
1293  */
1294  //@{
1295 
1296  /** \brief Returns bvector's capacity (number of bits it can store) */
1297  //size_type capacity() const { return blockman_.capacity(); }
1298 
1299  /*! \brief return current size of the vector (bits) */
1301 
1302  /*!
1303  \brief Change size of the bvector
1304  \param new_size - new size in bits
1305  */
1306  void resize(size_type new_size);
1307 
1308  //@}
1309  // --------------------------------------------------------------------
1310 
1311  /*! @name Population counting, ranks, ranges and intervals
1312  */
1313  //@{
1314 
1315  /*!
1316  \brief population count (count of ON bits)
1317  \sa count_range
1318  \return Total number of bits ON
1319  */
1321 
1322  /*! \brief Computes bitcount values for all bvector blocks
1323  \param arr - pointer on array of block bit counts
1324  \return Index of the last block counted.
1325  This number +1 gives you number of arr elements initialized during the
1326  function call.
1327  */
1329 
1330 
1331  /*!
1332  \brief Returns count of 1 bits in the given range [left..right]
1333  Uses rank-select index to accelerate the search
1334  \param left - index of first bit start counting from
1335  \param right - index of last bit
1336  \param rs_idx - block count structure to accelerate search
1337  \sa build_rs_index
1338 
1339  \return population count in the diapason
1340  */
1342  size_type right,
1344 
1345  /*!
1346  \brief Returns count of 1 bits in the given range [left..right]
1347 
1348  \param left - index of first bit start counting from
1349  \param right - index of last bit
1350 
1351  \return population count in the diapason
1352  @sa count_range_no_check
1353  */
1355 
1356  /*!
1357  Returns count of 1 bits in the given range [left..right]
1358  Function expects that caller guarantees that left < right
1359 
1360  @sa count_range
1361  */
1363 
1364 
1365  /*!
1366  Returns count of 1 bits in the given range [left..right]
1367  Function expects that caller guarantees that left < right
1368 
1369  @sa count_range
1370  */
1372  size_type right,
1374 
1375  /*!
1376  \brief Returns true if all bits in the range are 1s (saturated interval)
1377  Function uses closed interval [left, right]
1378 
1379  \param left - index of first bit start checking
1380  \param right - index of last bit
1381 
1382  \return true if all bits are 1, false otherwise
1383  @sa any_range, count_range
1384  */
1386 
1387  /*!
1388  \brief Returns true if any bits in the range are 1s (non-empty interval)
1389  Function uses closed interval [left, right]
1390 
1391  \param left - index of first bit start checking
1392  \param right - index of last bit
1393 
1394  \return true if at least 1 bits is set
1395  @sa is_all_one_range, count_range
1396  */
1398 
1399 
1400  /*! \brief compute running total of all blocks in bit vector (rank-select index)
1401  \param rs_idx - [out] pointer to index / count structure
1402  \param bv_blocks - [out] list of block ids in the vector (internal, optional)
1403  Function will fill full array of running totals
1404  \sa count_to, select, find_rank
1405  */
1406  void build_rs_index(rs_index_type* rs_idx, bvector<Alloc>* bv_blocks=0) const;
1407 
1408  /*!
1409  \brief Returns count of 1 bits (population) in [0..right] range.
1410 
1411  This operation is also known as rank of bit N.
1412 
1413  \param n - index of bit to rank
1414  \param rs_idx - rank-select to accelerate search
1415  should be prepared using build_rs_index
1416  \return population count in the range [0..n]
1417  \sa build_rs_index
1418  \sa count_to_test, select, rank, rank_corrected
1419  */
1422 
1423 
1424  /*!
1425  \brief Returns rank of specified bit position (same as count_to())
1426 
1427  \param n - index of bit to rank
1428  \param rs_idx - rank-select index
1429  \return population count in the range [0..n]
1430  \sa build_rs_index
1431  \sa count_to_test, select, rank, rank_corrected
1432  */
1435  { return count_to(n, rs_idx); }
1436 
1437  /*!
1438  \brief Returns rank corrceted by the requested border value (as -1)
1439 
1440  This is rank function (bit-count) minus value of bit 'n'
1441  if bit-n is true function returns rank()-1 if false returns rank()
1442  faster than rank() + test().
1443 
1444 
1445  \param n - index of bit to rank
1446  \param rs_idx - rank-select index
1447  \return population count in the range [0..n] corrected as -1 by the value of n
1448  \sa build_rs_index
1449  \sa count_to_test, select, rank
1450  */
1452  const rs_index_type& rs_idx) const BMNOEXCEPT;
1453 
1454  /*!
1455  \brief popcount in [0..right] range if test(right) == true
1456 
1457  This is conditional rank operation, which is faster than test()
1458  plus count_to()
1459 
1460  \param n - index of bit to test and rank
1461  \param rs_idx - rank-select index
1462  (block count structure to accelerate search)
1463  should be prepared using build_rs_index()
1464 
1465  \return population count in the diapason or 0 if right bit test failed
1466 
1467  \sa build_rs_index
1468  \sa count_to
1469  */
1470  size_type
1472  const rs_index_type& rs_idx) const BMNOEXCEPT;
1473 
1474 
1475  /*! Recalculate bitcount (deprecated)
1476  */
1478 
1479  /*!
1480  Disables count cache. (deprecated).
1481  */
1483 
1484  //@}
1485 
1486  // --------------------------------------------------------------------
1487  /*! @name Bit access (read-only) */
1488  //@{
1489 
1490  /*!
1491  \brief returns true if bit n is set and false is bit n is 0.
1492  \param n - Index of the bit to check.
1493  \return Bit value (1 or 0)
1494  */
1496 
1497  /*!
1498  \brief returns true if bit n is set and false is bit n is 0.
1499  \param n - Index of the bit to check.
1500  \return Bit value (1 or 0)
1501  */
1502  bool test(size_type n) const BMNOEXCEPT { return get_bit(n); }
1503 
1504  //@}
1505 
1506  // --------------------------------------------------------------------
1507  /*! @name bit-shift and insert operations */
1508  //@{
1509 
1510  /*!
1511  \brief Shift right by 1 bit, fill with zero return carry out
1512  \return Carry over bit value (1 or 0)
1513  */
1514  bool shift_right();
1515 
1516  /*!
1517  \brief Shift left by 1 bit, fill with zero return carry out
1518  \return Carry over bit value (1 or 0)
1519  */
1520  bool shift_left();
1521 
1522  /*!
1523  \brief Insert bit into specified position
1524  All the vector content after insert position is shifted right.
1525 
1526  \param n - index of the bit to insert
1527  \param value - insert value
1528 
1529  \return Carry over bit value (1 or 0)
1530  */
1531  bool insert(size_type n, bool value);
1532 
1533  /*!
1534  \brief Erase bit in the specified position
1535  All the vector content after erase position is shifted left.
1536 
1537  \param n - index of the bit to insert
1538  */
1540 
1541  //@}
1542 
1543  // --------------------------------------------------------------------
1544  /*! @name Check for empty-ness of container */
1545  //@{
1546 
1547  /*!
1548  \brief Returns true if any bits in this bitset are set, and otherwise returns false.
1549  \return true if any bit is set
1550  */
1552 
1553  /*!
1554  \brief Returns true if no bits are set, otherwise returns false.
1555  */
1556  bool none() const BMNOEXCEPT { return !any(); }
1557 
1558  /**
1559  \brief Returns true if the set is empty (no bits are set, otherwise returns false)
1560  Please note that this is NOT a size check, it is an empty SET check (absense of 1s)
1561  */
1562  bool empty() const BMNOEXCEPT { return !any(); }
1563 
1564  //@}
1565  // --------------------------------------------------------------------
1566 
1567  /*! @name Scan and find bits and indexes */
1568  //@{
1569 
1570  /*!
1571  \fn bool bvector::find(bm::id_t& pos) const
1572  \brief Finds index of first 1 bit
1573  \param pos - [out] index of the found 1 bit
1574  \return true if search returned result
1575  \sa get_first, get_next, extract_next, find_reverse, find_first_mismatch
1576  */
1577  bool find(size_type& pos) const BMNOEXCEPT;
1578 
1579  /*!
1580  \fn bool bvector::find(bm::id_t from, bm::id_t& pos) const
1581  \brief Find index of 1 bit starting from position
1582  \param from - position to start search from, please note that if bit at from position
1583  is set then it will be found, function uses closed interval [from...
1584  \param pos - [out] index of the found 1 bit
1585  \return true if search returned result
1586  \sa get_first, get_next, extract_next, find_reverse, find_first_mismatch
1587  */
1588  bool find(size_type from, size_type& pos) const BMNOEXCEPT;
1589 
1590 
1591  /*!
1592  \fn bm::id_t bvector::get_first() const
1593  \brief find first 1 bit in vector.
1594  Function may return 0 and this requires an extra check if bit 0 is
1595  actually set or bit-vector is empty
1596 
1597  \return Index of the first 1 bit, may return 0
1598  \sa get_next, find, extract_next, find_reverse
1599  */
1601 
1602  /*!
1603  \fn bm::id_t bvector::get_next(bm::id_t prev) const
1604  \brief Finds the number of the next bit ON.
1605  \param prev - Index of the previously found bit.
1606  \return Index of the next bit which is ON or 0 if not found.
1607  \sa get_first, find, extract_next, find_reverse
1608  */
1610  { return (++prev == bm::id_max) ? 0 : check_or_next(prev); }
1611 
1612  /*!
1613  \fn bm::id_t bvector::extract_next(bm::id_t prev)
1614  \brief Finds the number of the next bit ON and sets it to 0.
1615  \param prev - Index of the previously found bit.
1616  \return Index of the next bit which is ON or 0 if not found.
1617  \sa get_first, get_next, find_reverse
1618  */
1620  {
1621  return (++prev == bm::id_max) ? 0 : check_or_next_extract(prev);
1622  }
1623 
1624  /*!
1625  \brief Finds last index of 1 bit
1626  \param pos - [out] index of the last found 1 bit
1627  \return true if search returned result
1628  \sa get_first, get_next, extract_next,
1629  \sa find, find_first_mismatch, find_range
1630  */
1632 
1633  /*!
1634  \brief Reverse finds next(prev) index of 1 bit
1635  \param from - index to search from
1636  \param pos - [out] found position index
1637  (undefined if method returns false)
1638  \return true if search returned result
1639  \sa get_first, get_next, extract_next,
1640  \sa find, find_first_mismatch, find_range
1641  */
1642  bool find_reverse(size_type from, size_type& pos) const BMNOEXCEPT;
1643 
1644  /*!
1645  \brief Finds dynamic range of bit-vector [first, last]
1646  \param first - index of the first found 1 bit
1647  \param last - index of the last found 1 bit
1648  \return true if search returned result
1649  \sa get_first, get_next, extract_next, find, find_reverse
1650  */
1652 
1653  /*!
1654  \brief Find bit-vector position for the specified rank(bitcount)
1655 
1656  Rank based search, counts number of 1s from specified position until
1657  finds the ranked position relative to start from position.
1658  In other words: range population count between from and pos == rank.
1659 
1660  \param rank - rank to find (bitcount)
1661  \param from - start positioon for rank search
1662  \param pos - position with speciefied rank (relative to from position)
1663 
1664  \return true if requested rank was found
1665  */
1667  size_type& pos) const BMNOEXCEPT;
1668 
1669  /*!
1670  \brief Find bit-vector position for the specified rank(bitcount)
1671 
1672  Rank based search, counts number of 1s from specified position until
1673  finds the ranked position relative to start from position.
1674  In other words: range population count between from and pos == rank.
1675 
1676  \param rank - rank to find (bitcount)
1677  \param from - start positioon for rank search
1678  \param pos - position with speciefied rank (relative to from position)
1679  \param rs_idx - rank-select index to accelarate search
1680  (should be prepared using build_rs_index)
1681 
1682  \sa build_rs_index, select
1683 
1684  \return true if requested rank was found
1685  */
1687  const rs_index_type& rs_idx) const BMNOEXCEPT;
1688 
1689  /*!
1690  \brief select bit-vector position for the specified rank(bitcount)
1691 
1692  Rank based search, counts number of 1s from specified position until
1693  finds the ranked position relative to start from position.
1694  Uses
1695  In other words: range population count between from and pos == rank.
1696 
1697  \param rank - rank to find (bitcount)
1698  \param pos - position with speciefied rank (relative to from position) [out]
1699  \param rs_idx - block count structure to accelerate rank search
1700 
1701  \sa running_count_blocks, find_rank
1702 
1703  \return true if requested rank was found
1704  */
1706  const rs_index_type& rs_idx) const BMNOEXCEPT;
1707 
1708  //@}
1709 
1710 
1711  // --------------------------------------------------------------------
1712  /*! @name Algebra of Sets operations */
1713  //@{
1714 
1715  /*!
1716  \brief 3-operand OR : this := bv1 OR bv2
1717  \param bv1 - Argument vector 1
1718  \param bv2 - Argument vector 2
1719  \param opt_mode - optimization compression
1720  (when it is performed on the fly it is faster than a separate
1721  call to optimize()
1722  @sa optimize, bit_or
1723  */
1725  const bm::bvector<Alloc>& bv2,
1726  typename bm::bvector<Alloc>::optmode opt_mode=opt_none);
1727 
1728  /*!
1729  \brief 3-operand XOR : this := bv1 XOR bv2
1730  \param bv1 - Argument vector 1
1731  \param bv2 - Argument vector 2
1732  \param opt_mode - optimization compression
1733  (when it is performed on the fly it is faster than a separate
1734  call to optimize()
1735  @sa optimize, bit_xor
1736  */
1738  const bm::bvector<Alloc>& bv2,
1739  typename bm::bvector<Alloc>::optmode opt_mode=opt_none);
1740 
1741  /*!
1742  \brief 3-operand AND : this := bv1 AND bv2
1743  \param bv1 - Argument vector 1
1744  \param bv2 - Argument vector 2
1745  \param opt_mode - optimization compression
1746  (when it is performed on the fly it is faster than a separate
1747  call to optimize()
1748  @sa optimize, bit_and
1749  */
1751  const bm::bvector<Alloc>& bv2,
1752  typename bm::bvector<Alloc>::optmode opt_mode=opt_none);
1753 
1754 
1755  /*!
1756  \brief 3-operand AND where result is ORed into the terget vector : this |= bv1 AND bv2
1757  TARGET := TARGET OR (BV1 AND BV2)
1758 
1759  \param bv1 - Argument vector 1
1760  \param bv2 - Argument vector 2
1761  \param opt_mode - optimization compression
1762  (when it is performed on the fly it is faster than a separate
1763  call to optimize()
1764  @sa optimize, bit_and
1765  */
1767  const bm::bvector<Alloc>& bv2,
1768  typename bm::bvector<Alloc>::optmode opt_mode=opt_none);
1769 
1770 
1771  /*!
1772  \brief 3-operand SUB : this := bv1 MINUS bv2
1773  SUBtraction is also known as AND NOT
1774  \param bv1 - Argument vector 1
1775  \param bv2 - Argument vector 2
1776  \param opt_mode - optimization compression
1777  (when it is performed on the fly it is faster than a separate
1778  call to optimize()
1779  @sa optimize, bit_sub
1780  */
1782  const bm::bvector<Alloc>& bv2,
1783  typename bm::bvector<Alloc>::optmode opt_mode=opt_none);
1784 
1785 
1786  /*!
1787  \brief 2 operand logical OR
1788  \param bv - Argument vector.
1789  */
1791  {
1792  BM_ASSERT(!is_ro());
1794  return *this;
1795  }
1796 
1797  /*!
1798  \brief 2 operand logical AND
1799  \param bv - argument vector
1800  \param opt_mode - set an immediate optimization
1801  */
1803  optmode opt_mode = opt_none)
1804  {
1805  BM_ASSERT(!is_ro());
1806  combine_operation_and(bv, opt_mode);
1807  return *this;
1808  }
1809 
1810  /*!
1811  \brief 2 operand logical XOR
1812  \param bv - argument vector.
1813  */
1815  {
1816  BM_ASSERT(!is_ro());
1818  return *this;
1819  }
1820 
1821  /*!
1822  \brief 2 operand logical SUB(AND NOT). Also known as MINUS.
1823  \param bv - argument vector.
1824  */
1826  {
1827  BM_ASSERT(!is_ro());
1829  return *this;
1830  }
1831 
1832  /*!
1833  \brief Invert/NEG all bits
1834  It should be noted, invert is affected by size()
1835  if size is set - it only inverts [0..size-1] bits
1836  */
1838 
1839 
1840  /*! \brief perform a set-algebra operation by operation code
1841  */
1843  bm::operation opcode);
1844 
1845  /*! \brief perform a set-algebra operation OR
1846  */
1848 
1849  /*! \brief perform a set-algebra operation AND
1850  */
1852  optmode opt_mode);
1853 
1854  /*! \brief perform a set-algebra operation MINUS (AND NOT)
1855  */
1857 
1858  /*! \brief perform a set-algebra operation XOR
1859  */
1861 
1862  // @}
1863 
1864  // --------------------------------------------------------------------
1865  /*! @name Iterator-traversal methods */
1866  //@{
1867 
1868  /**
1869  \brief Returns enumerator pointing on the first non-zero bit.
1870  */
1871  enumerator first() const { return get_enumerator(0); }
1872 
1873  /**
1874  \fn bvector::enumerator bvector::end() const
1875  \brief Returns enumerator pointing on the next bit after the last.
1876  */
1877  enumerator end() const
1878  { return typename bvector<Alloc>::enumerator(this); }
1879 
1880  /**
1881  \brief Returns enumerator pointing on specified or the next available bit.
1882  */
1884  { return typename bvector<Alloc>::enumerator(this, pos); }
1885 
1886  //@}
1887 
1888  // --------------------------------------------------------------------
1889  /*! @name Memory management and compression */
1890 
1891  //@{
1892 
1893  /*!
1894  @brief Calculates bitvector statistics.
1895 
1896  @param st - pointer on statistics structure to be filled in.
1897 
1898  Function fills statistics structure containing information about how
1899  this vector uses memory and estimation of max. amount of memory
1900  bvector needs to serialize itself.
1901 
1902  @sa statistics
1903  */
1905 
1906 
1907  /*!
1908  \brief Sets new blocks allocation strategy.
1909  \param strat - Strategy code 0 - bitblocks allocation only.
1910  1 - Blocks mutation mode (adaptive algorithm)
1911  */
1913 
1914  /*!
1915  \brief Returns blocks allocation strategy.
1916  \return - Strategy code 0 - bitblocks allocation only.
1917  1 - Blocks mutation mode (adaptive algorithm)
1918  \sa set_new_blocks_strat
1919  */
1921  { return new_blocks_strat_; }
1922 
1923  /*!
1924  \brief Optimize memory bitvector's memory allocation.
1925 
1926  Function analyze all blocks in the bitvector, compresses blocks
1927  with a regular structure, frees some memory. This function is recommended
1928  after a bulk modification of the bitvector using set_bit, clear_bit or
1929  logical operations.
1930 
1931  Optionally function can calculate vector post optimization statistics
1932 
1933  @param temp_block - externally allocated temp buffer for optimization
1934  BM_DECLARE_TEMP_BLOCK(tb)
1935  if NULL - it will allocated (and de-allocated upon exit)
1936  @param opt_mode - optimization level
1937  @param stat - statistics of memory consumption and serialization
1938  stat can also be computed by calc_stat() but it would require an extra pass
1939 
1940  @sa optmode, optimize_gap_size, calc_stat
1941  */
1942  void optimize(bm::word_t* temp_block = 0,
1943  optmode opt_mode = opt_compress,
1944  statistics* stat = 0);
1945 
1946  /*!
1947  Run partial vector optimization for the area [left..right] (specified in bit coordinates)
1948 
1949  @param left - bit index to optimize from (approximate, rounded up to a nearest block)
1950  @param right - bit index to optimize to
1951  Please note that left and right define range in bit coordinates but later rounded to blocks
1952  @param temp_block - external scratch memory (MUST be pre-allocated)
1953  @param opt_mode - optimization level
1954 
1955  @sa optimize
1956  */
1958  size_type left, size_type right,
1959  bm::word_t* temp_block,
1960  optmode opt_mode = opt_compress);
1961 
1962  /*!
1963  \brief Optimize sizes of GAP blocks
1964 
1965  This method runs an analysis to find optimal GAP levels for the
1966  specific vector. Current GAP compression algorithm uses several fixed
1967  GAP sizes. By default bvector uses some reasonable preset.
1968  */
1970 
1971  /*!
1972  @brief Sets new GAP lengths table. All GAP blocks will be reallocated
1973  to match the new scheme.
1974 
1975  @param glevel_len - pointer on C-style array keeping GAP block sizes.
1976  */
1977  void set_gap_levels(const gap_word_t* glevel_len);
1978 
1979  /**
1980  Return true if bvector is initialized at all
1981  @internal
1982  */
1984 
1985  /**
1986  Calculate blocks digest vector (for diagnostics purposes)
1987  1 is added if NB is a real, allocated block
1988 
1989  @param bv_blocks - [out] bvector of blocks statistics
1990  @internal
1991  */
1992  void fill_alloc_digest(bvector<Alloc>& bv_blocks) const;
1993 
1994  //@}
1995 
1996  // --------------------------------------------------------------------
1997 
1998  /*! @name Comparison */
1999  //@{
2000 
2001  /*!
2002  \brief Lexicographical comparison with a bitvector.
2003 
2004  Function compares current bitvector with the provided argument
2005  bit by bit and returns -1 if this bitvector less than the argument,
2006  1 - greater, 0 - equal
2007 
2008  @return 0 if this == arg, -1 if this < arg, 1 if this > arg
2009  @sa find_first_mismatch
2010  */
2012 
2013  /*!
2014  \brief Equal comparison with an agr bit-vector
2015  @return true if vectors are identical
2016  */
2018  {
2019  size_type pos;
2020  bool found = find_first_mismatch(bvect, pos);
2021  return !found;
2022  }
2023 
2024  /*!
2025  \brief Find index of first bit different between this and the agr vector
2026 
2027  @param bvect - argumnet vector to compare with
2028  @param pos - [out] position of the first difference
2029  @param search_to - search limiter [0..to] to avoid overscan
2030  (default: unlimited to the vectors end)
2031 
2032  @return true if didfference found, false - both vectors are equivalent
2033  @sa compare
2034  */
2036  size_type& pos,
2037  size_type search_to = bm::id_max
2038  ) const BMNOEXCEPT;
2039 
2040  //@}
2041 
2042  // --------------------------------------------------------------------
2043  /*! @name Open internals */
2044  //@{
2045 
2046  /*!
2047  @internal
2048  */
2050  const bm::word_t* arg_blk,
2051  bool arg_gap,
2052  bm::operation opcode);
2053  /**
2054  \brief get access to memory manager (internal)
2055  Use only if you are BitMagic library
2056  @internal
2057  */
2059  { return blockman_; }
2060 
2061  /**
2062  \brief get access to memory manager (internal)
2063  Use only if you are BitMagic library
2064  @internal
2065  */
2067  { return blockman_; }
2068 
2069  /**
2070  Import integers (set bits). (Fast, no checks).
2071  @internal
2072  */
2073  void import(const size_type* ids, size_type ids_size,
2074  bm::sort_order sorted_idx);
2075 
2076  /**
2077  Import sorted integers (set bits). (Fast, no checks).
2078  @internal
2079  */
2080  void import_sorted(const size_type* ids,
2081  const size_type ids_size, bool opt_flag);
2082 
2083  /**
2084  \brief Set range without validity/bounds checking
2085  */
2087  size_type right);
2088  /**
2089  \brief Clear range without validity/bounds checking
2090  */
2092  size_type right);
2093 
2094 
2095  //@}
2096 
2097  static void throw_bad_alloc();
2098 
2099 protected:
2100  /**
2101  Syncronize size if it got extended due to bulk import
2102  @internal
2103  */
2104  void sync_size();
2105 
2106 
2107  void import_block(const size_type* ids,
2108  block_idx_type nblock, size_type start, size_type stop);
2109 
2110 
2111 
2113 
2114  /// set bit in GAP block with GAP block length control
2116  bool val, block_idx_type nblock, unsigned nbit);
2117 
2118  /// set bit in GAP block with GAP block length control
2120  bool val, block_idx_type nblock,
2121  unsigned nbit);
2122 
2123  /// check if specified bit is 1, and set it to 0
2124  /// if specified bit is 0, scan for the next 1 and returns it
2125  /// if no 1 found returns 0
2127 
2128 
2129  /**
2130  \brief AND specified bit without checking preconditions (size, etc)
2131  */
2132  bool and_bit_no_check(size_type n, bool val);
2133 
2134  bool set_bit_conditional_impl(size_type n, bool val, bool condition);
2135 
2136 
2138  bool gap,
2139  bm::word_t* blk,
2140  const bm::word_t* arg_blk,
2141  bool arg_gap,
2142  bm::operation opcode);
2143 
2144  /**
2145  @return true if block optimization may be needed
2146  */
2148  unsigned j,
2149  const bm::word_t* arg_blk1,
2150  const bm::word_t* arg_blk2);
2152  unsigned j,
2153  const bm::word_t* arg_blk1,
2154  const bm::word_t* arg_blk2);
2156  unsigned j,
2157  const bm::word_t* arg_blk1,
2158  const bm::word_t* arg_blk2);
2159 
2161  unsigned j,
2162  const bm::word_t* arg_blk1,
2163  const bm::word_t* arg_blk2);
2165  unsigned j,
2166  const bm::word_t* arg_blk1,
2167  const bm::word_t* arg_blk2);
2168 
2169 
2171  unsigned j,
2172  bm::word_t* blk,
2173  const bm::word_t* arg_blk);
2174 
2176  unsigned j,
2177  bm::word_t* blk,
2178  const bm::word_t* arg_blk);
2179 
2181  unsigned j,
2182  bm::word_t* blk,
2183  const bm::word_t* arg_blk);
2184 
2186  unsigned j,
2187  bm::word_t* blk,
2188  const bm::word_t* arg_blk);
2189 
2191  size_type left,
2192  size_type right);
2193 
2194 private:
2195  /**
2196  \brief Clear outside the range without validity/bounds checking
2197  */
2199  size_type right);
2200 
2201  /**
2202  Compute rank in bit-block using rank-select index
2203  */
2204  static
2206  block_idx_type nb,
2207  unsigned nbit_right,
2208  const rs_index_type& rs_idx) BMNOEXCEPT;
2209  /**
2210  Compute rank in GAP block using rank-select index
2211  @param test_set - request to test nbit_right before computing count
2212  (returns 0 if not set)
2213  */
2214  static
2216  block_idx_type nb,
2217  unsigned nbit_right,
2218  const rs_index_type& rs_idx,
2219  bool test_set = false) BMNOEXCEPT;
2220  /**
2221  Return value of first bit in the block
2222  */
2224 
2225 private:
2226  blocks_manager_type blockman_; //!< bitblocks manager
2227  strategy new_blocks_strat_; //!< block allocation strategy
2228  size_type size_; //!< size in bits
2229 };
2230 
2231 
2232 //---------------------------------------------------------------------
2233 
2234 template<class Alloc>
2235 inline bvector<Alloc> operator& (const bvector<Alloc>& bv1,
2236  const bvector<Alloc>& bv2)
2237 {
2238  bvector<Alloc> ret;
2239  ret.bit_and(bv1, bv2, bvector<Alloc>::opt_none);
2240  return ret;
2241 }
2242 
2243 //---------------------------------------------------------------------
2244 
2245 template<class Alloc>
2247  const bvector<Alloc>& bv2)
2248 {
2249  bvector<Alloc> ret;
2250  ret.bit_or(bv1, bv2, bvector<Alloc>::opt_none);
2251  return ret;
2252 }
2253 
2254 //---------------------------------------------------------------------
2255 
2256 template<class Alloc>
2258  const bvector<Alloc>& bv2)
2259 {
2260  bvector<Alloc> ret;
2261  ret.bit_xor(bv1, bv2, bvector<Alloc>::opt_none);
2262  return ret;
2263 }
2264 
2265 //---------------------------------------------------------------------
2266 
2267 template<class Alloc>
2269  const bvector<Alloc>& bv2)
2270 {
2271  bvector<Alloc> ret;
2272  ret.bit_sub(bv1, bv2, bvector<Alloc>::opt_none);
2273  return ret;
2274 }
2275 
2276 
2277 // -----------------------------------------------------------------------
2278 
2279 template<typename Alloc>
2281 {
2282  BM_ASSERT(!is_ro());
2283  blockman_.init_tree();
2284 }
2285 
2286 // -----------------------------------------------------------------------
2287 
2288 template<typename Alloc>
2289 void bvector<Alloc>::init(unsigned top_size, bool alloc_subs)
2290 {
2291  BM_ASSERT(!is_ro());
2292  if (!blockman_.is_init())
2293  blockman_.init_tree(top_size);
2294  if (alloc_subs)
2295  for (unsigned nb = 0; nb < top_size; ++nb)
2297 }
2298 
2299 
2300 // -----------------------------------------------------------------------
2301 
2302 template<typename Alloc>
2304 {
2305  if (this != &bvect)
2306  {
2308  switch (is_final)
2309  {
2311  if (bvect.is_ro())
2312  {
2314  size_ = bvect.size();
2315  }
2316  else
2317  {
2319  resize(bvect.size());
2320  }
2321  break;
2324  size_ = bvect.size();
2325  break;
2328  resize(bvect.size());
2329  break;
2330  default:
2331  BM_ASSERT(0);
2332  break;
2333  } // switch
2334  }
2335 }
2336 
2337 // -----------------------------------------------------------------------
2338 
2339 template<typename Alloc>
2341 {
2342  if (this != &bvect)
2343  {
2345  size_ = bvect.size_;
2347  }
2348 }
2349 
2350 //---------------------------------------------------------------------
2351 
2352 template<class Alloc>
2354 {
2355  BM_ASSERT(!is_ro());
2356  if (!blockman_.is_init())
2357  return; // nothing to do
2358 
2359  if (right < left)
2360  bm::xor_swap(left, right);
2361 
2362  keep_range_no_check(left, right);
2363 }
2364 
2365 // -----------------------------------------------------------------------
2366 
2367 template<typename Alloc>
2369  size_type right,
2370  bool value)
2371 {
2372  BM_ASSERT(!is_ro());
2373 
2374  if (!blockman_.is_init() && !value)
2375  return *this; // nothing to do
2376 
2377  if (right < left)
2378  return set_range(right, left, value);
2379 
2380  BM_ASSERT_THROW(right < bm::id_max, BM_ERR_RANGE);
2381  if (right >= size_) // this vect shorter than the arg.
2382  {
2383  size_type new_size = (right == bm::id_max) ? bm::id_max : right + 1;
2384  resize(new_size);
2385  }
2386 
2387  BM_ASSERT(left <= right);
2388  BM_ASSERT(left < size_);
2389 
2390  if (value)
2391  set_range_no_check(left, right);
2392  else
2393  clear_range_no_check(left, right);
2394 
2395  return *this;
2396 }
2397 
2398 // -----------------------------------------------------------------------
2399 
2400 template<typename Alloc>
2402 {
2403  if (!blockman_.is_init())
2404  return 0;
2405 
2406  word_t*** blk_root = blockman_.top_blocks_root();
2407  BM_ASSERT(blk_root);
2408 
2409  size_type cnt = 0;
2410  unsigned top_blocks = blockman_.top_block_size();
2411  for (unsigned i = 0; i < top_blocks; ++i)
2412  {
2413  bm::word_t** blk_blk = blk_root[i];
2414  if (!blk_blk)
2415  {
2416  ++i;
2417  bool found = bm::find_not_null_ptr(blk_root, i, top_blocks, &i);
2418  if (!found)
2419  break;
2420  blk_blk = blk_root[i];
2421  BM_ASSERT(blk_blk);
2422  if (!blk_blk)
2423  break;
2424  }
2425  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
2426  {
2428  continue;
2429  }
2430  unsigned j = 0;
2431  do
2432  {
2433  if (blk_blk[j])
2434  cnt += blockman_.block_bitcount(blk_blk[j]);
2435  if (blk_blk[j+1])
2436  cnt += blockman_.block_bitcount(blk_blk[j+1]);
2437  if (blk_blk[j+2])
2438  cnt += blockman_.block_bitcount(blk_blk[j+2]);
2439  if (blk_blk[j+3])
2440  cnt += blockman_.block_bitcount(blk_blk[j+3]);
2441  j += 4;
2442  } while (j < bm::set_sub_array_size);
2443 
2444  } // for i
2445  return cnt;
2446 }
2447 
2448 // -----------------------------------------------------------------------
2449 
2450 template<typename Alloc>
2452 {
2453  word_t*** blk_root = blockman_.top_blocks_root();
2454  if (!blk_root)
2455  return false;
2457  return for_each_nzblock_if(blk_root, blockman_.top_block_size(), func);
2458 }
2459 
2460 // -----------------------------------------------------------------------
2461 
2462 template<typename Alloc>
2464 {
2465  BM_ASSERT(!is_ro());
2466 
2467  if (size_ == new_size) return; // nothing to do
2468  if (size_ < new_size) // size grows
2469  {
2470  if (!blockman_.is_init())
2471  blockman_.init_tree();
2472 
2473  blockman_.reserve(new_size);
2474  size_ = new_size;
2475  }
2476  else // shrink
2477  {
2478  set_range(new_size, size_ - 1, false); // clear the tail
2479  size_ = new_size;
2480  }
2481 }
2482 
2483 // -----------------------------------------------------------------------
2484 
2485 template<typename Alloc>
2487 {
2488  BM_ASSERT(!is_ro());
2489 
2490  if (size_ >= bm::id_max)
2491  return;
2493  bool found = find_reverse(last);
2494  if (found && last >= size_)
2495  resize(last+1);
2496 }
2497 
2498 // -----------------------------------------------------------------------
2499 
2500 template<typename Alloc>
2502  bvector<Alloc>* bv_blocks) const
2503 {
2504  BM_ASSERT(rs_idx);
2505  if (bv_blocks)
2506  {
2507  bv_blocks->clear();
2508  bv_blocks->init();
2509  }
2510 
2511  unsigned bcount[bm::set_sub_array_size];
2513 
2514  rs_idx->init();
2515  if (!blockman_.is_init())
2516  return;
2517 
2518  // resize the RS index to fit the vector
2519  //
2520  size_type last_bit;
2521  bool found = find_reverse(last_bit);
2522  if (!found)
2523  return;
2524  block_idx_type nb = (last_bit >> bm::set_block_shift);
2525  unsigned i0, j0;
2526  bm::get_block_coord(nb, i0, j0);
2527 
2528  unsigned real_top_blocks = blockman_.find_real_top_blocks();
2529  unsigned max_top_blocks = blockman_.find_max_top_blocks();
2530  if (nb < (max_top_blocks * bm::set_sub_array_size))
2531  nb = (max_top_blocks * bm::set_sub_array_size);
2532  rs_idx->set_total(nb + 1);
2533  rs_idx->resize(nb + 1);
2534  rs_idx->resize_effective_super_blocks(real_top_blocks);
2535 
2536  // index construction
2537  //
2538  BM_ASSERT(max_top_blocks <= blockman_.top_block_size());
2539  bm::word_t*** blk_root = blockman_.top_blocks_root();
2540  for (unsigned i = 0; i < max_top_blocks; ++i)
2541  {
2542  bm::word_t** blk_blk = blk_root[i];
2543  if (!blk_blk)
2544  {
2545  rs_idx->set_null_super_block(i);
2546  continue;
2547  }
2548  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
2549  {
2550  rs_idx->set_full_super_block(i);
2551  if (bv_blocks)
2552  {
2553  size_type nb_from = i * bm::set_sub_array_size;
2554  size_type nb_to = nb_from + bm::set_sub_array_size - 1;
2555  bv_blocks->set_range_no_check(nb_from, nb_to);
2556  }
2557  continue;
2558  }
2559 
2560  unsigned j = 0;
2561  do
2562  {
2563  const bm::word_t* block = blk_blk[j];
2564  if (!block)
2565  {
2566  bcount[j] = 0; sub_count[j] = 0;
2567  continue;
2568  }
2569  unsigned local_first, local_second, local_third;
2570  bm::id64_t aux0, aux1; // aux infomation to encode
2571  if (BM_IS_GAP(block))
2572  {
2573  const bm::gap_word_t* const gap_block = BMGAP_PTR(block);
2574  local_first =
2576  local_second =
2577  bm::gap_bit_count_range(gap_block,
2579  bm::rs3_border1);
2580  local_third =
2581  bm::gap_bit_count_range(gap_block,
2584 
2585  // for GAP block calculate borderline positions in GAP
2586  // and value (0|1), save to AUX
2587  //
2588  unsigned is_set;
2589  aux0 = bm::gap_bfind(gap_block, rs3_border0+1, &is_set);
2590  aux0 <<= 1;
2591  if (is_set) aux0 |= 1;
2592  aux1 = bm::gap_bfind(gap_block, rs3_border1+1, &is_set);
2593  aux1 <<= 1;
2594  if (is_set) aux1 |= 1;
2595  }
2596  else
2597  {
2598  block = BLOCK_ADDR_SAN(block); // TODO: optimize FULL
2599  local_first =
2601  local_second =
2603  bm::rs3_border0+1,
2604  bm::rs3_border1);
2605  local_third =
2607  bm::rs3_border1+1,
2608  bm::gap_max_bits-1);
2609  // compute inetrmediate points
2612  }
2613  unsigned cnt = local_first + local_second + local_third;
2615 
2616  bcount[j] = cnt;
2617  if (bv_blocks && cnt)
2618  bv_blocks->set_bit_no_check(i * bm::set_sub_array_size + j);
2619 
2620  BM_ASSERT(cnt >= local_first + local_second);
2621  sub_count[j] = bm::id64_t(local_first | (local_second << 16)) |
2622  (aux0 << 32) | (aux1 << 48);
2623 
2624  } while (++j < bm::set_sub_array_size);
2625 
2626  rs_idx->register_super_block(i, &bcount[0], &sub_count[0]);
2627 
2628  } // for i
2629 
2630 }
2631 
2632 
2633 // -----------------------------------------------------------------------
2634 
2635 template<typename Alloc>
2638 {
2639  bm::word_t*** blk_root = blockman_.top_blocks_root();
2640  if (blk_root == 0)
2641  return 0;
2643  bm::for_each_nzblock(blk_root, blockman_.top_block_size(), func);
2644  return func.last_block();
2645 }
2646 
2647 // -----------------------------------------------------------------------
2648 
2649 #define BM_BORDER_TEST(blk, idx) bool(blk[idx >> bm::set_word_shift] & (1u << (idx & bm::set_word_mask)))
2650 
2651 
2652 #if (defined(BMSSE42OPT) || defined(BMAVX2OPT) || defined(BMAVX512OPT) || \
2653  defined(BMWASMSIMDOPT) || defined(BMNEONOPT))
2654 
2655 
2656 template<typename Alloc>
2659  block_idx_type nb,
2660  unsigned nbit_right,
2661  const rs_index_type& rs_idx) BMNOEXCEPT
2662 {
2663  BM_ASSERT(IS_VALID_ADDR(block));
2664  size_type c;
2665 
2666  bm::id64_t sub = rs_idx.sub_count(nb);
2667  unsigned sub_cnt = unsigned(sub);
2668  unsigned first = sub_cnt & 0xFFFF;
2669  unsigned second = sub_cnt >> 16;
2670 
2673 
2674 
2675  {
2676  unsigned cnt, aux0(bm::gap_word_t(sub >> 32)); (void)cnt; (void)aux0;
2678  unsigned cnt1, aux1(bm::gap_word_t(sub >> 48)); (void)aux1; (void) cnt1;
2679  BM_ASSERT(aux1 == (cnt1 =bm::bit_block_calc_count_to(block, bm::rs3_border1_1)));
2680  }
2681 
2682 
2683  #if defined(BM64_SSE4) || defined(BM64_AVX2) || defined(BM64_AVX512)
2684  const unsigned cutoff_bias = rs3_half_span/8;
2685  #else
2686  const unsigned cutoff_bias = 0;
2687  #endif
2688 
2689  unsigned sub_range = rs_idx.find_sub_range(nbit_right);
2690 
2691  // evaluate 3 sub-block intervals (and sub-intervals)
2692  // |--------[0]-----*-----[1]----*-----|
2693  switch(sub_range) // sub-range rank calc
2694  {
2695  case 0:
2696  // |--x-----[0]-----------[1]----------|
2697  if (nbit_right <= rs3_border0/2 + cutoff_bias)
2698  {
2699  c = bm::bit_block_calc_count_range<true, false>(block, 0, nbit_right);
2700  }
2701  else
2702  {
2703  // |--------[x]-----------[1]----------|
2704  if (nbit_right == rs3_border0)
2705  {
2706  c = first;
2707  }
2708  else
2709  {
2710  // |------x-[0]-----------[1]----------|
2711  c = bm::bit_block_calc_count_range(block, nbit_right+1,
2712  rs3_border0);
2713  c = first - c;
2714  }
2715  }
2716  break;
2717  case 1:
2718  {
2719  // |--------[0]-x---------[1]----------|
2720  if (nbit_right <= rs3_border0_1 + cutoff_bias)
2721  {
2722  c =
2723  bm::bit_block_calc_count_range<true, false>(block,
2725  nbit_right);
2726  c += first - BM_BORDER_TEST(block, bm::rs3_border0);
2727  }
2728  else
2729  {
2730  unsigned bc_second_range = first + second;
2731  // |--------[0]-----------[x]----------|
2732  if (nbit_right == rs3_border1)
2733  {
2734  c = bc_second_range;
2735  }
2736  else // sub-range processing
2737  {
2738  // |--------[0]--------x--[1]----------|
2739  BM_ASSERT(nbit_right > bm::rs3_border0_1);
2740  unsigned d1 = nbit_right - bm::rs3_border0_1;
2741  unsigned d2 = rs3_border1 - nbit_right;
2742  if (d2 < d1)
2743  {
2744  // |--------[0]----|----x-[1]----------|
2746  nbit_right+1,
2747  rs3_border1);
2748  c = bc_second_range - c;
2749  }
2750  else
2751  {
2752  // |--------[0]----|-x----[1]----------|
2753  c = bm::bit_block_calc_count_range<true, false>(
2754  block,
2756  nbit_right);
2757  unsigned aux0 = bm::gap_word_t(sub >> 32);
2758  c += aux0;
2759  c -= BM_BORDER_TEST(block, bm::rs3_border0_1);
2760  }
2761  }
2762  }
2763  }
2764  break;
2765  case 2:
2766  {
2767  // |--------[0]-----------[1]-x---*----|
2768  if (nbit_right <= rs3_border1_1)
2769  {
2770  unsigned d1 = nbit_right - bm::rs3_border1;
2771  unsigned d2 = (rs3_border1_1 + cutoff_bias) - nbit_right;
2772  if (d1 < d2) // |--------[0]-----------[1]-x---*----|
2773  {
2774  c = bm::bit_block_calc_count_range<true, false>(block,
2776  nbit_right);
2777  c += first + second; //bc_second_range;
2778  c -= BM_BORDER_TEST(block, bm::rs3_border1);
2779  }
2780  else // |--------[0]-----------[1]---x-*----|
2781  {
2782  if (nbit_right == rs3_border1_1)
2783  {
2784  unsigned aux1 = bm::gap_word_t(sub >> 48);
2785  c = aux1;
2786  }
2787  else
2788  {
2790  nbit_right+1,
2791  rs3_border1_1);
2792  unsigned aux1 = bm::gap_word_t(sub >> 48);
2793  c = aux1 - c;
2794  }
2795  }
2796  }
2797  else
2798  {
2799  // |--------[0]-----------[1]----------x
2800  if (nbit_right == bm::gap_max_bits-1)
2801  {
2802  c = rs_idx.count(nb);
2803  }
2804  else // sub-range processing
2805  {
2806  // |--------[0]-----------[1]-------x--|
2807  BM_ASSERT(nbit_right > bm::rs3_border1_1);
2808  unsigned d1 = nbit_right - bm::rs3_border1_1;
2809  unsigned d2 = bm::gap_max_bits - nbit_right;
2810  if (d2 < d1)
2811  {
2812  // |--------[0]----------[1]----*---x-|
2814  nbit_right+1,
2815  bm::gap_max_bits-1);
2816  size_type cnt = rs_idx.count(nb);
2817  c = cnt - c;
2818  }
2819  else
2820  {
2821  // |--------[0]----------[1]----*-x---|
2822  c = bm::bit_block_calc_count_range<true, false>(block,
2824  nbit_right);
2825  unsigned aux1 = bm::gap_word_t(sub >> 48);
2826  c += aux1;
2827  c -= BM_BORDER_TEST(block, bm::rs3_border1_1);
2828  }
2829  }
2830  }
2831  }
2832  break;
2833  default:
2834  BM_ASSERT(0);
2835  c = 0;
2836  } // switch
2837 
2838  BM_ASSERT(c == bm::bit_block_calc_count_to(block, nbit_right));
2839  return c;
2840 }
2841 
2842 #else // non-SIMD version
2843 
2844 template<typename Alloc>
2847  block_idx_type nb,
2848  unsigned nbit_right,
2849  const rs_index_type& rs_idx) BMNOEXCEPT
2850 {
2851  BM_ASSERT(block);
2852 
2853  bm::id64_t sub = rs_idx.sub_count(nb);
2854  unsigned sub_cnt = unsigned(sub);
2855  unsigned first = sub_cnt & 0xFFFF;
2856  unsigned second = sub_cnt >> 16;
2857 
2860 
2861 
2862  {
2863  unsigned cnt, aux0(bm::gap_word_t(sub >> 32)); (void)cnt; (void)aux0;
2865  unsigned cnt1, aux1(bm::gap_word_t(sub >> 48)); (void)aux1; (void) cnt1;
2866  BM_ASSERT(aux1 == (cnt1 =bm::bit_block_calc_count_to(block, bm::rs3_border1_1)));
2867  }
2868 
2869  size_type c=0;
2870  unsigned sub_choice =
2871  bm::get_nibble(bm::rs_intervals<true>::_c._lut, nbit_right);
2872 
2873  switch(sub_choice)
2874  {
2875  case 0:
2876  c = bm::bit_block_calc_count_range<true, false>(block, 0, nbit_right);
2877  break;
2878  case 1:
2879  c = first;
2880  break;
2881  case 2:
2882  c = bm::bit_block_calc_count_range(block, nbit_right+1, rs3_border0);
2883  c = first - c;
2884  break;
2885  case 3:
2886  c = bm::bit_block_calc_count_range<true, false>(block,
2888  nbit_right);
2889  c += first - BM_BORDER_TEST(block, bm::rs3_border0);
2890  break;
2891  case 4:
2892  c = first + second;
2893  break;
2894  case 5:
2895  c = bm::bit_block_calc_count_range(block, nbit_right+1, rs3_border1);
2896  c = first + second - c;
2897  break;
2898  case 6:
2899  c = bm::bit_block_calc_count_range<true, false>(
2900  block,
2902  nbit_right);
2903  c += bm::gap_word_t(sub >> 32); // aux0
2904  c -= BM_BORDER_TEST(block, bm::rs3_border0_1);
2905  break;
2906  case 7:
2907  c = bm::bit_block_calc_count_range<true, false>(block,
2909  nbit_right);
2910  c += first + second; //bc_second_range;
2911  c -= BM_BORDER_TEST(block, bm::rs3_border1);
2912  break;
2913  case 8:
2914  c = bm::gap_word_t(sub >> 48); // aux1;
2915  break;
2916  case 9:
2918  nbit_right+1,
2919  rs3_border1_1);
2920  c = bm::gap_word_t(sub >> 48) - c; // aux1 - c
2921  break;
2922  case 10:
2923  c = rs_idx.count(nb);
2924  break;
2925  case 11:
2927  nbit_right+1,
2928  bm::gap_max_bits-1);
2929  c = rs_idx.count(nb) - c;
2930  break;
2931  case 12:
2932  c = bm::bit_block_calc_count_range<true, false>(block,
2934  nbit_right);
2935  c += bm::gap_word_t(sub >> 48); // aux1;
2936  c -= BM_BORDER_TEST(block, bm::rs3_border1_1);
2937  break;
2938  default:
2939  BM_ASSERT(0);
2940  } // switch
2941  BM_ASSERT(c == bm::bit_block_calc_count_to(block, nbit_right));
2942  return c;
2943 }
2944 #endif
2945 
2946 #undef BM_BORDER_TEST
2947 
2948 // -----------------------------------------------------------------------
2949 
2950 template<typename Alloc>
2953  block_idx_type nb,
2954  unsigned nbit_right,
2955  const rs_index_type& rs_idx,
2956  bool test_set) BMNOEXCEPT
2957 {
2958  BM_ASSERT(gap_block);
2959  size_type c;
2960 
2961 
2962  if (test_set)
2963  {
2964  bool is_set = bm::gap_test_unr(gap_block, (gap_word_t)nbit_right);
2965  if (!is_set)
2966  return 0;
2967  }
2968 /*
2969  {
2970  unsigned len = bm::gap_length(gap_block);
2971  if (len < 64)
2972  {
2973  c = bm::gap_bit_count_to(gap_block, (gap_word_t)nbit_right);
2974  return c;
2975  }
2976  }
2977 */
2978  bm::id64_t sub = rs_idx.sub_count(nb);
2979  if (!sub)
2980  {
2981  c = 0;
2982  BM_ASSERT(c == bm::gap_bit_count_to(gap_block, (gap_word_t)nbit_right));
2983  return c;
2984  }
2985 
2986  unsigned sub_cnt = unsigned(sub);
2987  unsigned first = bm::gap_word_t(sub_cnt);
2988  unsigned second = (sub_cnt >> 16);
2989 
2990 
2992  BM_ASSERT(second == bm::gap_bit_count_range(gap_block, rs3_border0+1, rs3_border1));
2993 
2994  // evaluate 3 sub-block intervals
2995  // |--------[0]-----------[1]----------|
2996  const unsigned cutoff_bias = rs3_half_span/8;
2997  unsigned sub_range = rs_idx.find_sub_range(nbit_right);
2998  switch(sub_range) // sub-range rank calc
2999  {
3000  case 0:
3001  // |--x-----[0]-----------[1]----------|
3002  if (nbit_right <= (rs3_border0/2 + cutoff_bias))
3003  {
3004  c = bm::gap_bit_count_to(gap_block,(gap_word_t)nbit_right);
3005  }
3006  else
3007  {
3008  // |--------[x]-----------[1]----------|
3009  if (nbit_right == rs3_border0)
3010  {
3011  c = first;
3012  }
3013  else
3014  {
3015  // |------x-[0]-----------[1]----------|
3016  c =
3017  bm::gap_bit_count_range(gap_block, nbit_right+1, rs3_border0);
3018  c = first - c;
3019  }
3020  }
3021  break;
3022  case 1:
3023  // |--------[0]-x---------[1]----------|
3024  if (nbit_right <= (rs3_border0 + rs3_half_span + cutoff_bias))
3025  {
3026  unsigned aux0 = bm::gap_word_t(sub >> 32);
3027  c = bm::gap_bit_count_range_hint(gap_block,
3028  rs3_border0+1, nbit_right, aux0);
3029  c += first;
3030  }
3031  else
3032  {
3033  // |--------[0]-----------[x]----------|
3034  if (nbit_right == rs3_border1)
3035  {
3036  c = first + second;
3037  }
3038  else
3039  {
3040  // |--------[0]--------x--[1]----------|
3041  c =
3042  bm::gap_bit_count_range(gap_block, nbit_right+1, rs3_border1);
3043  c = first + second - c;
3044  }
3045  }
3046  break;
3047  case 2:
3048  {
3049  // |--------[0]-----------[1]-x--------|
3050  if (nbit_right <= (rs3_border1 + rs3_half_span + cutoff_bias))
3051  {
3052  unsigned aux1 = bm::gap_word_t(sub >> 48);
3053  c = bm::gap_bit_count_range_hint(gap_block,
3054  rs3_border1 + 1, nbit_right, aux1);
3055  c += first + second; // += bc_second_range
3056  }
3057  else
3058  {
3059  // |--------[0]-----------[1]----------x
3060  if (nbit_right == bm::gap_max_bits-1)
3061  {
3062  c = rs_idx.count(nb);
3063  }
3064  else
3065  {
3066  // |--------[0]-----------[1]-------x--|
3067  c = bm::gap_bit_count_range<bm::gap_word_t, true> (gap_block,
3068  nbit_right+1, bm::gap_max_bits-1);
3069  size_type cnt = rs_idx.count(nb);
3070  c = cnt - c;
3071  }
3072  }
3073  }
3074  break;
3075  default:
3076  BM_ASSERT(0);
3077  c = 0;
3078  } // switch
3079 
3080  BM_ASSERT(c == bm::gap_bit_count_to(gap_block, (gap_word_t)nbit_right));
3081  return c;
3082 }
3083 
3084 // -----------------------------------------------------------------------
3085 
3086 template<typename Alloc>
3087 typename bvector<Alloc>::size_type
3089  const rs_index_type& rs_idx) const BMNOEXCEPT
3090 {
3091  BM_ASSERT(right < bm::id_max);
3092  if (!blockman_.is_init())
3093  return 0;
3094 
3095  unsigned nb_right = unsigned(right >> bm::set_block_shift);
3096 
3097  // running count of all blocks before target
3098  //
3099  size_type cnt;
3100  if (nb_right >= rs_idx.get_total())
3101  {
3102  cnt = rs_idx.count();
3103  return cnt;
3104  }
3105  cnt = nb_right ? rs_idx.rcount(nb_right-1) : 0;
3106 
3107  unsigned i, j;
3108  bm::get_block_coord(nb_right, i, j);
3109  const bm::word_t* block = blockman_.get_block_ptr(i, j);
3110 
3111  if (block)
3112  {
3113  size_type c;
3114  unsigned nbit_right = unsigned(right & bm::set_block_mask);
3115  if (BM_IS_GAP(block))
3116  {
3117  const bm::gap_word_t* gap_block = BMGAP_PTR(block);
3118  c = this->gap_count_to(gap_block, nb_right, nbit_right, rs_idx);
3119  }
3120  else
3121  {
3122  if (block == FULL_BLOCK_FAKE_ADDR) // TODO: misses REAL full sometimes
3123  {
3124  return cnt + nbit_right + 1;
3125  }
3126  else // real bit-block
3127  {
3128  c = this->block_count_to(block, nb_right, nbit_right, rs_idx);
3129  }
3130  }
3131  cnt += c;
3132 
3133  }
3134  return cnt;
3135 }
3136 
3137 // -----------------------------------------------------------------------
3138 
3139 template<typename Alloc>
3140 typename bvector<Alloc>::size_type
3142  const rs_index_type& rs_idx) const BMNOEXCEPT
3143 {
3144  BM_ASSERT(right < bm::id_max);
3145  if (!blockman_.is_init())
3146  return 0;
3147 
3148  unsigned nb_right = unsigned(right >> bm::set_block_shift);
3149 
3150  unsigned i, j;
3151  bm::get_block_coord(nb_right, i, j);
3152  const bm::word_t* block = blockman_.get_block_ptr(i, j);
3153  if (!block)
3154  return 0;
3155 
3156  unsigned nbit_right = unsigned(right & bm::set_block_mask);
3157  size_type cnt = nbit_right + 1; // default for FULL BLOCK
3158  if (BM_IS_GAP(block))
3159  {
3160  bm::gap_word_t *gap_blk = BMGAP_PTR(block);
3161  cnt = gap_count_to(gap_blk, nb_right, nbit_right, rs_idx, true);
3162  if (!cnt)
3163  return cnt;
3164  BM_ASSERT(cnt == bm::gap_bit_count_to(gap_blk, (gap_word_t)nbit_right));
3165  /*
3166  if (bm::gap_test_unr(gap_blk, (gap_word_t)nbit_right))
3167  {
3168  cnt = gap_count_to(gap_blk, nb_right, nbit_right, rs_idx);
3169  BM_ASSERT(cnt == bm::gap_bit_count_to(gap_blk, (gap_word_t)nbit_right));
3170  }
3171  else
3172  return 0;
3173  */
3174  }
3175  else
3176  {
3177  if (block != FULL_BLOCK_FAKE_ADDR)
3178  {
3179  unsigned w = block[nbit_right >> bm::set_word_shift]; // nword
3180  if (w &= (1u << (nbit_right & bm::set_word_mask)))
3181  {
3182  cnt = block_count_to(block, nb_right, nbit_right, rs_idx);
3183  BM_ASSERT(cnt == bm::bit_block_calc_count_to(block, nbit_right));
3184  }
3185  else
3186  return 0;
3187  }
3188  }
3189  cnt += nb_right ? rs_idx.rcount(nb_right - 1) : 0;
3190  return cnt;
3191 }
3192 
3193 // -----------------------------------------------------------------------
3194 
3195 template<typename Alloc>
3198  const rs_index_type& rs_idx) const BMNOEXCEPT
3199 {
3200  BM_ASSERT(right < bm::id_max);
3201  if (!blockman_.is_init())
3202  return 0;
3203 
3204  unsigned nblock_right = unsigned(right >> bm::set_block_shift);
3205  unsigned nbit_right = unsigned(right & bm::set_block_mask);
3206 
3207  size_type cnt = nblock_right ? rs_idx.rcount(nblock_right - 1) : 0;
3208 
3209  unsigned i, j;
3210  bm::get_block_coord(nblock_right, i, j);
3211  const bm::word_t* block = blockman_.get_block_ptr(i, j);
3212 
3213  if (!block)
3214  return cnt;
3215 
3216  bool gap = BM_IS_GAP(block);
3217  if (gap)
3218  {
3219  cnt += bm::gap_bit_count_to<bm::gap_word_t, true>(
3220  BMGAP_PTR(block), (gap_word_t)nbit_right);
3221  }
3222  else
3223  {
3224  if (block == FULL_BLOCK_FAKE_ADDR)
3225  cnt += nbit_right;
3226  else
3227  {
3228  cnt += block_count_to(block, nblock_right, nbit_right, rs_idx);
3229  unsigned w = block[nbit_right >> bm::set_word_shift] &
3230  (1u << (nbit_right & bm::set_word_mask));
3231  cnt -= bool(w); // rank correction
3232  }
3233  }
3234  return cnt;
3235 }
3236 
3237 
3238 // -----------------------------------------------------------------------
3239 
3240 template<typename Alloc>
3243 {
3244  BM_ASSERT(left < bm::id_max && right < bm::id_max);
3245  if (!blockman_.is_init())
3246  return 0;
3247  if (left > right)
3248  bm::xor_swap(left, right);
3249  if (right == bm::id_max)
3250  --right;
3251  return count_range_no_check(left, right);
3252 }
3253 
3254 // -----------------------------------------------------------------------
3255 
3256 template<typename Alloc>
3259 {
3260  size_type cnt = 0;
3261 
3262  // calculate logical number of start and destination blocks
3263  block_idx_type nblock_left = (left >> bm::set_block_shift);
3264  block_idx_type nblock_right = (right >> bm::set_block_shift);
3265 
3266  unsigned i0, j0;
3267  bm::get_block_coord(nblock_left, i0, j0);
3268  const bm::word_t* block = blockman_.get_block(i0, j0);
3269 
3270  bool left_gap = BM_IS_GAP(block);
3271 
3272  unsigned nbit_left = unsigned(left & bm::set_block_mask);
3273  unsigned nbit_right = unsigned(right & bm::set_block_mask);
3274 
3275  unsigned r =
3276  (nblock_left == nblock_right) ? nbit_right : (bm::bits_in_block-1);
3277 
3279 
3280  if (block)
3281  {
3282  if ((nbit_left == 0) && (r == (bm::bits_in_block-1))) // whole block
3283  {
3284  func(block);
3285  cnt += func.count();
3286  }
3287  else
3288  {
3289  if (left_gap)
3290  {
3292  (gap_word_t)nbit_left,
3293  (gap_word_t)r);
3294  }
3295  else
3296  {
3297  cnt += bm::bit_block_calc_count_range(block, nbit_left, r);
3298  }
3299  }
3300  }
3301 
3302  if (nblock_left == nblock_right) // in one block
3303  return cnt;
3304 
3305  // process all full mid-blocks
3306  {
3307  func.reset();
3308  word_t*** blk_root = blockman_.top_blocks_root();
3309  block_idx_type top_blocks_size = blockman_.top_block_size();
3310 
3311  bm::for_each_nzblock_range(blk_root, top_blocks_size,
3312  nblock_left+1, nblock_right-1, func);
3313  cnt += func.count();
3314  }
3315 
3316  bm::get_block_coord(nblock_right, i0, j0);
3317  block = blockman_.get_block(i0, j0);
3318  bool right_gap = BM_IS_GAP(block);
3319 
3320  if (block)
3321  {
3322  if (right_gap)
3323  {
3324  cnt +=
3325  bm::gap_bit_count_to(BMGAP_PTR(block), (gap_word_t)nbit_right);
3326  }
3327  else
3328  {
3329  cnt += bm::bit_block_calc_count_range(block, 0, nbit_right);
3330  }
3331  }
3332  return cnt;
3333 }
3334 
3335 // -----------------------------------------------------------------------
3336 
3337 template<typename Alloc>
3339  size_type right) const BMNOEXCEPT
3340 {
3341  if (!blockman_.is_init())
3342  return false; // nothing to do
3343 
3344  if (right < left)
3345  bm::xor_swap(left, right);
3346  if (right == bm::id_max)
3347  --right;
3348  if (left == right)
3349  return test(left);
3350 
3351  BM_ASSERT(left < bm::id_max && right < bm::id_max);
3352 
3353  block_idx_type nblock_left = (left >> bm::set_block_shift);
3354  block_idx_type nblock_right = (right >> bm::set_block_shift);
3355 
3356  unsigned i0, j0;
3357  bm::get_block_coord(nblock_left, i0, j0);
3358  const bm::word_t* block = blockman_.get_block(i0, j0);
3359 
3360  if (nblock_left == nblock_right) // hit in the same block
3361  {
3362  unsigned nbit_left = unsigned(left & bm::set_block_mask);
3363  unsigned nbit_right = unsigned(right & bm::set_block_mask);
3364  return bm::block_is_all_one_range(block, nbit_left, nbit_right);
3365  }
3366 
3367  // process entry point block
3368  {
3369  unsigned nbit_left = unsigned(left & bm::set_block_mask);
3370  bool all_one = bm::block_is_all_one_range(block,
3371  nbit_left, (bm::gap_max_bits-1));
3372  if (!all_one)
3373  return all_one;
3374  ++nblock_left;
3375  }
3376 
3377  // process tail block
3378  {
3379  bm::get_block_coord(nblock_right, i0, j0);
3380  block = blockman_.get_block(i0, j0);
3381  unsigned nbit_right = unsigned(right & bm::set_block_mask);
3382  bool all_one = bm::block_is_all_one_range(block, 0, nbit_right);
3383  if (!all_one)
3384  return all_one;
3385  --nblock_right;
3386  }
3387 
3388  // check all blocks in the middle
3389  //
3390  if (nblock_left <= nblock_right)
3391  {
3392  unsigned i_from, j_from, i_to, j_to;
3393  bm::get_block_coord(nblock_left, i_from, j_from);
3394  bm::get_block_coord(nblock_right, i_to, j_to);
3395 
3396  bm::word_t*** blk_root = blockman_.top_blocks_root();
3397 
3398  for (unsigned i = i_from; i <= i_to; ++i)
3399  {
3400  bm::word_t** blk_blk = blk_root[i];
3401  if (!blk_blk)
3402  return false;
3403  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
3404  continue;
3405 
3406  unsigned j = (i == i_from) ? j_from : 0;
3407  unsigned j_limit = (i == i_to) ? j_to+1 : bm::set_sub_array_size;
3408  do
3409  {
3410  bool all_one = bm::check_block_one(blk_blk[j], true);
3411  if (!all_one)
3412  return all_one;
3413  } while (++j < j_limit);
3414  } // for i
3415  }
3416  return true;
3417 }
3418 
3419 // -----------------------------------------------------------------------
3420 
3421 template<typename Alloc>
3423 {
3424  BM_ASSERT(left < bm::id_max && right < bm::id_max);
3425 
3426  if (!blockman_.is_init())
3427  return false; // nothing to do
3428 
3429  if (right < left)
3430  bm::xor_swap(left, right);
3431  if (right == bm::id_max)
3432  --right;
3433  if (left == right)
3434  return test(left);
3435 
3436  block_idx_type nblock_left = (left >> bm::set_block_shift);
3437  block_idx_type nblock_right = (right >> bm::set_block_shift);
3438 
3439  unsigned i0, j0;
3440  bm::get_block_coord(nblock_left, i0, j0);
3441  const bm::word_t* block = blockman_.get_block(i0, j0);
3442 
3443  if (nblock_left == nblock_right) // hit in the same block
3444  {
3445  unsigned nbit_left = unsigned(left & bm::set_block_mask);
3446  unsigned nbit_right = unsigned(right & bm::set_block_mask);
3447  return bm::block_any_range(block, nbit_left, nbit_right);
3448  }
3449 
3450  // process entry point block
3451  {
3452  unsigned nbit_left = unsigned(left & bm::set_block_mask);
3453  bool any_one = bm::block_any_range(block,
3454  nbit_left, (bm::gap_max_bits-1));
3455  if (any_one)
3456  return any_one;
3457  ++nblock_left;
3458  }
3459 
3460  // process tail block
3461  {
3462  bm::get_block_coord(nblock_right, i0, j0);
3463  block = blockman_.get_block(i0, j0);
3464  unsigned nbit_right = unsigned(right & bm::set_block_mask);
3465  bool any_one = bm::block_any_range(block, 0, nbit_right);
3466  if (any_one)
3467  return any_one;
3468  --nblock_right;
3469  }
3470 
3471  // check all blocks in the middle
3472  //
3473  if (nblock_left <= nblock_right)
3474  {
3475  unsigned i_from, j_from, i_to, j_to;
3476  bm::get_block_coord(nblock_left, i_from, j_from);
3477  bm::get_block_coord(nblock_right, i_to, j_to);
3478 
3479  bm::word_t*** blk_root = blockman_.top_blocks_root();
3480  {
3482  if (i_from >= top_size)
3483  return false;
3484  if (i_to >= top_size)
3485  {
3486  i_to = unsigned(top_size-1);
3487  j_to = bm::set_sub_array_size-1;
3488  }
3489  }
3490 
3491  for (unsigned i = i_from; i <= i_to; ++i)
3492  {
3493  bm::word_t** blk_blk = blk_root[i];
3494  if (!blk_blk)
3495  continue;
3496  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
3497  return true;
3498 
3499  unsigned j = (i == i_from) ? j_from : 0;
3500  unsigned j_limit = (i == i_to) ? j_to+1 : bm::set_sub_array_size;
3501  do
3502  {
3503  bool any_one = bm::block_any(blk_blk[j]);
3504  if (any_one)
3505  return any_one;
3506  } while (++j < j_limit);
3507  } // for i
3508  }
3509  return false;
3510 }
3511 
3512 // -----------------------------------------------------------------------
3513 
3514 template<typename Alloc>
3517  size_type right,
3518  const rs_index_type& rs_idx) const BMNOEXCEPT
3519 {
3520  if (left > right)
3521  bm::xor_swap(left, right);
3522  BM_ASSERT_THROW(right < bm::id_max, BM_ERR_RANGE);
3523  return count_range_no_check(left, right, rs_idx);
3524 }
3525 
3526 // -----------------------------------------------------------------------
3527 
3528 template<typename Alloc>
3531  size_type right,
3532  const rs_index_type& rs_idx) const BMNOEXCEPT
3533 {
3534  BM_ASSERT(left <= right);
3535  if (left == right)
3536  return this->test(left);
3537  size_type cnt_l, cnt_r;
3538  if (left)
3539  cnt_l = this->count_to(left-1, rs_idx);
3540  else
3541  cnt_l = left; // == 0
3542  cnt_r = this->count_to(right, rs_idx);
3543  BM_ASSERT(cnt_r >= cnt_l);
3544  return cnt_r - cnt_l;
3545 }
3546 
3547 // -----------------------------------------------------------------------
3548 
3549 template<typename Alloc>
3551 {
3552  BM_ASSERT(!is_ro());
3553 
3554  if (!size_)
3555  return *this; // cannot invert a set of power 0
3556 
3557  unsigned top_blocks = blockman_.reserve_top_blocks(bm::set_top_array_size);
3558  bm::word_t*** blk_root = blockman_.top_blocks_root();
3559  for (unsigned i = 0; i < top_blocks; ++i)
3560  {
3561  bm::word_t** blk_blk = blk_root[i];
3562  if (!blk_blk)
3563  {
3564  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
3565  continue;
3566  }
3567  if (blk_blk == (bm::word_t**)FULL_BLOCK_FAKE_ADDR)
3568  {
3569  blk_root[i] = 0;
3570  continue;
3571  }
3572  unsigned j = 0; bm::word_t* blk;
3573  do
3574  {
3575  blk = blk_blk[j];
3576  if (!blk)
3578  else
3579  if (IS_FULL_BLOCK(blk))
3580  blockman_.set_block_ptr(i, j, 0);
3581  else
3582  {
3583  if (BM_IS_GAP(blk))
3584  bm::gap_invert(BMGAP_PTR(blk));
3585  else
3586  bm::bit_invert((wordop_t*)blk);
3587  }
3588  } while (++j < bm::set_sub_array_size);
3589  } // for i
3590 
3591  if (size_ == bm::id_max)
3592  set_bit_no_check(bm::id_max, false);
3593  else
3595 
3596  return *this;
3597 }
3598 
3599 // -----------------------------------------------------------------------
3600 
3601 template<typename Alloc>
3603 {
3604  BM_ASSERT(n < size_);
3605  BM_ASSERT_THROW((n < size_), BM_ERR_RANGE);
3606 
3607  // calculate logical block number
3608  unsigned nb = unsigned(n >> bm::set_block_shift);
3609  unsigned i, j;
3610  bm::get_block_coord(nb, i, j);
3611 
3613  return false;
3614 
3615  const bm::word_t* const* blk_blk = blockman_.top_blocks_[i];
3616  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
3617  return true;
3618  if (!blk_blk) return false;
3619  if (const bm::word_t* block = blk_blk[j])
3620  {
3621  if (block == FULL_BLOCK_FAKE_ADDR)
3622  return true;
3623  unsigned nbit = unsigned(n & bm::set_block_mask);
3624  if (BM_IS_GAP(block))
3625  return bm::gap_test_unr(BMGAP_PTR(block), nbit);
3626  return block[nbit >> bm::set_word_shift] &
3627  (1u << (nbit & bm::set_word_mask));
3628  }
3629  return false;
3630 }
3631 
3632 // -----------------------------------------------------------------------
3633 
3634 template<typename Alloc>
3636  optmode opt_mode,
3637  statistics* stat)
3638 {
3639  BM_ASSERT(!is_ro());
3640 
3641  if (!blockman_.is_init())
3642  {
3643  if (stat)
3644  calc_stat(stat);
3645  return;
3646  }
3647  if (!temp_block)
3648  temp_block = blockman_.check_allocate_tempblock();
3649 
3650  if (stat)
3651  {
3652  stat->reset();
3653  ::memcpy(stat->gap_levels,
3654  blockman_.glen(), sizeof(gap_word_t) * bm::gap_levels);
3655  stat->max_serialize_mem = (unsigned)sizeof(bm::id_t) * 4;
3656  }
3657  blockman_.optimize_tree(temp_block, opt_mode, stat);
3658  if (stat)
3659  {
3660  blockman_.stat_correction(stat);
3661  stat->memory_used += (unsigned)(sizeof(*this) - sizeof(blockman_));
3662  }
3663 
3664  // don't need to keep temp block if we optimizing memory usage
3666 }
3667 
3668 // -----------------------------------------------------------------------
3669 
3670 template<typename Alloc>
3672  size_type left,
3673  size_type right,
3674  bm::word_t* temp_block,
3675  optmode opt_mode)
3676 {
3677  BM_ASSERT(!is_ro());
3678  BM_ASSERT(left <= right);
3679  BM_ASSERT(temp_block);
3680 
3681  block_idx_type nblock_left = (left >> bm::set_block_shift);
3682  block_idx_type nblock_right = (right >> bm::set_block_shift);
3683 
3684  for (; nblock_left <= nblock_right; ++nblock_left)
3685  {
3686  unsigned i0, j0;
3687  bm::get_block_coord(nblock_left, i0, j0);
3688  if (i0 >= blockman_.top_block_size())
3689  break;
3690  bm::word_t* block = blockman_.get_block_ptr(i0, j0);
3691  if (block)
3692  blockman_.optimize_block(i0, j0, block, temp_block, opt_mode, 0);
3693  } // for
3694 
3695 }
3696 
3697 // -----------------------------------------------------------------------
3698 
3699 template<typename Alloc>
3701 {
3702 #if 0
3703  if (!blockman_.is_init())
3704  return;
3705 
3706  struct bvector<Alloc>::statistics st;
3707  calc_stat(&st);
3708 
3709  if (!st.gap_blocks)
3710  return;
3711 
3712  gap_word_t opt_glen[bm::gap_levels];
3713  ::memcpy(opt_glen, st.gap_levels, bm::gap_levels * sizeof(*opt_glen));
3714 
3715  improve_gap_levels(st.gap_length,
3716  st.gap_length + st.gap_blocks,
3717  opt_glen);
3718 
3719  set_gap_levels(opt_glen);
3720 #endif
3721 }
3722 
3723 // -----------------------------------------------------------------------
3724 
3725 template<typename Alloc>
3726 void bvector<Alloc>::set_gap_levels(const gap_word_t* glevel_len)
3727 {
3728  BM_ASSERT(!is_ro());
3729 
3730  if (blockman_.is_init())
3731  {
3732  word_t*** blk_root = blockman_.top_blocks_root();
3733  typename
3734  blocks_manager_type::gap_level_func gl_func(blockman_, glevel_len);
3735  for_each_nzblock(blk_root, blockman_.top_block_size(),gl_func);
3736  }
3737 
3738  blockman_.set_glen(glevel_len);
3739 }
3740 
3741 // -----------------------------------------------------------------------
3742 
3743 template<typename Alloc>
3745 {
3746  int res;
3747  unsigned top_blocks = blockman_.top_block_size();
3748  unsigned bvect_top_blocks = bv.blockman_.top_block_size();
3749 
3750  if (bvect_top_blocks > top_blocks) top_blocks = bvect_top_blocks;
3751 
3752  for (unsigned i = 0; i < top_blocks; ++i)
3753  {
3754  const bm::word_t* const* blk_blk = blockman_.get_topblock(i);
3755  const bm::word_t* const* arg_blk_blk = bv.blockman_.get_topblock(i);
3756 
3757  if (blk_blk == arg_blk_blk)
3758  continue;
3759 
3760  for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
3761  {
3762  const bm::word_t* arg_blk; const bm::word_t* blk;
3763  if ((bm::word_t*)arg_blk_blk == FULL_BLOCK_FAKE_ADDR)
3764  arg_blk = FULL_BLOCK_REAL_ADDR;
3765  else
3766  {
3767  arg_blk = arg_blk_blk ? arg_blk_blk[j] : 0;
3768  if (arg_blk == FULL_BLOCK_FAKE_ADDR)
3769  arg_blk = FULL_BLOCK_REAL_ADDR;
3770  }
3771  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
3772  blk = FULL_BLOCK_REAL_ADDR;
3773  else
3774  {
3775  blk = blk_blk ? blk_blk[j] : 0;
3776  if (blk == FULL_BLOCK_FAKE_ADDR)
3777  blk = FULL_BLOCK_REAL_ADDR;
3778  }
3779  if (blk == arg_blk) continue;
3780 
3781  // If one block is zero we check if the other one has at least
3782  // one bit ON
3783 
3784  if (!blk || !arg_blk)
3785  {
3786  const bm::word_t* pblk; bool is_gap;
3787 
3788  if (blk)
3789  {
3790  pblk = blk;
3791  res = 1;
3792  is_gap = BM_IS_GAP(blk);
3793  }
3794  else
3795  {
3796  pblk = arg_blk;
3797  res = -1;
3798  is_gap = BM_IS_GAP(arg_blk);
3799  }
3800 
3801  if (is_gap)
3802  {
3803  if (!bm::gap_is_all_zero(BMGAP_PTR(pblk)))
3804  return res;
3805  }
3806  else
3807  {
3808  if (!bm::bit_is_all_zero(pblk))
3809  return res;
3810  }
3811  continue;
3812  }
3813  bool arg_gap = BM_IS_GAP(arg_blk);
3814  bool gap = BM_IS_GAP(blk);
3815 
3816  if (arg_gap != gap)
3817  {
3818  BM_DECLARE_TEMP_BLOCK(temp_blk)
3819  bm::wordop_t* blk1; bm::wordop_t* blk2;
3820 
3821  if (gap)
3822  {
3824  BMGAP_PTR(blk));
3825  blk1 = (bm::wordop_t*)temp_blk;
3826  blk2 = (bm::wordop_t*)arg_blk;
3827  }
3828  else
3829  {
3831  BMGAP_PTR(arg_blk));
3832  blk1 = (bm::wordop_t*)blk;
3833  blk2 = (bm::wordop_t*)temp_blk;
3834  }
3835  res = bm::bitcmp(blk1, blk2, bm::set_block_size_op);
3836  }
3837  else
3838  {
3839  if (gap)
3840  {
3841  res = bm::gapcmp(BMGAP_PTR(blk), BMGAP_PTR(arg_blk));
3842  }
3843  else
3844  {
3845  res = bm::bitcmp((bm::wordop_t*)blk,
3846  (bm::wordop_t*)arg_blk,
3848  }
3849  }
3850  if (res != 0)
3851  return res;
3852  } // for j
3853 
3854  } // for i
3855 
3856  return 0;
3857 }
3858 
3859 // -----------------------------------------------------------------------
3860 
3861 template<typename Alloc>
3863  const bvector<Alloc>& bvect, size_type& pos,
3864  size_type search_to) const BMNOEXCEPT
3865 {
3866  unsigned top_blocks = blockman_.top_block_size();
3867  bm::word_t*** top_root = blockman_.top_blocks_root();
3868 
3869  if (!top_blocks || !top_root)
3870  {
3871  return bvect.find(pos);
3872  }
3873  bm::word_t*** arg_top_root = bvect.blockman_.top_blocks_root();
3874  unsigned i_to, j_to;
3875  {
3876  unsigned bvect_top_blocks = bvect.blockman_.top_block_size();
3877  if (!bvect_top_blocks || !arg_top_root)
3878  {
3879  bool f = this->find(pos);
3880  if (f)
3881  {
3882  if (pos > search_to)
3883  return false;
3884  }
3885  return f;
3886  }
3887 
3888  if (bvect_top_blocks > top_blocks)
3889  top_blocks = bvect_top_blocks;
3890  block_idx_type nb_to = (search_to >> bm::set_block_shift);
3891  bm::get_block_coord(nb_to, i_to, j_to);
3892  }
3893  if (i_to < top_blocks)
3894  top_blocks = i_to+1;
3895 
3896  for (unsigned i = 0; i < top_blocks; ++i)
3897  {
3898  const bm::word_t* const* blk_blk = blockman_.get_topblock(i);
3899  const bm::word_t* const* arg_blk_blk = bvect.blockman_.get_topblock(i);
3900 
3901  if (blk_blk == arg_blk_blk)
3902  {
3903  /* TODO: fix buffer overrread here
3904  unsigned arg_top_blocks = bvect.blockman_.top_block_size_;
3905  if (top_blocks < arg_top_blocks)
3906  arg_top_blocks = top_blocks;
3907  if (i_to < arg_top_blocks)
3908  arg_top_blocks = i_to+1;
3909 
3910  // look ahead for top level mismatch
3911  for (++i; i < arg_top_blocks; ++i)
3912  {
3913  if (top_root[i] != arg_top_root[i])
3914  {
3915  blk_blk = blockman_.get_topblock(i);
3916  arg_blk_blk = bvect.blockman_.get_topblock(i);
3917  BM_ASSERT(blk_blk != arg_blk_blk);
3918  goto find_sub_block;
3919  }
3920  }
3921  */
3922  continue;
3923  }
3924  //find_sub_block:
3925  unsigned j = 0;
3926  do
3927  {
3928  const bm::word_t* arg_blk; const bm::word_t* blk;
3929  arg_blk = ((bm::word_t*)arg_blk_blk == FULL_BLOCK_FAKE_ADDR) ?
3931  arg_blk_blk ? (BLOCK_ADDR_SAN(arg_blk_blk[j])) : 0;
3932  blk = ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR) ?
3934  (blk_blk ? (BLOCK_ADDR_SAN(blk_blk[j])) : 0);
3935  if (blk == arg_blk)
3936  continue;
3937 
3938  unsigned block_pos;
3939  bool found = bm::block_find_first_diff(blk, arg_blk, &block_pos);
3940  if (found)
3941  {
3942  pos =
3944  (size_type(j) * bm::gap_max_bits) + block_pos;
3945  if (pos > search_to)
3946  return false;
3947  return true;
3948  }
3949 
3950  if (i == i_to)
3951  {
3952  if (j >= j_to)
3953  return false;
3954  }
3955 
3956  } while (++j < bm::set_sub_array_size);
3957  } // for i
3958 
3959  return false;
3960 
3961 }
3962 
3963 // -----------------------------------------------------------------------
3964 
3965 template<typename Alloc>
3967 {
3968  if (this != &bvect)
3969  {
3972  }
3973 }
3974 
3975 // -----------------------------------------------------------------------
3976 
3977 template<typename Alloc>
3979  struct bvector<Alloc>::statistics* st) const BMNOEXCEPT
3980 {
3981  BM_ASSERT(st);
3982 
3983  st->reset();
3984  ::memcpy(st->gap_levels,
3985  blockman_.glen(), sizeof(gap_word_t) * bm::gap_levels);
3986 
3987  st->max_serialize_mem = unsigned(sizeof(bm::id_t) * 4);
3988  unsigned top_size = blockman_.top_block_size();
3989 
3990  size_t blocks_mem = sizeof(blockman_);
3991  blocks_mem +=
3993  blocks_mem += sizeof(bm::word_t**) * top_size;
3994  bm::word_t*** blk_root = blockman_.top_blocks_root();
3995 
3996  if (blk_root)
3997  {
3998  for (unsigned i = 0; i < top_size; ++i)
3999  {
4000  const bm::word_t* const* blk_blk = blk_root[i];
4001  if (!blk_blk)
4002  {
4003  ++i;
4004  bool found = bm::find_not_null_ptr(blk_root, i, top_size, &i);
4005  if (!found)
4006  break;
4007  blk_blk = blk_root[i];
4008  BM_ASSERT(blk_blk);
4009  if (!blk_blk)
4010  break;
4011  }
4012  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
4013  continue;
4014  st->ptr_sub_blocks++;
4015  for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
4016  {
4017  const bm::word_t* blk = blk_blk[j];
4018  if (IS_VALID_ADDR(blk))
4019  {
4020  if (BM_IS_GAP(blk))
4021  {
4022  const bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
4023  unsigned cap;
4024  unsigned len = gap_length(gap_blk);
4025  cap = is_ro() ? len
4026  : bm::gap_capacity(gap_blk, blockman_.glen());
4027  unsigned level = bm::gap_level(gap_blk);
4028  st->add_gap_block(cap, len, level);
4029  }
4030  else // bit block
4031  st->add_bit_block();
4032  }
4033  } // for j
4034  } // for i
4035 
4036  size_t full_null_size = blockman_.calc_serialization_null_full();
4037  st->max_serialize_mem += full_null_size;
4038 
4039  } // if blk_root
4040 
4041  size_t safe_inc = st->max_serialize_mem / 10; // 10% increment
4042  if (!safe_inc) safe_inc = 256;
4043  st->max_serialize_mem += safe_inc;
4044 
4045  // Calc size of different odd and temporary things.
4046  st->memory_used += unsigned(sizeof(*this) - sizeof(blockman_));
4047  blocks_mem += st->ptr_sub_blocks * (sizeof(void*) * bm::set_sub_array_size);
4048  st->memory_used += blocks_mem;
4049  if (is_ro())
4050  st->memory_used += sizeof(typename blocks_manager_type::arena);
4051  st->bv_count = 1;
4052 
4053 }
4054 
4055 // -----------------------------------------------------------------------
4056 
4057 template<typename Alloc>
4059 {
4060  bv_blocks.init();
4061 
4062  unsigned top_size = blockman_.top_block_size();
4063  bm::word_t*** blk_root = blockman_.top_blocks_root();
4064  if (blk_root)
4065  {
4066  for (unsigned i = 0; i < top_size; ++i)
4067  {
4068  const bm::word_t* const* blk_blk = blk_root[i];
4069  if (!blk_blk || ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR))
4070  continue;
4071  for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
4072  {
4073  const bm::word_t* blk = blk_blk[j];
4074  if (IS_VALID_ADDR(blk))
4075  {
4076  size_type nb = i * bm::set_sub_array_size + j;
4077  bv_blocks.set_bit_no_check(nb);
4078  }
4079  } // for j
4080  } // for i
4081  } // if blk_root
4082 }
4083 
4084 
4085 // -----------------------------------------------------------------------
4086 
4087 template<class Alloc>
4089  size_type ids_size, bm::sort_order so)
4090 {
4091  BM_ASSERT(!is_ro());
4092 
4093  if (!ids || !ids_size)
4094  return; // nothing to do
4095  if (!blockman_.is_init())
4096  blockman_.init_tree();
4097 
4098  import(ids, ids_size, so);
4099  sync_size();
4100 }
4101 
4102 // -----------------------------------------------------------------------
4103 
4104 template<class Alloc>
4105 void bvector<Alloc>::keep(const size_type* ids, size_type ids_size,
4106  bm::sort_order so)
4107 {
4108  BM_ASSERT(!is_ro());
4109 
4110  if (!ids || !ids_size || !blockman_.is_init())
4111  {
4112  clear();
4113  return;
4114  }
4115  bvector<Alloc> bv_tmp; // TODO: better optimize for SORTED case (avoid temp)
4116  bv_tmp.import(ids, ids_size, so);
4117 
4118  size_type last;
4119  bool found = bv_tmp.find_reverse(last);
4120  if (found)
4121  {
4122  bv_tmp.resize(last+1);
4123  bit_and(bv_tmp);
4124  }
4125  else
4126  {
4127  BM_ASSERT(0);
4128  clear();
4129  }
4130 }
4131 
4132 // -----------------------------------------------------------------------
4133 
4134 template<class Alloc>
4136 {
4137  if (is_ro())
4138  {
4139  BM_ASSERT(free_mem);
4141  }
4142  else
4143  blockman_.set_all_zero(free_mem);
4144 }
4145 
4146 // -----------------------------------------------------------------------
4147 
4148 template<class Alloc>
4150  size_type ids_size, bm::sort_order so)
4151 {
4152  BM_ASSERT(!is_ro());
4153 
4154  if (!ids || !ids_size || !blockman_.is_init())
4155  {
4156  return;
4157  }
4158  bvector<Alloc> bv_tmp; // TODO: better optimize for SORTED case (avoid temp)
4159  bv_tmp.import(ids, ids_size, so);
4160 
4161  size_type last;
4162  bool found = bv_tmp.find_reverse(last);
4163  if (found)
4164  {
4165  bv_tmp.resize(last+1);
4166  bit_sub(bv_tmp);
4167  }
4168  else
4169  {
4170  BM_ASSERT(0);
4171  }
4172 }
4173 
4174 // -----------------------------------------------------------------------
4175 
4176 template<class Alloc>
4178 {
4179  BM_ASSERT(!is_ro());
4180 
4181  set_range(0, size_ - 1, true);
4182  return *this;
4183 }
4184 
4185 // -----------------------------------------------------------------------
4186 
4187 template<class Alloc>
4189 {
4190  BM_ASSERT(!is_ro());
4191 
4192  set_bit(n, val);
4193  return *this;
4194 }
4195 
4196 // -----------------------------------------------------------------------
4197 
4198 template<class Alloc>
4199 bool bvector<Alloc>::set_bit_conditional(size_type n, bool val, bool condition)
4200 {
4201  if (val == condition) return false;
4202  if (n >= size_)
4203  {
4204  size_type new_size = (n == bm::id_max) ? bm::id_max : n + 1;
4205  resize(new_size);
4206  }
4207  return set_bit_conditional_impl(n, val, condition);
4208 }
4209 
4210 // -----------------------------------------------------------------------
4211 
4212 template<class Alloc>
4214 {
4215  BM_ASSERT(!is_ro());
4216  BM_ASSERT(n < size_);
4217  BM_ASSERT_THROW(n < size_, BM_ERR_RANGE);
4218 
4219  if (!blockman_.is_init())
4220  blockman_.init_tree();
4221  return and_bit_no_check(n, val);
4222 }
4223 
4224 // -----------------------------------------------------------------------
4225 
4226 template<class Alloc>
4228 {
4229  BM_ASSERT(!is_ro());
4230  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
4231 
4232  if (!blockman_.is_init())
4233  blockman_.init_tree();
4234  if (n >= size_)
4235  {
4236  size_type new_size = (n == bm::id_max) ? bm::id_max : n + 1;
4237  resize(new_size);
4238  }
4239  return set_bit_no_check(n, val);
4240 }
4241 
4242 // -----------------------------------------------------------------------
4243 
4244 template<class Alloc>
4245 void bvector<Alloc>::import(const size_type* ids, size_type size_in,
4246  bm::sort_order sorted_idx)
4247 {
4248  BM_ASSERT(!is_ro());
4249 
4250  if (!size_in)
4251  return;
4252 
4253  size_type n, start(0), stop(size_in);
4254  block_idx_type nblock;
4255 
4256  n = ids[start];
4257  nblock = (n >> bm::set_block_shift);
4258 
4259  switch(sorted_idx)
4260  {
4261  case BM_SORTED:
4262  {
4263  block_idx_type nblock_end = (ids[size_in-1] >> bm::set_block_shift);
4264  if (nblock == nblock_end) // special case: one block import
4265  {
4266  import_block(ids, nblock, 0, stop);
4267  return;
4268  }
4269  // multi-block import, do top block space reservation
4270  unsigned i, j;
4271  bm::get_block_coord(nblock_end, i, j);
4273  }
4274  break;
4275  default:
4276  break;
4277  } // switch
4278 
4279  do
4280  {
4281  n = ids[start];
4282  nblock = (n >> bm::set_block_shift);
4283  #ifdef BM64ADDR
4284  stop = bm::idx_arr_block_lookup_u64(ids, size_in, nblock, start);
4285  #else
4286  stop = bm::idx_arr_block_lookup_u32(ids, size_in, nblock, start);
4287  #endif
4288  BM_ASSERT(start < stop);
4289  import_block(ids, nblock, start, stop);
4290  start = stop;
4291  } while (start < size_in);
4292 }
4293 
4294 // -----------------------------------------------------------------------
4295 
4296 template<class Alloc>
4298  const size_type size_in,
4299  bool opt_flag)
4300 {
4301  BM_ASSERT(size_in);
4302  BM_ASSERT(ids[0] < bm::id_max); // limit is 2^31-1 (for 32-bit mode)
4303  BM_ASSERT(ids[size_in-1] < bm::id_max);
4304 
4305  size_type n, start(0), stop = size_in;
4306  block_idx_type nblock, nblock_end;
4307 
4308  n = ids[start];
4309  nblock = (n >> bm::set_block_shift);
4310  nblock_end = (ids[size_in-1] >> bm::set_block_shift);
4311 
4312  if (nblock == nblock_end) // special (but frequent)case: one block import
4313  {
4314  import_block(ids, nblock, 0, stop);
4315  unsigned nbit = unsigned(ids[size_in-1] & bm::set_block_mask);
4316  if (opt_flag && nbit == 65535) // last bit in block
4317  {
4318  unsigned i, j;
4319  bm::get_block_coord(nblock, i, j);
4321  }
4322  }
4323  else
4324  {
4325  do
4326  {
4327  // TODO: use one-sided binary search to find the block limits
4328  #ifdef BM64ADDR
4329  stop = bm::idx_arr_block_lookup_u64(ids, size_in, nblock, start);
4330  #else
4331  stop = bm::idx_arr_block_lookup_u32(ids, size_in, nblock, start);
4332  #endif
4333  BM_ASSERT(start < stop);
4334 
4335  import_block(ids, nblock, start, stop);
4336  start = stop;
4337  nblock = (ids[stop] >> bm::set_block_shift);
4338  } while (start < size_in);
4339 
4340 
4341  if (opt_flag) // multi-block sorted import, lets optimize
4342  {
4343  n = ids[start];
4344  nblock = (n >> bm::set_block_shift);
4345  nblock_end = (ids[size_in-1] >> bm::set_block_shift);
4346  unsigned nbit = unsigned(ids[size_in-1] & bm::set_block_mask);
4347  nblock_end += bool(nbit == 65535);
4348  do
4349  {
4350  unsigned i, j;
4351  bm::get_block_coord(nblock++, i, j);
4353  } while (nblock < nblock_end);
4354  }
4355 
4356  }
4357 }
4358 
4359 
4360 // -----------------------------------------------------------------------
4361 
4362 template<class Alloc>
4364  block_idx_type nblock,
4365  size_type start,
4366  size_type stop)
4367 {
4368  BM_ASSERT(stop > start);
4369  int block_type;
4370  bm::word_t* blk =
4371  blockman_.check_allocate_block(nblock, 1, 0, &block_type,
4372  true/*allow NULL ret*/);
4373  if (!IS_FULL_BLOCK(blk))
4374  {
4375  if (BM_IS_GAP(blk))
4376  {
4377  if (stop-start == 1)
4378  {
4379  unsigned nbit = unsigned(ids[0] & bm::set_block_mask);
4380  gap_block_set_no_ret(BMGAP_PTR(blk), true, nblock, nbit);
4381  return;
4382  }
4383  blk = blockman_.deoptimize_block(nblock); // TODO: try to avoid
4384  }
4385  #ifdef BM64ADDR
4386  bm::set_block_bits_u64(blk, ids, start, stop);
4387  #else
4388  bm::set_block_bits_u32(blk, ids, start, stop);
4389  #endif
4390  if (new_blocks_strat_ == BM_GAP) // optimization required
4391  {
4392  BM_DECLARE_TEMP_BLOCK(temp_blk);
4393  unsigned i0, j0;
4394  bm::get_block_coord(nblock, i0, j0);
4395  blockman_.optimize_block(i0, j0, blk, temp_blk, opt_compress, 0);
4396  }
4397 
4398  if (nblock == bm::set_total_blocks-1)
4399  blk[bm::set_block_size-1] &= ~(1u<<31); // clear the "impossible" last just in case
4400  }
4401 }
4402 
4403 // -----------------------------------------------------------------------
4404 
4405 template<class Alloc>
4407 {
4408  BM_ASSERT(!is_ro());
4409  BM_ASSERT_THROW(idx1 < bm::id_max, BM_ERR_RANGE);
4410  BM_ASSERT_THROW(idx2 < bm::id_max, BM_ERR_RANGE);
4411 
4412  block_idx_type nb1 = (idx1 >> bm::set_block_shift);
4413  block_idx_type nb2 = (idx2 >> bm::set_block_shift);
4414 
4415  bm::word_t* block1, *block2;
4416  unsigned nbit1, nbit2;
4417  nbit1 = unsigned(idx1 & bm::set_block_mask);
4418  nbit2 = unsigned(idx2 & bm::set_block_mask);
4419 
4420  if (nb1 == nb2) // same block hit
4421  {
4422  unsigned i0, j0;
4423  bm::get_block_coord(nb1, i0, j0);
4424  block1 = blockman_.get_block_ptr(i0, j0);
4425  if (!block1 || (block1==FULL_BLOCK_FAKE_ADDR)) // nothing to do?
4426  return;
4427 
4428  if (BM_IS_GAP(block1))
4429  {
4430  bm::gap_word_t* gblk = BMGAP_PTR(block1);
4431  bool b1 = bm::gap_test_unr(gblk, nbit1);
4432  bool b2 = bm::gap_test_unr(gblk, nbit2);
4433  if (b1 != b2)
4434  {
4435  this->gap_block_set_no_ret(gblk, b2, nb1, nbit1);
4436  block2 = blockman_.get_block_ptr(i0, j0);
4437  if (block1 == block2) // same block
4438  this->gap_block_set_no_ret(gblk, b1, nb1, nbit2);
4439  else
4440  set_bit_no_check(idx2, b1);
4441  }
4442  return;
4443  }
4444  unsigned nword1 = unsigned(nbit1 >> bm::set_word_shift);
4445  unsigned nword2 = unsigned(nbit2 >> bm::set_word_shift);
4446  nbit1 &= bm::set_word_mask; nbit2 &= bm::set_word_mask;
4447  bool b1 = block1[nword1] & (1u << nbit1);
4448  bool b2 = block1[nword2] & (1u << nbit2);
4449  if (b1 != b2)
4450  {
4451  nbit1 = 1u << nbit1; nbit2 = 1u << nbit2;
4452  auto w = block1[nword1];
4453  (b2) ? w |= nbit1 : w &= ~nbit1;
4454  block1[nword1] = w;
4455  w = block1[nword2];
4456  (b1) ? w |= nbit2 : w &= ~nbit2;
4457  block1[nword2] = w;
4458  }
4459  return;
4460  } // if (same block)
4461 
4462  {
4463  unsigned i0, j0;
4464  bm::get_block_coord(nb1, i0, j0);
4465  block1 = blockman_.get_block_ptr(i0, j0);
4466  bm::get_block_coord(nb2, i0, j0);
4467  block2 = blockman_.get_block_ptr(i0, j0);
4468  }
4469  if (block1 == block2) // nothing to do
4470  return;
4471 
4472  bm::gap_word_t *gblk1{0}, *gblk2{0};
4473  unsigned cpos1{ 0 }, cpos2{ 0 };
4474  bool b1, b2, b1real, b2real;
4475 
4476  if (!block1)
4477  {
4478  b1 = false; b1real = false;
4479  }
4480  else
4481  if (block1 == FULL_BLOCK_FAKE_ADDR)
4482  {
4483  b1 = true; b1real = false;
4484  }
4485  else
4486  {
4487  b1real = true;
4488  nbit1 = unsigned(idx1 & bm::set_block_mask);
4489  if (BM_IS_GAP(block1))
4490  {
4491  gblk1 = BMGAP_PTR(block1);
4492  unsigned is_set;
4493  cpos1 = bm::gap_bfind(gblk1, nbit1, &is_set);
4494  b1 = is_set;
4495  }
4496  else // bit block
4497  {
4498  unsigned nword1 = unsigned(nbit1 >> bm::set_word_shift);
4499  b1 = block1[nword1] & (1u << (nbit1 & bm::set_word_mask));
4500  }
4501  }
4502 
4503  if (!block2)
4504  {
4505  b2 = false; b2real = false;
4506  }
4507  else
4508  if (block2 == FULL_BLOCK_FAKE_ADDR)
4509  {
4510  b2 = true; b2real = false;
4511  }
4512  else
4513  {
4514  b2real = true;
4515  nbit2 = unsigned(idx2 & bm::set_block_mask);
4516  if (BM_IS_GAP(block2))
4517  {
4518  gblk2 = BMGAP_PTR(block2);
4519  unsigned is_set;
4520  cpos2 = bm::gap_bfind(gblk2, nbit2, &is_set);
4521  b2 = is_set;
4522  }
4523  else // bit block
4524  {
4525  unsigned nword2 = unsigned(nbit2 >> bm::set_word_shift);
4526  b2 = block2[nword2] & (1u << (nbit2 & bm::set_word_mask));
4527  }
4528  }
4529 
4530  if (b1 == b2)
4531  return;
4532 
4533  if (b1real)
4534  {
4535  if (BM_IS_GAP(block1))
4536  {
4537  unsigned new_len, old_len;
4538  unsigned is_set = b1;
4539  old_len = bm::gap_length(gblk1)-1;
4540  new_len = bm::gap_set_value_cpos(b2, gblk1, nbit1, &is_set, cpos1);
4541  if (old_len < new_len)
4542  {
4543  unsigned threshold = bm::gap_limit(gblk1, blockman_.glen());
4544  if (new_len > threshold)
4545  blockman_.extend_gap_block(nb1, gblk1);
4546  }
4547  }
4548  else // bit block
4549  {
4550  unsigned nword1 = unsigned(nbit1 >> bm::set_word_shift);
4551  nbit1 = 1u << (nbit1 & bm::set_word_mask);
4552  auto w = block1[nword1];
4553  (b2) ? w |= nbit1 : w &= ~nbit1;
4554  block1[nword1] = w;
4555  }
4556  }
4557  else // block
4558  {
4559  set_bit_no_check(idx1, b2);
4560  }
4561 
4562  if (b2real)
4563  {
4564  if (BM_IS_GAP(block2))
4565  {
4566  unsigned new_len, old_len;
4567  unsigned is_set = b2;
4568  old_len = bm::gap_length(gblk2)-1;
4569  new_len = bm::gap_set_value_cpos(b1, gblk2, nbit2, &is_set, cpos2);
4570  if (old_len < new_len)
4571  {
4572  unsigned threshold = bm::gap_limit(gblk2, blockman_.glen());
4573  if (new_len > threshold)
4574  blockman_.extend_gap_block(nb2, gblk2);
4575  }
4576  }
4577  else // bit block
4578  {
4579  unsigned nword2 = unsigned(nbit2 >> bm::set_word_shift);
4580  nbit2 = 1u << (nbit2 & bm::set_word_mask);
4581  auto w = block2[nword2];
4582  (b1) ? w |= nbit2 : w &= ~nbit2;
4583  block2[nword2] = w;
4584  }
4585  }
4586  else
4587  {
4588  set_bit_no_check(idx2, b1);
4589  }
4590 
4591 
4592 }
4593 
4594 // -----------------------------------------------------------------------
4595 
4596 template<class Alloc>
4598 {
4599  BM_ASSERT(!is_ro());
4600  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
4601 
4602  // calculate logical block number
4603  block_idx_type nblock = (n >> bm::set_block_shift);
4604 
4605  int block_type;
4606  bm::word_t* blk =
4608  val,
4610  &block_type);
4611 
4612  if (!IS_VALID_ADDR(blk))
4613  return false;
4614 
4615  // calculate word number in block and bit
4616  unsigned nbit = unsigned(n & bm::set_block_mask);
4617  if (block_type) // gap
4618  {
4619  return gap_block_set(BMGAP_PTR(blk), val, nblock, nbit);
4620  }
4621  else // bit block
4622  {
4623  unsigned nword = unsigned(nbit >> bm::set_word_shift);
4624  nbit &= bm::set_word_mask;
4625  bm::word_t* word = blk + nword;
4626  bm::word_t mask = (((bm::word_t)1) << nbit);
4627 
4628  if (val)
4629  {
4630  val = ~(*word & mask);
4631  *word |= mask; // set bit
4632  return val;
4633  }
4634  else
4635  {
4636  val = ~(*word & mask);
4637  *word &= ~mask; // clear bit
4638  return val;
4639  }
4640  }
4641 }
4642 
4643 // -----------------------------------------------------------------------
4644 
4645 template<class Alloc>
4647 {
4648  BM_ASSERT(!is_ro());
4649  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
4650 
4651  const bool val = true; // set bit
4652 
4653  block_idx_type nblock = (n >> bm::set_block_shift);
4654  unsigned nbit = unsigned(n & bm::set_block_mask);
4655 
4656  int block_type;
4657  bm::word_t* blk =
4659  val,
4661  &block_type);
4662  if (!IS_VALID_ADDR(blk))
4663  return;
4664 
4665  if (block_type) // gap block
4666  {
4667  this->gap_block_set_no_ret(BMGAP_PTR(blk), val, nblock, nbit);
4668  }
4669  else // bit block
4670  {
4671  unsigned nword = nbit >> bm::set_word_shift;
4672  nbit &= bm::set_word_mask;
4673  blk[nword] |= (1u << nbit); // set bit
4674  }
4675 }
4676 
4677 // -----------------------------------------------------------------------
4678 
4679 template<class Alloc>
4681 {
4682  BM_ASSERT(!is_ro());
4683  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
4684 
4685  const bool val = false; // clear bit
4686 
4687  block_idx_type nblock = (n >> bm::set_block_shift);
4688  int block_type;
4689  bm::word_t* blk =
4691  val,
4693  &block_type);
4694  if (!blk)
4695  return;
4696 
4697  unsigned nbit = unsigned(n & bm::set_block_mask);
4698  if (block_type) // gap
4699  {
4700  this->gap_block_set_no_ret(BMGAP_PTR(blk), val, nblock, nbit);
4701  }
4702  else // bit block
4703  {
4704  unsigned nword = unsigned(nbit >> bm::set_word_shift);
4705  nbit &= bm::set_word_mask;
4706  blk[nword] &= ~(1u << nbit); // clear bit
4707  }
4708 }
4709 
4710 
4711 // -----------------------------------------------------------------------
4712 
4713 template<class Alloc>
4715  bool val, block_idx_type nblock,
4716  unsigned nbit)
4717 {
4718  unsigned is_set, new_len, old_len;
4719  old_len = bm::gap_length(gap_blk)-1;
4720  new_len = bm::gap_set_value(val, gap_blk, nbit, &is_set);
4721  if (old_len < new_len)
4722  {
4723  unsigned threshold = bm::gap_limit(gap_blk, blockman_.glen());
4724  if (new_len > threshold)
4725  blockman_.extend_gap_block(nblock, gap_blk);
4726  }
4727  return is_set;
4728 }
4729 
4730 // -----------------------------------------------------------------------
4731 
4732 template<class Alloc>
4734  bool val, block_idx_type nblock, unsigned nbit)
4735 {
4736  unsigned new_len, old_len;
4737  old_len = bm::gap_length(gap_blk)-1;
4738  new_len = bm::gap_set_value(val, gap_blk, nbit);
4739  if (old_len < new_len)
4740  {
4741  unsigned threshold = bm::gap_limit(gap_blk, blockman_.glen());
4742  if (new_len > threshold)
4743  blockman_.extend_gap_block(nblock, gap_blk);
4744  }
4745 }
4746 
4747 
4748 // -----------------------------------------------------------------------
4749 
4750 template<class Alloc>
4752 {
4753  BM_ASSERT(!is_ro());
4754  // calculate logical block number
4755  block_idx_type nblock = (n >> bm::set_block_shift);
4756  bm::word_t* blk =
4759  BM_ASSERT(IS_VALID_ADDR(blk));
4760 
4761  unsigned nbit = unsigned(n & bm::set_block_mask);
4762  unsigned is_set;
4763  if (BM_IS_GAP(blk))
4764  {
4765  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
4766  is_set = (bm::gap_test_unr(gap_blk, nbit) != 0);
4767  this->gap_block_set(gap_blk, !is_set, nblock, nbit); // flip
4768  }
4769  else // bit block
4770  {
4771  unsigned nword = unsigned(nbit >> bm::set_word_shift);
4772  nbit &= bm::set_word_mask;
4773  bm::word_t* word = blk + nword;
4774  const bm::word_t mask = (((bm::word_t)1) << nbit);
4775  is_set = ((*word) & mask);
4776  *word ^= mask; // flip the bit
4777  }
4778  return is_set;
4779 }
4780 
4781 // -----------------------------------------------------------------------
4782 
4783 template<class Alloc>
4785  bool val,
4786  bool condition)
4787 {
4788  // calculate logical block number
4789  block_idx_type nblock = (n >> bm::set_block_shift);
4790  int block_type;
4791  bm::word_t* blk =
4793  val,
4795  &block_type);
4796  if (!IS_VALID_ADDR(blk))
4797  return false;
4798 
4799  // calculate word number in block and bit
4800  unsigned nbit = unsigned(n & bm::set_block_mask);
4801 
4802  if (block_type == 1) // gap
4803  {
4804  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
4805  unsigned is_set = gap_block_set(gap_blk, val, nblock, nbit);
4806  return is_set;
4807  }
4808  else // bit block
4809  {
4810  unsigned nword = unsigned(nbit >> bm::set_word_shift);
4811  nbit &= bm::set_word_mask;
4812 
4813  bm::word_t* word = blk + nword;
4814  bm::word_t mask = (((bm::word_t)1) << nbit);
4815  bool is_set = ((*word) & mask) != 0;
4816 
4817  if (is_set != condition)
4818  return false;
4819  if (is_set != val) // need to change bit
4820  {
4821  if (val) // set bit
4822  *word |= mask;
4823  else // clear bit
4824  *word &= ~mask;
4825  return true;
4826  }
4827  }
4828  return false;
4829 
4830 }
4831 
4832 // -----------------------------------------------------------------------
4833 
4834 
4835 template<class Alloc>
4837 {
4838  BM_ASSERT(!is_ro());
4839  // calculate logical block number
4840  block_idx_type nblock = (n >> bm::set_block_shift);
4841 
4842  int block_type;
4843  bm::word_t* blk =
4845  val,
4847  &block_type);
4848  if (!IS_VALID_ADDR(blk))
4849  return false;
4850 
4851  // calculate word number in block and bit
4852  unsigned nbit = unsigned(n & bm::set_block_mask);
4853 
4854  if (block_type == 1) // gap
4855  {
4856  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
4857  bool old_val = (bm::gap_test_unr(gap_blk, nbit) != 0);
4858 
4859  bool new_val = val & old_val;
4860  if (new_val != old_val)
4861  {
4862  unsigned is_set = gap_block_set(gap_blk, val, nblock, nbit);
4863  BM_ASSERT(is_set);
4864  return is_set;
4865  }
4866  }
4867  else // bit block
4868  {
4869  unsigned nword = unsigned(nbit >> bm::set_word_shift);
4870  nbit &= bm::set_word_mask;
4871 
4872  bm::word_t* word = blk + nword;
4873  bm::word_t mask = (((bm::word_t)1) << nbit);
4874  bool is_set = ((*word) & mask) != 0;
4875 
4876  bool new_val = is_set & val;
4877  if (new_val != val) // need to change bit
4878  {
4879  if (new_val) // set bit
4880  {
4881  *word |= mask;
4882  }
4883  else // clear bit
4884  {
4885  *word &= ~mask;
4886  }
4887  return true;
4888  }
4889  }
4890  return false;
4891 }
4892 
4893 //---------------------------------------------------------------------
4894 
4895 template<class Alloc>
4897 {
4898  if (from == bm::id_max)
4899  return false;
4900  if (!from)
4901  {
4902  return find(pos);
4903  }
4904  pos = check_or_next(from);
4905  return (pos != 0);
4906 }
4907 
4908 //---------------------------------------------------------------------
4909 
4910 template<class Alloc>
4912 {
4913  bool found;
4914 
4915  unsigned top_blocks = blockman_.top_block_size();
4916  if (!top_blocks)
4917  return false;
4918  for (unsigned i = top_blocks-1; true; --i)
4919  {
4920  const bm::word_t* const* blk_blk = blockman_.get_topblock(i);
4921  if (blk_blk)
4922  {
4923  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
4924  blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
4925 
4926  for (unsigned short j = bm::set_sub_array_size-1; true; --j)
4927  {
4928  const bm::word_t* blk = blk_blk[j];
4929  if (blk)
4930  {
4931  unsigned block_pos;
4932  if (blk == FULL_BLOCK_FAKE_ADDR)
4933  {
4934  block_pos = bm::gap_max_bits-1;
4935  found = true;
4936  }
4937  else
4938  {
4939  bool is_gap = BM_IS_GAP(blk);
4940  found = is_gap ? bm::gap_find_last(BMGAP_PTR(blk), &block_pos)
4941  : bm::bit_find_last(blk, &block_pos);
4942  }
4943  if (found)
4944  {
4945  block_idx_type base_idx =
4948  base_idx += j * bm::gap_max_bits;
4949  pos = base_idx + block_pos;
4950  return found;
4951  }
4952  }
4953 
4954  if (j == 0)
4955  break;
4956  } // for j
4957  } // if blk_blk
4958 
4959  if (i == 0)
4960  break;
4961  } // for i
4962  return false;
4963 }
4964 
4965 //---------------------------------------------------------------------
4966 
4967 template<class Alloc>
4969 {
4970  bool found;
4971  if (!blockman_.is_init())
4972  return false; // nothing to do
4973  if (!from)
4974  {
4975  pos = from;
4976  return this->test(from);
4977  }
4978 
4979  block_idx_type nb = (from >> bm::set_block_shift);
4980  unsigned i0, j0;
4981  bm::get_block_coord(nb, i0, j0);
4982 
4983  const bm::word_t* block = blockman_.get_block_ptr(i0, j0);
4984  if (block)
4985  {
4986  size_type base_idx;
4987  unsigned found_nbit;
4988  unsigned nbit = unsigned(from & bm::set_block_mask);
4989  found = bm::block_find_reverse(block, nbit, &found_nbit);
4990  if (found)
4991  {
4992  base_idx = bm::get_block_start<size_type>(i0, j0);
4993  pos = base_idx + found_nbit;
4994  return found;
4995  }
4996  }
4997 
4998  if (nb)
4999  --nb;
5000  else
5001  return false;
5002  bm::get_block_coord(nb, i0, j0);
5003 
5004  const bm::word_t* const* blk_blk = blockman_.get_topblock(i0);
5005  if (blk_blk)
5006  {
5007  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5008  blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
5009  for (unsigned j = j0; true; --j)
5010  {
5011  const bm::word_t* blk = blk_blk[j];
5012  if (blk)
5013  {
5014  unsigned block_pos;
5015  if (blk == FULL_BLOCK_FAKE_ADDR)
5016  {
5017  block_pos = bm::gap_max_bits-1;
5018  found = true;
5019  }
5020  else
5021  {
5022  bool is_gap = BM_IS_GAP(blk);
5023  found = is_gap ? bm::gap_find_last(BMGAP_PTR(blk), &block_pos)
5024  : bm::bit_find_last(blk, &block_pos);
5025  }
5026  if (found)
5027  {
5028  block_idx_type base_idx =
5031  base_idx += j * bm::gap_max_bits;
5032  pos = base_idx + block_pos;
5033  return found;
5034  }
5035  }
5036  if (!j)
5037  break;
5038  } // for j
5039  }
5040  if (i0)
5041  --i0;
5042  else
5043  return false;
5044 
5045  for (unsigned i = i0; true; --i)
5046  {
5047  blk_blk = blockman_.get_topblock(i);
5048  if (blk_blk)
5049  {
5050  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5051  blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
5052  for (unsigned short j = bm::set_sub_array_size-1; true; --j)
5053  {
5054  const bm::word_t* blk = blk_blk[j];
5055  if (blk)
5056  {
5057  unsigned block_pos;
5058  if (blk == FULL_BLOCK_FAKE_ADDR)
5059  {
5060  block_pos = bm::gap_max_bits-1;
5061  found = true;
5062  }
5063  else
5064  {
5065  bool is_gap = BM_IS_GAP(blk);
5066  found = is_gap ? bm::gap_find_last(BMGAP_PTR(blk), &block_pos)
5067  : bm::bit_find_last(blk, &block_pos);
5068  }
5069  if (found)
5070  {
5071  block_idx_type base_idx =
5074  base_idx += j * bm::gap_max_bits;
5075  pos = base_idx + block_pos;
5076  return found;
5077  }
5078  }
5079  if (!j)
5080  break;
5081  } // for j
5082  }
5083  if (i == 0)
5084  break;
5085  } // for i
5086 
5087  return false;
5088 }
5089 
5090 //---------------------------------------------------------------------
5091 
5092 template<class Alloc>
5094 {
5095  bool found;
5096 
5097  unsigned top_blocks = blockman_.top_block_size();
5098  for (unsigned i = 0; i < top_blocks; ++i)
5099  {
5100  const bm::word_t* const* blk_blk = blockman_.get_topblock(i);
5101  if (blk_blk)
5102  {
5103  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5104  blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
5105 
5106  for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
5107  {
5108  const bm::word_t* blk = blk_blk[j];
5109  if (blk)
5110  {
5111  unsigned block_pos;
5112  if (blk == FULL_BLOCK_FAKE_ADDR)
5113  {
5114  found = true; block_pos = 0;
5115  }
5116  else
5117  {
5118  bool is_gap = BM_IS_GAP(blk);
5119  found = (is_gap) ? bm::gap_find_first(BMGAP_PTR(blk), &block_pos)
5120  : bm::bit_find_first(blk, &block_pos);
5121  }
5122  if (found)
5123  {
5125  base_idx += j * bm::gap_max_bits;
5126  pos = base_idx + block_pos;
5127  return found;
5128  }
5129  }
5130  } // for j
5131  } // if blk_blk
5132  } // for i
5133  return false;
5134 }
5135 
5136 //---------------------------------------------------------------------
5137 
5138 template<class Alloc>
5140  size_type& in_last) const BMNOEXCEPT
5141 {
5142  bool found = find(in_first);
5143  if (found)
5144  {
5145  found = find_reverse(in_last);
5146  BM_ASSERT(found);
5147  BM_ASSERT(in_first <= in_last);
5148  }
5149  else
5150  {
5151  in_first = in_last = 0; // zero the output just in case
5152  }
5153  return found;
5154 }
5155 
5156 //---------------------------------------------------------------------
5157 
5158 template<class Alloc>
5160  size_type from,
5161  size_type& pos) const BMNOEXCEPT
5162 {
5163  BM_ASSERT_THROW(from < bm::id_max, BM_ERR_RANGE);
5164 
5165  bool ret = false;
5166 
5167  if (!rank_in || !blockman_.is_init())
5168  return ret;
5169 
5170  block_idx_type nb = (from >> bm::set_block_shift);
5172  unsigned bit_pos = 0;
5173 
5174  for (; nb < bm::set_total_blocks; ++nb)
5175  {
5176  int no_more_blocks;
5177  const bm::word_t* block = blockman_.get_block(nb, &no_more_blocks);
5178  if (block)
5179  {
5180  if (!nbit && (rank_in > bm::gap_max_bits)) // requested rank cannot be in this block
5181  {
5182  unsigned cnt = blockman_.block_bitcount(block);
5183  BM_ASSERT(cnt < rank_in);
5184  rank_in -= cnt;
5185  continue;
5186  }
5187  else
5188  {
5189  rank_in = bm::block_find_rank(block, rank_in, nbit, bit_pos);
5190  if (!rank_in) // target found
5191  {
5192  pos = bit_pos + (nb * bm::set_block_size * 32);
5193  return true;
5194  }
5195  }
5196  }
5197  else
5198  {
5199  // TODO: better next block search
5200  if (no_more_blocks)
5201  break;
5202  }
5203  nbit ^= nbit; // zero start bit after first scanned block
5204  } // for nb
5205 
5206  return ret;
5207 }
5208 
5209 //---------------------------------------------------------------------
5210 
5211 template<class Alloc>
5213  size_type from,
5214  size_type& pos,
5215  const rs_index_type& rs_idx) const BMNOEXCEPT
5216 {
5217  BM_ASSERT_THROW(from < bm::id_max, BM_ERR_RANGE);
5218 
5219  bool ret = false;
5220 
5221  if (!rank_in ||
5222  !blockman_.is_init() ||
5223  (rs_idx.count() < rank_in))
5224  return ret;
5225 
5226  block_idx_type nb;
5227  if (from)
5228  nb = (from >> bm::set_block_shift);
5229  else
5230  {
5231  nb = rs_idx.find(rank_in);
5232  BM_ASSERT(rs_idx.rcount(nb) >= rank_in);
5233  if (nb)
5234  rank_in -= rs_idx.rcount(nb-1);
5235  }
5236 
5238  unsigned bit_pos = 0;
5239 
5240  for (; nb < rs_idx.get_total(); ++nb)
5241  {
5242  int no_more_blocks;
5243  const bm::word_t* block = blockman_.get_block(nb, &no_more_blocks);
5244  if (block)
5245  {
5246  if (!nbit) // check if the whole block can be skipped
5247  {
5248  unsigned block_bc = rs_idx.count(nb);
5249  if (rank_in <= block_bc) // target block
5250  {
5251  nbit = rs_idx.select_sub_range(nb, rank_in);
5252  rank_in = bm::block_find_rank(block, rank_in, nbit, bit_pos);
5253  BM_ASSERT(rank_in == 0);
5254  pos = bit_pos + (nb * bm::set_block_size * 32);
5255  return true;
5256  }
5257  rank_in -= block_bc;
5258  continue;
5259  }
5260 
5261  rank_in = bm::block_find_rank(block, rank_in, nbit, bit_pos);
5262  if (!rank_in) // target found
5263  {
5264  pos = bit_pos + (nb * bm::set_block_size * 32);
5265  return true;
5266  }
5267  }
5268  else
5269  {
5270  // TODO: better next block search
5271  if (no_more_blocks)
5272  break;
5273  }
5274  nbit ^= nbit; // zero start bit after first scanned block
5275  } // for nb
5276 
5277  return ret;
5278 }
5279 
5280 //---------------------------------------------------------------------
5281 
5282 template<class Alloc>
5284  const rs_index_type& rs_idx) const BMNOEXCEPT
5285 {
5286  bool ret = false;
5287 
5288  if (!rank_in ||
5289  !blockman_.is_init() ||
5290  (rs_idx.count() < rank_in))
5291  return ret;
5292 
5293  block_idx_type nb;
5294  bm::gap_word_t sub_range_from;
5295  bool found = rs_idx.find(&rank_in, &nb, &sub_range_from);
5296  if (!found)
5297  return found;
5298 
5299  unsigned i, j;
5300  bm::get_block_coord(nb, i, j);
5301  const bm::word_t* block = blockman_.get_block_ptr(i, j);
5302  BM_ASSERT(block);
5303  BM_ASSERT(rank_in <= rs_idx.count(nb));
5304 
5305  unsigned bit_pos = 0;
5306  if (block == FULL_BLOCK_FAKE_ADDR)
5307  {
5308  BM_ASSERT(rank_in <= bm::gap_max_bits);
5309  bit_pos = sub_range_from + unsigned(rank_in) - 1;
5310  }
5311  else
5312  {
5313  rank_in = bm::block_find_rank(block, rank_in, sub_range_from, bit_pos);
5314  BM_ASSERT(rank_in == 0);
5315  }
5316  pos = bit_pos + (nb * bm::set_block_size * 32);
5317  return true;
5318 }
5319 
5320 //---------------------------------------------------------------------
5321 
5322 template<class Alloc>
5323 typename bvector<Alloc>::size_type
5325 {
5326  if (!blockman_.is_init())
5327  return 0;
5328 
5329  // calculate logical block number
5331  unsigned i, j;
5332  bm::get_block_coord(nb, i, j);
5333  const bm::word_t* block = blockman_.get_block_ptr(i, j);
5334 
5335  if (block)
5336  {
5337  unsigned block_pos;
5338  bool found = false;
5339  // calculate word number in block and bit
5340  unsigned nbit = unsigned(prev & bm::set_block_mask);
5341  if (BM_IS_GAP(block))
5342  {
5343  if (bm::gap_block_find(BMGAP_PTR(block), nbit, &block_pos))
5344  {
5345  prev = (size_type(nb) * bm::gap_max_bits) + block_pos;
5346  return prev;
5347  }
5348  }
5349  else
5350  {
5351  if (block == FULL_BLOCK_FAKE_ADDR)
5352  return prev;
5353  found = bm::bit_block_find(block, nbit, &block_pos);
5354  if (found)
5355  {
5356  prev = (size_type(nb) * bm::gap_max_bits) + block_pos;
5357  return prev;
5358  }
5359  }
5360  }
5361  ++j;
5362  block_idx_type top_blocks = blockman_.top_block_size();
5363  for (; i < top_blocks; ++i)
5364  {
5365  const bm::word_t* const* blk_blk = blockman_.get_topblock(i);
5366  if (blk_blk)
5367  {
5368  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5369  blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
5370 
5371  for (; j < bm::set_sub_array_size; ++j)
5372  {
5373  const bm::word_t* blk = blk_blk[j];
5374  if (blk)
5375  {
5376  bool found;
5377  unsigned block_pos;
5378  if (blk == FULL_BLOCK_FAKE_ADDR)
5379  {
5380  found = true; block_pos = 0;
5381  }
5382  else
5383  {
5384  bool is_gap = BM_IS_GAP(blk);
5385  found = (is_gap) ? bm::gap_find_first(BMGAP_PTR(blk), &block_pos)
5386  : bm::bit_find_first(blk, &block_pos);
5387  }
5388  if (found)
5389  {
5390  size_type base_idx = size_type(i) * bm::bits_in_array;
5391  base_idx += j * bm::gap_max_bits;
5392  prev = base_idx + block_pos;
5393  return prev;
5394  }
5395  }
5396  } // for j
5397  }
5398  j = 0;
5399  } // for i
5400 
5401  return 0;
5402 }
5403 
5404 //---------------------------------------------------------------------
5405 
5406 template<class Alloc>
5409 {
5410  BM_ASSERT(!is_ro());
5411  if (!blockman_.is_init())
5412  return 0;
5413  // TODO: optimization
5414  size_type pos = this->check_or_next(prev);
5415  if (pos >= prev)
5416  this->clear_bit_no_check(pos);
5417  return pos;
5418 }
5419 
5420 //---------------------------------------------------------------------
5421 
5422 template<class Alloc>
5424 {
5425  BM_ASSERT(!is_ro());
5426  return insert(0, false);
5427 }
5428 
5429 //---------------------------------------------------------------------
5430 
5431 template<class Alloc>
5433 {
5434  BM_ASSERT(!is_ro());
5435  bool b = this->test(0);
5436  this->erase(0);
5437  return b;
5438 }
5439 
5440 //---------------------------------------------------------------------
5441 
5442 template<class Alloc>
5443 bool bvector<Alloc>::insert(size_type n, bool value)
5444 {
5445  BM_ASSERT(!is_ro());
5446  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
5447 
5448  if (size_ < bm::id_max)
5449  ++size_;
5450  if (!blockman_.is_init())
5451  {
5452  if (value)
5453  set(n);
5454  return 0;
5455  }
5456 
5457  // calculate logical block number
5459 
5460  int block_type;
5461  bm::word_t carry_over = 0;
5462 
5463  // 1: process target block insertion
5464  if (value || n)
5465  {
5466  unsigned i, j;
5467  bm::get_block_coord(nb, i, j);
5468  bm::word_t* block = blockman_.get_block_ptr(i, j);
5469 
5470  const unsigned nbit = unsigned(n & bm::set_block_mask);
5471  if (!block)
5472  {
5473  if (value)
5474  {
5476  goto insert_bit_check;
5477  }
5478  }
5479  else
5480  {
5481  insert_bit_check:
5482  if (BM_IS_GAP(block))
5483  {
5484  unsigned new_block_len;
5485  bm::gap_word_t* gap_blk = BMGAP_PTR(block);
5486  carry_over = bm::gap_insert(gap_blk, nbit, value, &new_block_len);
5487  unsigned threshold = bm::gap_limit(gap_blk, blockman_.glen());
5488  if (new_block_len > threshold)
5489  blockman_.extend_gap_block(nb, gap_blk);
5490  }
5491  else
5492  {
5493  if (IS_FULL_BLOCK(block))
5494  {
5495  if (!value)
5496  {
5497  block = blockman_.deoptimize_block(nb);
5498  goto insert_bit;
5499  }
5500  carry_over = 1;
5501  }
5502  else // BIT block
5503  {
5504  insert_bit:
5505  BM_ASSERT(IS_VALID_ADDR(block));
5506  carry_over = bm::bit_block_insert(block, nbit, value);
5507  }
5508  }
5509  }
5510  ++nb;
5511  }
5512 
5513  // 2: shift right everything else
5514  //
5515  unsigned i0, j0;
5516  bm::get_block_coord(nb, i0, j0);
5517 
5518  unsigned top_blocks = blockman_.top_block_size();
5519  bm::word_t*** blk_root = blockman_.top_blocks_root();
5520  bm::word_t** blk_blk;
5521  bm::word_t* block;
5522 
5523  for (unsigned i = i0; i < bm::set_top_array_size; ++i)
5524  {
5525  if (i >= top_blocks)
5526  {
5527  if (!carry_over)
5528  break;
5529  blk_blk = 0;
5530  }
5531  else
5532  blk_blk = blk_root[i];
5533 
5534  if (!blk_blk) // top level group of blocks missing - can skip it
5535  {
5536  if (carry_over)
5537  {
5538  // carry over: needs block-list extension and a block
5540  if (nblock > nb)
5541  {
5542  block =
5543  blockman_.check_allocate_block(nblock, 0, 0, &block_type, false);
5544  block[0] |= carry_over; // block is brand new (0000)
5545 
5546  // reset all control vars (blocks tree may have re-allocated)
5547  blk_root = blockman_.top_blocks_root();
5548  blk_blk = blk_root[i];
5549  top_blocks = blockman_.top_block_size();
5550 
5551  carry_over = 0;
5552  }
5553  }
5554  continue;
5555  }
5556  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5557  {
5558  if (carry_over)
5559  continue;
5561  }
5562 
5563  unsigned j = j0;
5564  do
5565  {
5567  block = blk_blk[j];
5568  if (!block)
5569  {
5570  if (carry_over)
5571  {
5572  size_type nbit = nblock * bm::gap_max_bits;
5573  set_bit_no_check(nbit);
5574  carry_over = 0; block = 0;
5575  }
5576  // no CO: tight loop scan for the next available block (if any)
5577  for (++j; j < bm::set_sub_array_size; ++j)
5578  {
5579  if (0 != (block = blk_blk[j]))
5580  {
5581  nblock = (i * bm::set_sub_array_size) + j;
5582  break;
5583  }
5584  } // for j
5585  if (!block) // no more blocks in this j-dimention
5586  continue;
5587  }
5588  if (IS_FULL_BLOCK(block))
5589  {
5590  // 1 in 1 out, block is still all 0xFFFF..
5591  // 0 into 1 -> carry in 0, carry out 1
5592  if (!carry_over)
5593  {
5594  block = blockman_.deoptimize_block(nblock);
5595  block[0] <<= (carry_over = 1);
5596  }
5597  continue;
5598  }
5599  if (BM_IS_GAP(block))
5600  {
5601  if (nblock == bm::set_total_blocks-1) // last block
5602  {
5603  // process as a bit-block (for simplicity)
5604  block = blockman_.deoptimize_block(nblock);
5605  }
5606  else // use gap-block shift here
5607  {
5608  unsigned new_block_len;
5609  bm::gap_word_t* gap_blk = BMGAP_PTR(block);
5610 
5611  carry_over = bm::gap_shift_r1(gap_blk, carry_over, &new_block_len);
5612  unsigned threshold = bm::gap_limit(gap_blk, blockman_.glen());
5613  if (new_block_len > threshold)
5614  blockman_.extend_gap_block(nblock, gap_blk);
5615  continue;
5616  }
5617  }
5618  // bit-block
5619  {
5620  bm::word_t acc;
5621  carry_over = bm::bit_block_shift_r1_unr(block, &acc, carry_over);
5622  BM_ASSERT(carry_over <= 1);
5623 
5624  if (nblock == bm::set_total_blocks-1) // last possible block
5625  {
5626  carry_over = block[bm::set_block_size-1] & (1u<<31);
5627  block[bm::set_block_size-1] &= ~(1u<<31); // clear the 1-bit tail
5628  if (!acc) // block shifted out: release memory
5629  blockman_.zero_block(nblock);
5630  break;
5631  }
5632  if (!acc)
5633  blockman_.zero_block(nblock);
5634  }
5635 
5636  } while (++j < bm::set_sub_array_size);
5637  j0 = 0;
5638  } // for i
5639  return carry_over;
5640 
5641 }
5642 
5643 //---------------------------------------------------------------------
5644 
5645 template<class Alloc>
5647 {
5648  BM_ASSERT(!is_ro());
5649  BM_ASSERT_THROW(n < bm::id_max, BM_ERR_RANGE);
5650 
5651  if (!blockman_.is_init())
5652  return ;
5653 
5654  // calculate logical block number
5656 
5657  if (!n ) // regular shift-left by 1 bit
5658  {}
5659  else // process target block bit erase
5660  {
5661  unsigned i, j;
5662  bm::get_block_coord(nb, i, j);
5663  bm::word_t* block = blockman_.get_block_ptr(i, j);
5664  bool carry_over = test_first_block_bit(nb+1);
5665  if (!block)
5666  {
5667  if (carry_over)
5668  {
5669  block = blockman_.check_allocate_block(nb, BM_BIT);
5670  block[bm::set_block_size-1] = (1u << 31u);
5671  }
5672  }
5673  else
5674  {
5675  if (BM_IS_GAP(block) || IS_FULL_BLOCK(block))
5676  block = blockman_.deoptimize_block(nb);
5677  BM_ASSERT(IS_VALID_ADDR(block));
5678  unsigned nbit = unsigned(n & bm::set_block_mask);
5679  bm::bit_block_erase(block, nbit, carry_over);
5680  }
5681  ++nb;
5682  }
5683  // left shifting of all other blocks
5684  //
5685  unsigned i0, j0;
5686  bm::get_block_coord(nb, i0, j0);
5687 
5688  unsigned top_blocks = blockman_.top_block_size();
5689  bm::word_t*** blk_root = blockman_.top_blocks_root();
5690  bm::word_t** blk_blk;
5691  bm::word_t* block;
5692 
5693  for (unsigned i = i0; i < bm::set_top_array_size; ++i)
5694  {
5695  if (i >= top_blocks)
5696  break;
5697  else
5698  blk_blk = blk_root[i];
5699 
5700  if (!blk_blk) // top level group of blocks missing
5701  {
5702  bool found = bm::find_not_null_ptr(blk_root, i+1, top_blocks, &i);
5703  if (!found)
5704  break;
5705  --i;
5706  continue;
5707  }
5708  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5709  {
5710  bool carry_over = 0;
5711  if (i + 1 < bm::set_top_array_size)
5712  {
5714  carry_over = this->test(co_idx);
5715  if (carry_over)
5716  continue; // nothing to do (1 in)
5717  else
5719  }
5720  else
5721  {
5723  }
5724  }
5725 
5726  unsigned j = j0;
5727  do
5728  {
5730  bool carry_over = 0; // test_first_block_bit(nblock+1); // look ahead for CO
5731  block = blk_blk[j];
5732  if (!block)
5733  {
5734  // no CO: tight loop scan for the next available block (if any)
5735  bool no_blocks = (j == 0);
5736  for (++j; j < bm::set_sub_array_size; ++j)
5737  {
5738  if (0 != (block = blk_blk[j]))
5739  {
5740  nblock = (block_idx_type(i) * bm::set_sub_array_size) + j;
5741  break;
5742  }
5743  } // for j
5744  if (!block) // no more blocks in this j-dimention ?
5745  {
5746  if (j == bm::set_sub_array_size && no_blocks)
5747  {
5748  blockman_.zero_block(i, j-1); // free the top level
5749  }
5750  continue;
5751  }
5752  }
5753  BM_ASSERT(block);
5754  if (IS_FULL_BLOCK(block))
5755  {
5756  carry_over = test_first_block_bit(nblock+1); // look ahead for CO
5757  // 1 in 1 out, block is still all 0xFFFF..
5758  // 0 into 1 -> carry in 0, carry out 1
5759  if (!carry_over)
5760  {
5761  block = blockman_.deoptimize_block(nblock);
5762  block[bm::set_block_size-1] >>= 1;
5763  }
5764  carry_over = 1;
5765  }
5766  else
5767  if (BM_IS_GAP(block))
5768  {
5769  carry_over = test_first_block_bit(nblock+1); // look ahead for CO
5770  unsigned new_block_len;
5771  bm::gap_word_t* gap_blk = BMGAP_PTR(block);
5772 
5773  carry_over = bm::gap_shift_l1(gap_blk, carry_over, &new_block_len);
5774  unsigned threshold = bm::gap_limit(gap_blk, blockman_.glen());
5775  if (new_block_len > threshold)
5776  blockman_.extend_gap_block(nblock, gap_blk);
5777  else
5778  {
5779  if (bm::gap_is_all_zero(gap_blk))
5780  blockman_.zero_block(i, j);
5781  }
5782  }
5783  else // bit-block
5784  {
5785  bm::word_t acc;
5786  carry_over = bm::bit_block_shift_l1_unr(block, &acc, carry_over);
5787  if (!acc)
5788  blockman_.zero_block(i, j);
5789  }
5790 
5791  if (carry_over && nblock)
5792  {
5794  }
5795 
5796  } while (++j < bm::set_sub_array_size);
5797  j0 = 0;
5798  } // for i
5799 
5800 }
5801 
5802 //---------------------------------------------------------------------
5803 
5804 template<class Alloc>
5806 {
5807  if (nb >= bm::set_total_blocks) // last possible block
5808  return false;
5809  return test(nb * bm::gap_max_bits);
5810 }
5811 
5812 
5813 //---------------------------------------------------------------------
5814 
5815 template<class Alloc>
5817 {
5818  BM_ASSERT(!is_ro());
5819 
5820  if (!bv.blockman_.is_init()) // nothing to OR
5821  return;
5822 
5823  if (bv.is_ro()) // argument is immutable, just use OR
5824  {
5825  this->bit_or(bv);
5826  return;
5827  }
5828 
5829  unsigned top_blocks = blockman_.top_block_size();
5830  if (size_ < bv.size_) // this vect shorter than the arg.
5831  {
5832  size_ = bv.size_;
5833  }
5834  unsigned arg_top_blocks = bv.blockman_.top_block_size();
5835  top_blocks = blockman_.reserve_top_blocks(arg_top_blocks);
5836 
5837 
5838  bm::word_t*** blk_root = blockman_.top_blocks_root();
5839  bm::word_t*** blk_root_arg = bv.blockman_.top_blocks_root();
5840 
5841  for (unsigned i = 0; i < top_blocks; ++i)
5842  {
5843  bm::word_t** blk_blk = blk_root[i];
5844  bm::word_t** blk_blk_arg = (i < arg_top_blocks) ? blk_root_arg[i] : 0;
5845  if (blk_blk == blk_blk_arg || !blk_blk_arg) // nothing to do (0 OR 0 == 0)
5846  continue;
5847  if (!blk_blk && blk_blk_arg) // top block transfer
5848  {
5849  BM_ASSERT(i < arg_top_blocks);
5850 
5851  blk_root[i] = blk_root_arg[i];
5852  blk_root_arg[i] = 0;
5853  continue;
5854  }
5855  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
5856  continue;
5857  if ((bm::word_t*)blk_blk_arg == FULL_BLOCK_FAKE_ADDR)
5858  {
5860  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
5861  continue;
5862  }
5863 
5864  unsigned j = 0;
5865  bm::word_t* blk;
5866  bm::word_t* arg_blk;
5867  do
5868  {
5869  blk = blk_blk[j]; arg_blk = blk_blk_arg[j];
5870  if (blk != arg_blk)
5871  {
5872  if (!blk && arg_blk) // block transfer
5873  {
5874  blockman_.set_block_ptr(i, j, arg_blk);
5875  bv.blockman_.set_block_ptr(i, j, 0);
5876  }
5877  else // need full OR
5878  {
5879  combine_operation_block_or(i, j, blk, arg_blk);
5880  }
5881  }
5882  } while (++j < bm::set_sub_array_size);
5883  } // for i
5884 }
5885 
5886 //---------------------------------------------------------------------
5887 
5888 template<class Alloc>
5890  const bm::word_t* arg_blk,
5891  bool arg_gap,
5892  bm::operation opcode)
5893 {
5894  unsigned i0, j0;
5895  bm::get_block_coord(nb, i0, j0);
5896  bm::word_t* blk = blockman_.get_block_ptr(i0, j0);
5897 
5898  bool gap = BM_IS_GAP(blk);
5899  combine_operation_with_block(nb, gap, blk, arg_blk, arg_gap, opcode);
5900 }
5901 
5902 //---------------------------------------------------------------------
5903 
5904 template<class Alloc>
5907  const bm::bvector<Alloc>& bv2,
5908  typename bm::bvector<Alloc>::optmode opt_mode)
5909 {
5910  BM_ASSERT(!is_ro());
5911 
5912  if (blockman_.is_init())
5914 
5915  if (&bv1 == &bv2)
5916  {
5917  this->bit_or(bv2);
5918  return *this;
5919  }
5920  if (this == &bv1)
5921  {
5922  this->bit_or(bv2);
5923  return *this;
5924  }
5925  if (this == &bv2)
5926  {
5927  this->bit_or(bv1);
5928  return *this;
5929  }
5930 
5931  const blocks_manager_type& bman1 = bv1.get_blocks_manager();
5932  const blocks_manager_type& bman2 = bv2.get_blocks_manager();
5933 
5934  unsigned top_blocks1 = bman1.top_block_size();
5935  unsigned top_blocks2 = bman2.top_block_size();
5936  unsigned top_blocks = (top_blocks2 > top_blocks1) ? top_blocks2 : top_blocks1;
5937  top_blocks = blockman_.reserve_top_blocks(top_blocks);
5938 
5939  size_ = bv1.size_;
5940  if (size_ < bv2.size_)
5941  size_ = bv2.size_;
5942 
5943  bm::word_t*** blk_root_arg1 = bv1.blockman_.top_blocks_root();
5944  if (!blk_root_arg1)
5945  {
5946  this->bit_or(bv2);
5947  return *this;
5948  }
5949  bm::word_t*** blk_root_arg2 = bv2.blockman_.top_blocks_root();
5950  if (!blk_root_arg2)
5951  {
5952  this->bit_or(bv1);
5953  return *this;
5954  }
5955 
5956  for (unsigned i = 0; i < top_blocks; ++i)
5957  {
5958  bm::word_t** blk_blk_arg1 = (i < top_blocks1) ? blk_root_arg1[i] : 0;
5959  bm::word_t** blk_blk_arg2 = (i < top_blocks2) ? blk_root_arg2[i] : 0;
5960 
5961  if (blk_blk_arg1 == blk_blk_arg2)
5962  {
5963  BM_ASSERT(!blk_blk_arg1 || (bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR);
5964  bm::word_t*** blk_root = blockman_.top_blocks_root();
5965  blk_root[i] = blk_blk_arg1;
5966  continue;
5967  }
5968  if ((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR ||
5969  (bm::word_t*)blk_blk_arg2 == FULL_BLOCK_FAKE_ADDR)
5970  {
5971  bm::word_t*** blk_root = blockman_.top_blocks_root();
5972  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
5973  continue;
5974  }
5976  bool any_blocks = false;
5977  unsigned j = 0;
5978  do
5979  {
5980  const bm::word_t* arg_blk1 = blk_blk_arg1 ? blk_blk_arg1[j] : 0;
5981  const bm::word_t* arg_blk2 = blk_blk_arg2 ? blk_blk_arg2[j] : 0;
5982  if (arg_blk1 == arg_blk2 && !arg_blk1)
5983  continue;
5984  bool need_opt = combine_operation_block_or(i, j, arg_blk1, arg_blk2);
5985  if (need_opt && opt_mode == opt_compress)
5986  blockman_.optimize_bit_block(i, j, opt_mode);
5987  any_blocks |= bool(blk_blk[j]);
5988  } while (++j < bm::set_sub_array_size);
5989 
5990  if (!any_blocks)
5992 
5993  } // for i
5994 
5995  if (opt_mode != opt_none)
5997 
5998  return *this;
5999 }
6000 
6001 //---------------------------------------------------------------------
6002 
6003 template<class Alloc>
6006  const bm::bvector<Alloc>& bv2,
6007  typename bm::bvector<Alloc>::optmode opt_mode)
6008 {
6009  BM_ASSERT(!is_ro());
6010 
6011  if (blockman_.is_init())
6013 
6014  if (&bv1 == &bv2)
6015  return *this; // nothing to do empty result
6016 
6017  if (this == &bv1)
6018  {
6019  this->bit_xor(bv2);
6020  return *this;
6021  }
6022  if (this == &bv2)
6023  {
6024  this->bit_xor(bv1);
6025  return *this;
6026  }
6027 
6028  const blocks_manager_type& bman1 = bv1.get_blocks_manager();
6029  if (!bman1.is_init())
6030  {
6031  *this = bv2;
6032  return *this;
6033  }
6034  const blocks_manager_type& bman2 = bv2.get_blocks_manager();
6035  if (!bman2.is_init())
6036  {
6037  *this = bv1;
6038  return *this;
6039  }
6040 
6041  unsigned top_blocks1 = bman1.top_block_size();
6042  unsigned top_blocks2 = bman2.top_block_size();
6043  unsigned top_blocks = (top_blocks2 > top_blocks1) ? top_blocks2 : top_blocks1;
6044  top_blocks = blockman_.reserve_top_blocks(top_blocks);
6045 
6046  size_ = bv1.size_;
6047  if (size_ < bv2.size_)
6048  size_ = bv2.size_;
6049 
6050  bm::word_t*** blk_root_arg1 = bv1.blockman_.top_blocks_root();
6051  bm::word_t*** blk_root_arg2 = bv2.blockman_.top_blocks_root();
6052 
6053  for (unsigned i = 0; i < top_blocks; ++i)
6054  {
6055  bm::word_t** blk_blk_arg1 = (i < top_blocks1) ? blk_root_arg1[i] : 0;
6056  bm::word_t** blk_blk_arg2 = (i < top_blocks2) ? blk_root_arg2[i] : 0;
6057 
6058  if (blk_blk_arg1 == blk_blk_arg2)
6059  {
6060  if (!blk_blk_arg1)
6061  continue;
6062  BM_ASSERT((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR);
6064  continue;
6065  }
6066  if ((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR)
6067  {
6068  if (!blk_blk_arg2)
6069  {
6070  set_full_sb:
6071  bm::word_t*** blk_root= blockman_.top_blocks_root();
6072  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
6073  continue;
6074  }
6075  blk_blk_arg1 = FULL_SUB_BLOCK_REAL_ADDR;
6076  }
6077  if ((bm::word_t*)blk_blk_arg2 == FULL_BLOCK_FAKE_ADDR)
6078  {
6079  if (!blk_blk_arg1)
6080  goto set_full_sb;
6081  blk_blk_arg2 = FULL_SUB_BLOCK_REAL_ADDR;
6082  }
6083 
6085  bool any_blocks = false;
6086  unsigned j = 0;
6087  do
6088  {
6089  const bm::word_t* arg_blk1; const bm::word_t* arg_blk2;
6090  arg_blk1 = blk_blk_arg1 ? blk_blk_arg1[j] : 0;
6091  arg_blk2 = blk_blk_arg2 ? blk_blk_arg2[j] : 0;
6092 
6093  if ((arg_blk1 == arg_blk2) &&
6094  (!arg_blk1 || arg_blk1 == FULL_BLOCK_FAKE_ADDR))
6095  continue; // 0 ^ 0 == 0 , 1 ^ 1 == 0 (nothing to do)
6096 
6097  bool need_opt = combine_operation_block_xor(i, j, arg_blk1, arg_blk2);
6098  if (need_opt && opt_mode == opt_compress)
6099  blockman_.optimize_bit_block(i, j, opt_mode);
6100  any_blocks |= bool(blk_blk[j]);
6101  } while (++j < bm::set_sub_array_size);
6102 
6103  if (!any_blocks)
6105 
6106  } // for i
6107 
6108  if (opt_mode != opt_none)
6110 
6111  return *this;
6112 }
6113 
6114 //---------------------------------------------------------------------
6115 
6116 template<class Alloc>
6119  const bm::bvector<Alloc>& bv2,
6120  typename bm::bvector<Alloc>::optmode opt_mode)
6121 {
6122  BM_ASSERT(!is_ro());
6123 
6124  if (&bv1 == &bv2)
6125  {
6126  *this = bv1;
6127  return *this;
6128  }
6129  if (this == &bv1)
6130  {
6131  this->bit_and(bv2);
6132  return *this;
6133  }
6134  if (this == &bv2)
6135  {
6136  this->bit_and(bv1);
6137  return *this;
6138  }
6139  if (blockman_.is_init())
6141 
6142  const blocks_manager_type& bman1 = bv1.get_blocks_manager();
6143  const blocks_manager_type& bman2 = bv2.get_blocks_manager();
6144  if (!bman1.is_init() || !bman2.is_init())
6145  return *this;
6146 
6147  unsigned top_blocks1 = bman1.top_block_size();
6148  unsigned top_blocks2 = bman2.top_block_size();
6149  unsigned top_blocks = (top_blocks2 > top_blocks1) ? top_blocks2 : top_blocks1;
6150  top_blocks = blockman_.reserve_top_blocks(top_blocks);
6151 
6152  size_ = bv1.size_;
6153  if (size_ < bv2.size_)
6154  size_ = bv2.size_;
6155 
6156  bm::word_t*** blk_root_arg1 = bv1.blockman_.top_blocks_root();
6157  bm::word_t*** blk_root_arg2 = bv2.blockman_.top_blocks_root();
6158 
6159  for (unsigned i = 0; i < top_blocks; ++i)
6160  {
6161  bm::word_t** blk_blk_arg1 = (i < top_blocks1) ? blk_root_arg1[i] : 0;
6162  bm::word_t** blk_blk_arg2 = (i < top_blocks2) ? blk_root_arg2[i] : 0;
6163 
6164  if (blk_blk_arg1 == blk_blk_arg2)
6165  {
6166  if (!blk_blk_arg1)
6167  continue; // 0 & 0 == 0
6168  if ((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR)
6169  {
6170  bm::word_t*** blk_root = blockman_.top_blocks_root();
6171  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
6172  continue;
6173  }
6174  }
6175  if ((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR)
6176  blk_blk_arg1 = FULL_SUB_BLOCK_REAL_ADDR;
6177  if ((bm::word_t*)blk_blk_arg2 == FULL_BLOCK_FAKE_ADDR)
6178  blk_blk_arg2 = FULL_SUB_BLOCK_REAL_ADDR;
6179 
6181  bool any_blocks = false;
6182  unsigned j = 0;
6183  do
6184  {
6185  const bm::word_t* arg_blk1; const bm::word_t* arg_blk2;
6186  arg_blk1 = blk_blk_arg1 ? blk_blk_arg1[j] : 0;
6187  arg_blk2 = blk_blk_arg2 ? blk_blk_arg2[j] : 0;
6188 
6189  if ((arg_blk1 == arg_blk2) && !arg_blk1)
6190  continue; // 0 & 0 == 0
6191 
6192  bool need_opt = combine_operation_block_and(i, j, arg_blk1, arg_blk2);
6193  if (need_opt && opt_mode == opt_compress)
6194  blockman_.optimize_bit_block(i, j, opt_mode);
6195  any_blocks |= bool(blk_blk[j]);
6196  } while (++j < bm::set_sub_array_size);
6197 
6198  if (!any_blocks)
6200 
6201  } // for i
6202 
6203  if (opt_mode != opt_none)
6205 
6206  return *this;
6207 }
6208 
6209 //---------------------------------------------------------------------
6210 
6211 template<class Alloc>
6214  const bm::bvector<Alloc>& bv2,
6215  typename bm::bvector<Alloc>::optmode opt_mode)
6216 {
6217  BM_ASSERT(!is_ro());
6218 
6219  if (&bv1 == &bv2)
6220  {
6221  this->bit_or(bv1);
6222  return *this;
6223  }
6224  if (this == &bv1)
6225  {
6226  this->bit_and(bv2);
6227  return *this;
6228  }
6229  if (this == &bv2)
6230  {
6231  this->bit_and(bv1);
6232  return *this;
6233  }
6234 
6235  const blocks_manager_type& bman1 = bv1.get_blocks_manager();
6236  const blocks_manager_type& bman2 = bv2.get_blocks_manager();
6237  if (!bman1.is_init() || !bman2.is_init())
6238  return *this;
6239 
6240  unsigned top_blocks1 = bman1.top_block_size();
6241  unsigned top_blocks2 = bman2.top_block_size();
6242  unsigned top_blocks = (top_blocks2 > top_blocks1) ? top_blocks2 : top_blocks1;
6243  top_blocks = blockman_.reserve_top_blocks(top_blocks);
6244 
6245  size_type new_size = bv1.size_;
6246  if (new_size < bv2.size_)
6247  new_size = bv2.size_;
6248  if (size_ < new_size)
6249  size_ = new_size;
6250 
6251  bm::word_t*** blk_root_arg1 = bv1.blockman_.top_blocks_root();
6252  bm::word_t*** blk_root_arg2 = bv2.blockman_.top_blocks_root();
6253 
6254  for (unsigned i = 0; i < top_blocks; ++i)
6255  {
6256  bm::word_t** blk_blk_arg1 = (i < top_blocks1) ? blk_root_arg1[i] : 0;
6257  bm::word_t** blk_blk_arg2 = (i < top_blocks2) ? blk_root_arg2[i] : 0;
6258 
6259  if (blk_blk_arg1 == blk_blk_arg2)
6260  {
6261  if (!blk_blk_arg1)
6262  continue; // 0 & 0 == 0
6263  if ((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR)
6264  {
6265  bm::word_t*** blk_root = blockman_.top_blocks_root();
6266  if (blk_root[i])
6268  BM_ASSERT(!blk_root[i]);
6269  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
6270  continue;
6271  }
6272  }
6273  if ((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR)
6274  blk_blk_arg1 = FULL_SUB_BLOCK_REAL_ADDR;
6275  if ((bm::word_t*)blk_blk_arg2 == FULL_BLOCK_FAKE_ADDR)
6276  blk_blk_arg2 = FULL_SUB_BLOCK_REAL_ADDR;
6277 
6279  bool any_blocks = false;
6280  for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
6281  {
6282  if (blk_blk[j] == FULL_BLOCK_FAKE_ADDR) // saturated: nothing to do
6283  {
6284  any_blocks = true;
6285  continue;
6286  }
6287 
6288  const bm::word_t* arg_blk1; const bm::word_t* arg_blk2;
6289  arg_blk1 = blk_blk_arg1 ? blk_blk_arg1[j] : 0;
6290  arg_blk2 = blk_blk_arg2 ? blk_blk_arg2[j] : 0;
6291 
6292  if ((arg_blk1 == arg_blk2) && !arg_blk1)
6293  continue; // 0 & 0 == 0
6294 
6295  bool need_opt;
6296  if (!blk_blk[j]) // nothing to OR
6297  {
6298  need_opt =
6299  combine_operation_block_and(i, j, arg_blk1, arg_blk2);
6300  }
6301  else
6302  {
6303  need_opt =
6304  combine_operation_block_and_or(i, j, arg_blk1, arg_blk2);
6305  }
6306  if (need_opt && opt_mode == opt_compress)
6307  blockman_.optimize_bit_block(i, j, opt_mode);
6308 
6309  any_blocks |= bool(blk_blk[j]);
6310 
6311  } // for j
6312 
6313  if (!any_blocks)
6315 
6316  } // for i
6317 
6318  if (opt_mode != opt_none)
6320 
6321  return *this;
6322 }
6323 
6324 
6325 
6326 //---------------------------------------------------------------------
6327 
6328 template<class Alloc>
6331  const bm::bvector<Alloc>& bv2,
6332  typename bm::bvector<Alloc>::optmode opt_mode)
6333 {
6334  BM_ASSERT(!is_ro());
6335 
6336  if (blockman_.is_init())
6338 
6339  if (&bv1 == &bv2)
6340  return *this; // nothing to do empty result
6341 
6342  if (this == &bv1)
6343  {
6344  this->bit_sub(bv2);
6345  return *this;
6346  }
6347  if (this == &bv2)
6348  {
6349  this->bit_sub(bv1);
6350  return *this;
6351  }
6352 
6353  const blocks_manager_type& bman1 = bv1.get_blocks_manager();
6354  const blocks_manager_type& bman2 = bv2.get_blocks_manager();
6355  if (!bman1.is_init())
6356  {
6357  return *this;
6358  }
6359  if (!bman2.is_init())
6360  {
6361  this->bit_or(bv1);
6362  return *this;
6363  }
6364 
6365  unsigned top_blocks1 = bman1.top_block_size();
6366  unsigned top_blocks2 = bman2.top_block_size();
6367  unsigned top_blocks = (top_blocks2 > top_blocks1) ? top_blocks2 : top_blocks1;
6368  top_blocks = blockman_.reserve_top_blocks(top_blocks);
6369 
6370  size_ = bv1.size_;
6371  if (size_ < bv2.size_)
6372  size_ = bv2.size_;
6373 
6374  bm::word_t*** blk_root_arg1 = bv1.blockman_.top_blocks_root();
6375  bm::word_t*** blk_root_arg2 = bv2.blockman_.top_blocks_root();
6376 
6377  for (unsigned i = 0; i < top_blocks; ++i)
6378  {
6379  bm::word_t** blk_blk_arg1 = (i < top_blocks1) ? blk_root_arg1[i] : 0;
6380  bm::word_t** blk_blk_arg2 = (i < top_blocks2) ? blk_root_arg2[i] : 0;
6381 
6382  if (blk_blk_arg1 == blk_blk_arg2)
6383  continue; // 0 AND NOT 0 == 0
6384  if ((bm::word_t*)blk_blk_arg2 == FULL_BLOCK_FAKE_ADDR)
6385  continue;
6386  if ((bm::word_t*)blk_blk_arg1 == FULL_BLOCK_FAKE_ADDR)
6387  blk_blk_arg1 = FULL_SUB_BLOCK_REAL_ADDR;
6388 
6390  bool any_blocks = false;
6391  unsigned j = 0;
6392  do
6393  {
6394  const bm::word_t* arg_blk1 = blk_blk_arg1 ? blk_blk_arg1[j] : 0;
6395  const bm::word_t* arg_blk2 = blk_blk_arg2 ? blk_blk_arg2[j] : 0;
6396  if ((arg_blk1 == arg_blk2) && !arg_blk1)
6397  continue; // 0 & ~0 == 0
6398 
6399  bool need_opt = combine_operation_block_sub(i, j, arg_blk1, arg_blk2);
6400  if (need_opt && opt_mode == opt_compress)
6401  blockman_.optimize_bit_block(i, j, opt_mode);
6402  any_blocks |= bool(blk_blk[j]);
6403  } while (++j < bm::set_sub_array_size);
6404 
6405  if (!any_blocks)
6407 
6408  } // for i
6409 
6410  if (opt_mode != opt_none)
6412 
6413  return *this;
6414 }
6415 
6416 
6417 //---------------------------------------------------------------------
6418 
6419 #define BM_OR_OP(x) \
6420  { \
6421  blk = blk_blk[j+x]; arg_blk = blk_blk_arg[j+x]; \
6422  if (blk != arg_blk) \
6423  combine_operation_block_or(i, j+x, blk, arg_blk); \
6424  }
6425 
6426 template<class Alloc>
6428 {
6429  if (!bv.blockman_.is_init())
6430  return;
6431 
6432  unsigned top_blocks = blockman_.top_block_size();
6433  if (size_ < bv.size_)
6434  size_ = bv.size_;
6435 
6436  unsigned arg_top_blocks = bv.blockman_.top_block_size();
6437  top_blocks = blockman_.reserve_top_blocks(arg_top_blocks);
6438 
6439  bm::word_t*** blk_root = blockman_.top_blocks_root();
6440  bm::word_t*** blk_root_arg = bv.blockman_.top_blocks_root();
6441 
6442  for (unsigned i = 0; i < top_blocks; ++i)
6443  {
6444  bm::word_t** blk_blk = blk_root[i];
6445  bm::word_t** blk_blk_arg = (i < arg_top_blocks) ? blk_root_arg[i] : 0;
6446  if (blk_blk == blk_blk_arg || !blk_blk_arg) // nothing to do (0 OR 0 == 0)
6447  continue;
6448  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
6449  continue;
6450  if ((bm::word_t*)blk_blk_arg == FULL_BLOCK_FAKE_ADDR)
6451  {
6453  blk_root[i] = (bm::word_t**)FULL_BLOCK_FAKE_ADDR;
6454  continue;
6455  }
6456  if (!blk_blk)
6457  blk_blk = blockman_.alloc_top_subblock(i);
6458 
6459  unsigned j = 0;
6460  bm::word_t* blk;
6461  const bm::word_t* arg_blk;
6462  do
6463  {
6464  #if defined(BM64_AVX2) || defined(BM64_AVX512)
6465  if (!avx2_test_all_eq_wave2(blk_blk + j, blk_blk_arg + j))
6466  {
6467  BM_OR_OP(0)
6468  BM_OR_OP(1)
6469  BM_OR_OP(2)
6470  BM_OR_OP(3)
6471  }
6472  j += 4;
6473  #elif defined(BM64_SSE4)
6474  if (!sse42_test_all_eq_wave2(blk_blk + j, blk_blk_arg + j))
6475  {
6476  BM_OR_OP(0)
6477  BM_OR_OP(1)
6478  }
6479  j += 2;
6480  #else
6481  BM_OR_OP(0)
6482  ++j;
6483  #endif
6484  } while (j < bm::set_sub_array_size);
6485  } // for i
6486 }
6487 
6488 #undef BM_OR_OP
6489 
6490 //---------------------------------------------------------------------
6491 
6492 #define BM_XOR_OP(x) \
6493  { \
6494  blk = blk_blk[j+x]; arg_blk = blk_blk_arg[j+x]; \
6495  combine_operation_block_xor(i, j+x, blk, arg_blk); \
6496  }
6497 
6498 template<class Alloc>
6500 {
6501  if (!bv.blockman_.is_init())
6502  return;
6503  if (!blockman_.is_init())
6504  {
6505  *this = bv;
6506  return;
6507  }
6508 
6509  unsigned top_blocks = blockman_.top_block_size();
6510  if (size_ < bv.size_) // this vect shorter than the arg.
6511  {
6512  size_ = bv.size_;
6513  }
6514  unsigned arg_top_blocks = bv.blockman_.top_block_size();
6515  top_blocks = blockman_.reserve_top_blocks(arg_top_blocks);
6516 
6517  bm::word_t*** blk_root = blockman_.top_blocks_root();
6518  bm::word_t*** blk_root_arg = bv.blockman_.top_blocks_root();
6519 
6520  for (unsigned i = 0; i < top_blocks; ++i)
6521  {
6522  bm::word_t** blk_blk_arg = (i < arg_top_blocks) ? blk_root_arg[i] : 0;
6523  if (!blk_blk_arg)
6524  continue;
6525  bm::word_t** blk_blk = blk_root[i];
6526  if (blk_blk == blk_blk_arg) // nothing to do (any XOR 0 == 0)
6527  {
6528  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
6529  blk_root[i] = 0;
6530  continue;
6531  }
6532  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
6533  {
6534  if (!blk_blk_arg)
6535  continue;
6537  }
6538  if ((bm::word_t*)blk_blk_arg == FULL_BLOCK_FAKE_ADDR)
6539  {
6540  if (!blk_blk)
6541  {
6542  blk_root[i] = (bm::word_t**) FULL_BLOCK_FAKE_ADDR;
6543  continue;
6544  }
6545  blk_blk_arg = FULL_SUB_BLOCK_REAL_ADDR;
6546  }
6547 
6548  if (!blk_blk)
6549  blk_blk = blockman_.alloc_top_subblock(i);
6550 
6551  unsigned j = 0;
6552  bm::word_t* blk;
6553  const bm::word_t* arg_blk;
6554  do
6555  {
6556  #if defined(BM64_AVX2) || defined(BM64_AVX512)
6557  if (!avx2_test_all_zero_wave2(blk_blk + j, blk_blk_arg + j))
6558  {
6559  BM_XOR_OP(0)
6560  BM_XOR_OP(1)
6561  BM_XOR_OP(2)
6562  BM_XOR_OP(3)
6563  }
6564  j += 4;
6565  #elif defined(BM64_SSE4)
6566  if (!sse42_test_all_zero_wave2(blk_blk + j, blk_blk_arg + j))
6567  {
6568  BM_XOR_OP(0)
6569  BM_XOR_OP(1)
6570  }
6571  j += 2;
6572  #else
6573  BM_XOR_OP(0)
6574  ++j;
6575  #endif
6576  } while (j < bm::set_sub_array_size);
6577  } // for i
6578 }
6579 
6580 #undef BM_XOR_OP
6581 
6582 
6583 //---------------------------------------------------------------------
6584 
6585 #define BM_AND_OP(x) if (0 != (blk = blk_blk[j+x])) \
6586  { \
6587  if (0 != (arg_blk = blk_blk_arg[j+x])) \
6588  { \
6589  combine_operation_block_and(i, j+x, blk, arg_blk); \
6590  if (opt_mode == opt_compress) \
6591  blockman_.optimize_bit_block(i, j+x, opt_mode); \
6592  } \
6593  else \
6594  blockman_.zero_block(i, j+x); \
6595  }
6596 
6597 template<class Alloc>
6599  typename bm::bvector<Alloc>::optmode opt_mode)
6600 {
6601  if (!blockman_.is_init())
6602  return; // nothing to do, already empty
6603  if (!bv.blockman_.is_init())
6604  {
6605  clear(true);
6606  return;
6607  }
6608 
6609  unsigned top_blocks = blockman_.top_block_size();
6610  if (size_ < bv.size_) // this vect shorter than the arg.
6611  size_ = bv.size_;
6612 
6613  unsigned arg_top_blocks = bv.blockman_.top_block_size();
6614  top_blocks = blockman_.reserve_top_blocks(arg_top_blocks);
6615 
6616 
6617  bm::word_t*** blk_root = blockman_.top_blocks_root();
6618  bm::word_t*** blk_root_arg = bv.blockman_.top_blocks_root();
6619 
6620  for (unsigned i = 0; i < top_blocks; ++i)
6621  {
6622  bm::word_t** blk_blk = blk_root[i];
6623  if (!blk_blk) // nothing to do (0 AND 1 == 0)
6624  continue;
6625  bm::word_t** blk_blk_arg = (i < arg_top_blocks) ? blk_root_arg[i] : 0;
6626  if (!blk_blk_arg) // free a whole group of blocks
6627  {
6628  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
6629  {
6630  blk_root[i] = 0;
6631  }
6632  else
6633  {
6634  for (unsigned j = 0; j < bm::set_sub_array_size; ++j)
6635  blockman_.zero_block(i, j);
6637  }
6638  continue;
6639  }
6640  if ((bm::word_t*)blk_blk_arg == FULL_BLOCK_FAKE_ADDR)
6641  continue; // any & 1 == any
6642 
6643  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
6645 
6646  unsigned j = 0;
6647  bm::word_t* blk;
6648  const bm::word_t* arg_blk;
6649  do
6650  {
6651  #if defined(BM64_AVX2) || defined(BM64_AVX512)
6652  if (!avx2_test_all_zero_wave(blk_blk + j))
6653  {
6654  BM_AND_OP(0)
6655  BM_AND_OP(1)
6656  BM_AND_OP(2)
6657  BM_AND_OP(3)
6658  }
6659  j += 4;
6660  #elif defined(BM64_SSE4)
6661  if (!sse42_test_all_zero_wave(blk_blk + j))
6662  {
6663  BM_AND_OP(0)
6664  BM_AND_OP(1)
6665  }
6666  j += 2;
6667  #else
6668  BM_AND_OP(0)
6669  ++j;
6670  #endif
6671  } while (j < bm::set_sub_array_size);
6672  } // for i
6673 }
6674 
6675 #undef BM_AND_OP
6676 
6677 
6678 //---------------------------------------------------------------------
6679 
6680 #define BM_SUB_OP(x) \
6681  if ((0 != (blk = blk_blk[j+x])) && (0 != (arg_blk = blk_blk_arg[j+x]))) \
6682  combine_operation_block_sub(i, j+x, blk, arg_blk);
6683 
6684 
6685 template<class Alloc>
6687 {
6688  if (!blockman_.is_init() || !bv.blockman_.is_init())
6689  return;
6690 
6691  unsigned top_blocks = blockman_.top_block_size();
6692  if (size_ < bv.size_) // this vect shorter than the arg.
6693  size_ = bv.size_;
6694 
6695  unsigned arg_top_blocks = bv.blockman_.top_block_size();
6696  top_blocks = blockman_.reserve_top_blocks(arg_top_blocks);
6697 
6698  bm::word_t*** blk_root = blockman_.top_blocks_root();
6699  bm::word_t*** blk_root_arg = bv.blockman_.top_blocks_root();
6700 
6701  for (unsigned i = 0; i < top_blocks; ++i)
6702  {
6703  bm::word_t** blk_blk = blk_root[i];
6704  bm::word_t** blk_blk_arg = (i < arg_top_blocks) ? blk_root_arg[i] : 0;
6705  if (!blk_blk || !blk_blk_arg) // nothing to do (0 AND NOT 1 == 0)
6706  continue;
6707 
6708  if ((bm::word_t*)blk_blk_arg == FULL_BLOCK_FAKE_ADDR) // zero result
6709  {
6711  continue;
6712  }
6713  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
6715 
6716  bm::word_t* blk;
6717  const bm::word_t* arg_blk;
6718  unsigned j = 0;
6719  do
6720  {
6721  #if defined(BM64_AVX2) || defined(BM64_AVX512)
6722  if (!avx2_test_all_zero_wave(blk_blk + j))
6723  {
6724  BM_SUB_OP(0)
6725  BM_SUB_OP(1)
6726  BM_SUB_OP(2)
6727  BM_SUB_OP(3)
6728  }
6729  j += 4;
6730  #elif defined(BM64_SSE4)
6731  if (!sse42_test_all_zero_wave(blk_blk + j))
6732  {
6733  BM_SUB_OP(0)
6734  BM_SUB_OP(1)
6735  }
6736  j += 2;
6737  #else
6738  BM_SUB_OP(0)
6739  ++j;
6740  #endif
6741  } while (j < bm::set_sub_array_size);
6742  } // for i
6743 }
6744 
6745 #undef BM_SUB_OP
6746 
6747 //---------------------------------------------------------------------
6748 
6749 template<class Alloc>
6751  const bm::bvector<Alloc>& bv,
6752  bm::operation opcode)
6753 {
6754  if (!blockman_.is_init())
6755  {
6756  if (opcode == BM_AND || opcode == BM_SUB)
6757  return;
6758  blockman_.init_tree();
6759  }
6760 
6761  unsigned top_blocks = blockman_.top_block_size();
6762  unsigned arg_top_blocks = bv.blockman_.top_block_size();
6763 
6764  if (arg_top_blocks > top_blocks)
6765  top_blocks = blockman_.reserve_top_blocks(arg_top_blocks);
6766 
6767  if (size_ < bv.size_) // this vect shorter than the arg.
6768  {
6769  size_ = bv.size_;
6770  // stretch our capacity
6771  blockman_.reserve_top_blocks(arg_top_blocks);
6772  top_blocks = blockman_.top_block_size();
6773  }
6774  else
6775  if (size_ > bv.size_) // this vector larger
6776  {
6777  if (opcode == BM_AND) // clear the tail with zeros
6778  {
6779  set_range(bv.size_, size_ - 1, false);
6780  if (arg_top_blocks < top_blocks)
6781  {
6782  // not to scan blocks we already swiped
6783  top_blocks = arg_top_blocks;
6784  }
6785  }
6786  }
6787 
6788  bm::word_t*** blk_root = blockman_.top_blocks_root();
6789  unsigned block_idx = 0; (void) block_idx;
6790  unsigned i, j;
6791 
6792  // calculate effective top size to avoid overscan
6793  top_blocks = blockman_.top_block_size();
6794  if (top_blocks < bv.blockman_.top_block_size())
6795  {
6796  if (opcode != BM_AND)
6797  {
6798  top_blocks = bv.blockman_.top_block_size();
6799  }
6800  }
6801 
6802  for (i = 0; i < top_blocks; ++i)
6803  {
6804  bm::word_t** blk_blk = blk_root[i];
6805  if (blk_blk == 0) // not allocated
6806  {
6807  if (opcode == BM_AND) // 0 AND anything == 0
6808  {
6809  block_idx += bm::set_sub_array_size;
6810  continue;
6811  }
6812  const bm::word_t* const* bvbb = bv.blockman_.get_topblock(i);
6813  if (bvbb == 0) // skip it because 0 OP 0 == 0
6814  {
6815  block_idx += bm::set_sub_array_size;
6816  continue;
6817  }
6818  // 0 - self, non-zero argument
6820  for (j = 0; j < bm::set_sub_array_size; ++j)
6821  {
6822  const bm::word_t* arg_blk = bv.blockman_.get_block(i, j);
6823  if (arg_blk )
6825  0, 0,
6826  arg_blk, BM_IS_GAP(arg_blk),
6827  opcode);
6828  } // for j
6829  continue;
6830  }
6831 
6832  if (opcode == BM_AND)
6833  {
6835  for (j = 0; j < bm::set_sub_array_size; ++j)
6836  {
6837  bm::word_t* blk = blk_blk[j];
6838  if (blk)
6839  {
6840  const bm::word_t* arg_blk = bv.blockman_.get_block(i, j);
6841  if (arg_blk)
6843  BM_IS_GAP(blk), blk,
6844  arg_blk, BM_IS_GAP(arg_blk),
6845  opcode);
6846  else
6847  blockman_.zero_block(i, j);
6848  }
6849 
6850  } // for j
6851  }
6852  else // OR, SUB, XOR
6853  {
6855  for (j = 0; j < bm::set_sub_array_size; ++j)
6856  {
6857  bm::word_t* blk = blk_blk[j];
6858  const bm::word_t* arg_blk = bv.blockman_.get_block(i, j);
6859  if (arg_blk || blk)
6860  combine_operation_with_block(r + j, BM_IS_GAP(blk), blk,
6861  arg_blk, BM_IS_GAP(arg_blk),
6862  opcode);
6863  } // for j
6864  }
6865  } // for i
6866 
6867 }
6868 
6869 //---------------------------------------------------------------------
6870 
6871 template<class Alloc>
6873  unsigned j,
6874  const bm::word_t* arg_blk1,
6875  const bm::word_t* arg_blk2)
6876 {
6877  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
6878  if (!arg_blk1)
6879  {
6880  blockman_.clone_assign_block(i, j, arg_blk2);
6881  return 0;
6882  }
6883  if (!arg_blk2)
6884  {
6885  blockman_.clone_assign_block(i, j, arg_blk1);
6886  return 0;
6887  }
6888  if ((arg_blk1==FULL_BLOCK_FAKE_ADDR) || (arg_blk2==FULL_BLOCK_FAKE_ADDR))
6889  {
6891  return 0;
6892  }
6893 
6894  bool is_gap1 = BM_IS_GAP(arg_blk1);
6895  bool is_gap2 = BM_IS_GAP(arg_blk2);
6896 
6897  if (is_gap1 | is_gap2) // at least one GAP
6898  {
6899  if (is_gap1 & is_gap2) // both GAPS
6900  {
6901  unsigned res_len;
6902  bm::gap_operation_or(BMGAP_PTR(arg_blk1),
6903  BMGAP_PTR(arg_blk2),
6904  tmp_buf, res_len);
6905  blockman_.clone_gap_block(i, j, tmp_buf, res_len);
6906  return 0;
6907  }
6908  // one GAP one bit block
6909  const bm::word_t* arg_block;
6910  const bm::gap_word_t* arg_gap;
6911  if (is_gap1) // arg1 is GAP -> clone arg2(bit)
6912  {
6913  arg_block = arg_blk2;
6914  arg_gap = BMGAP_PTR(arg_blk1);
6915  }
6916  else // arg2 is GAP
6917  {
6918  arg_block = arg_blk1;
6919  arg_gap = BMGAP_PTR(arg_blk2);
6920  }
6921  bm::word_t* block = blockman_.clone_assign_block(i, j, arg_block);
6922  bm::gap_add_to_bitset(block, arg_gap);
6923 
6924  return true; // optimization may be needed
6925  }
6926 
6927  // 2 bit-blocks
6928  //
6930  blockman_.set_block_ptr(i, j, block);
6931 
6932  bool all_one = bm::bit_block_or_2way(block, arg_blk1, arg_blk2);
6933  if (all_one)
6934  {
6936  blockman_.return_tempblock(block);
6937  return 0;
6938  }
6939  return true;
6940 }
6941 
6942 //---------------------------------------------------------------------
6943 
6944 template<class Alloc>
6946  unsigned j,
6947  const bm::word_t* arg_blk1,
6948  const bm::word_t* arg_blk2)
6949 {
6950  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
6951 
6952  if (!arg_blk1)
6953  {
6954  blockman_.clone_assign_block(i, j, arg_blk2);
6955  return 0;
6956  }
6957  if (!arg_blk2)
6958  {
6959  blockman_.clone_assign_block(i, j, arg_blk1);
6960  return 0;
6961  }
6962  if (arg_blk1==FULL_BLOCK_FAKE_ADDR)
6963  {
6964  BM_ASSERT(!IS_FULL_BLOCK(arg_blk2));
6965  blockman_.clone_assign_block(i, j, arg_blk2, true); // invert
6966  return 0;
6967  }
6968  if (arg_blk2==FULL_BLOCK_FAKE_ADDR)
6969  {
6970  BM_ASSERT(!IS_FULL_BLOCK(arg_blk1));
6971  blockman_.clone_assign_block(i, j, arg_blk1, true); // invert
6972  return 0;
6973  }
6974 
6975  bool is_gap1 = BM_IS_GAP(arg_blk1);
6976  bool is_gap2 = BM_IS_GAP(arg_blk2);
6977 
6978  if (is_gap1 | is_gap2) // at least one GAP
6979  {
6980  if (is_gap1 & is_gap2) // both GAPS
6981  {
6982  unsigned res_len;
6983  bm::gap_operation_xor(BMGAP_PTR(arg_blk1),
6984  BMGAP_PTR(arg_blk2),
6985  tmp_buf, res_len);
6986  blockman_.clone_gap_block(i, j, tmp_buf, res_len);
6987  return 0;
6988  }
6989  // one GAP one bit block
6990  const bm::word_t* arg_block;
6991  const bm::gap_word_t* arg_gap;
6992  if (is_gap1) // arg1 is GAP -> clone arg2(bit)
6993  {
6994  arg_block = arg_blk2;
6995  arg_gap = BMGAP_PTR(arg_blk1);
6996  }
6997  else // arg2 is GAP
6998  {
6999  arg_block = arg_blk1;
7000  arg_gap = BMGAP_PTR(arg_blk2);
7001  }
7002  bm::word_t* block = blockman_.clone_assign_block(i, j, arg_block);
7003  bm::gap_xor_to_bitset(block, arg_gap);
7004 
7005  return true; // optimization may be needed
7006  }
7007 
7008  // 2 bit-blocks
7009  //
7011  blockman_.set_block_ptr(i, j, block);
7012 
7013  bm::id64_t or_mask = bm::bit_block_xor_2way(block, arg_blk1, arg_blk2);
7014  if (!or_mask)
7015  {
7016  blockman_.set_block_ptr(i, j, 0);
7017  blockman_.return_tempblock(block);
7018  return 0;
7019  }
7020 
7021  return true;
7022 }
7023 
7024 //---------------------------------------------------------------------
7025 
7026 template<class Alloc>
7028  unsigned j,
7029  const bm::word_t* arg_blk1,
7030  const bm::word_t* arg_blk2)
7031 {
7032  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
7033 
7034  if (!arg_blk1 || !arg_blk2)
7035  return 0;
7036  if ((arg_blk1==FULL_BLOCK_FAKE_ADDR) && (arg_blk2==FULL_BLOCK_FAKE_ADDR))
7037  {
7039  return 0;
7040  }
7041  if (arg_blk1==FULL_BLOCK_FAKE_ADDR)
7042  {
7043  blockman_.clone_assign_block(i, j, arg_blk2);
7044  return 0;
7045  }
7046  if (arg_blk2==FULL_BLOCK_FAKE_ADDR)
7047  {
7048  blockman_.clone_assign_block(i, j, arg_blk1);
7049  return 0;
7050  }
7051 
7052  bool is_gap1 = BM_IS_GAP(arg_blk1);
7053  bool is_gap2 = BM_IS_GAP(arg_blk2);
7054 
7055  if (is_gap1 | is_gap2) // at least one GAP
7056  {
7057  if (is_gap1 & is_gap2) // both GAPS
7058  {
7059  unsigned res_len;
7060  bm::gap_operation_and(BMGAP_PTR(arg_blk1),
7061  BMGAP_PTR(arg_blk2),
7062  tmp_buf, res_len);
7063  blockman_.clone_gap_block(i, j, tmp_buf, res_len);
7064  return 0;
7065  }
7066  // one GAP one bit block
7067  const bm::word_t* arg_block;
7068  const bm::gap_word_t* arg_gap;
7069  if (is_gap1) // arg1 is GAP -> clone arg2(bit)
7070  {
7071  arg_block = arg_blk2;
7072  arg_gap = BMGAP_PTR(arg_blk1);
7073  }
7074  else // arg2 is GAP
7075  {
7076  arg_block = arg_blk1;
7077  arg_gap = BMGAP_PTR(arg_blk2);
7078  }
7079  bm::word_t* block = blockman_.clone_assign_block(i, j, arg_block);
7080  bm::gap_and_to_bitset(block, arg_gap);
7081 
7082  bool all_z = bm::bit_is_all_zero(block); // maybe ALL empty block?
7083  if (all_z)
7084  {
7085  blockman_.set_block_ptr(i, j, 0);
7086  blockman_.return_tempblock(block);
7087  return false;
7088  }
7089 
7090  return true; // optimization may be needed
7091  }
7092 
7093  // 2 bit-blocks
7094  //
7096  blockman_.set_block_ptr(i, j, block);
7097 
7098  bm::id64_t digest = bm::bit_block_and_2way(block, arg_blk1, arg_blk2, ~0ull);
7099  if (!digest)
7100  {
7101  blockman_.set_block_ptr(i, j, 0);
7102  blockman_.return_tempblock(block);
7103  return 0;
7104  }
7105 
7106  return true;
7107 }
7108 
7109 //---------------------------------------------------------------------
7110 
7111 template<class Alloc>
7113  unsigned j,
7114  const bm::word_t* arg_blk1,
7115  const bm::word_t* arg_blk2)
7116 {
7117  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
7118  bm::word_t* blk = blockman_.get_block_ptr(i, j);
7119  BM_ASSERT(blk); // target block MUST be allocated
7120 
7121  if (!arg_blk1 || !arg_blk2)
7122  return 0;
7123  if ((arg_blk1==FULL_BLOCK_FAKE_ADDR) && (arg_blk2==FULL_BLOCK_FAKE_ADDR))
7124  {
7125  if (blk)
7126  blockman_.zero_block(i, j); // free target block and assign FULL
7128  return 0;
7129  }
7130  if (arg_blk1==FULL_BLOCK_FAKE_ADDR)
7131  {
7132  combine_operation_block_or(i, j, blk, arg_blk2);
7133  return 0;
7134  }
7135  if (arg_blk2==FULL_BLOCK_FAKE_ADDR)
7136  {
7137  combine_operation_block_or(i, j, blk, arg_blk1);
7138  return 0;
7139  }
7140 
7141  blk = blockman_.deoptimize_block_no_check(blk, i, j);
7142 
7143  bool is_gap1 = BM_IS_GAP(arg_blk1);
7144  bool is_gap2 = BM_IS_GAP(arg_blk2);
7145 
7146  if (is_gap1 | is_gap2) // at least one GAP
7147  {
7148  if (is_gap1 & is_gap2) // both GAPS
7149  {
7150  unsigned res_len;
7151  bm::gap_operation_and(BMGAP_PTR(arg_blk1), BMGAP_PTR(arg_blk2),
7152  tmp_buf, res_len);
7153  bm::gap_add_to_bitset(blk, tmp_buf, res_len);
7154  bool all_one = bm::is_bits_one((bm::wordop_t*) blk);
7155  if (all_one)
7156  {
7159  return false;
7160  }
7161  return true;
7162  }
7163  // one GAP, one bit
7164  const bm::word_t* arg_block;
7165  const bm::gap_word_t* arg_gap;
7166  if (is_gap1) // arg1 is GAP -> clone arg2(bit)
7167  {
7168  arg_block = arg_blk2;
7169  arg_gap = BMGAP_PTR(arg_blk1);
7170  }
7171  else // arg2 is GAP
7172  {
7173  arg_block = arg_blk1;
7174  arg_gap = BMGAP_PTR(arg_blk2);
7175  }
7177  bm::bit_block_copy(tmp_blk, arg_block);
7178  bm::gap_and_to_bitset(tmp_blk, arg_gap); // bit := bit AND gap
7179  bool all_one = bm::bit_block_or(blk, tmp_blk); // target |= bit
7180  if (all_one)
7181  {
7185  return false;
7186  }
7187  return true; // optimization may be needed
7188  }
7189 
7190  // 1+2 bit-blocks
7191  //
7192  bm::id64_t digest_and = ~0ull;
7193  bm::id64_t digest =
7194  bm::bit_block_and_or_2way(blk, arg_blk1, arg_blk2, digest_and);
7195  if (digest == digest_and)
7196  {
7197  bool all_one = bm::is_bits_one((bm::wordop_t*) blk);
7198  if (all_one)
7199  {
7202  return false;
7203  }
7204  }
7205  return true; // optimization may be needed
7206 }
7207 
7208 
7209 //---------------------------------------------------------------------
7210 
7211 template<class Alloc>
7213  unsigned j,
7214  const bm::word_t* arg_blk1,
7215  const bm::word_t* arg_blk2)
7216 {
7217  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
7218 
7219  if (!arg_blk1)
7220  return 0;
7221  if (!arg_blk2)
7222  {
7223  blockman_.clone_assign_block(i, j, arg_blk1);
7224  return 0;
7225  }
7226  if (arg_blk2==FULL_BLOCK_FAKE_ADDR)
7227  return 0;
7228  if (arg_blk1==FULL_BLOCK_FAKE_ADDR)
7229  arg_blk1 = FULL_BLOCK_REAL_ADDR;
7230 
7231  bool is_gap1 = BM_IS_GAP(arg_blk1);
7232  bool is_gap2 = BM_IS_GAP(arg_blk2);
7233 
7234  if (is_gap1 | is_gap2) // at least one GAP
7235  {
7236  if (is_gap1 & is_gap2) // both GAPS
7237  {
7238  unsigned res_len;
7239  bm::gap_operation_sub(BMGAP_PTR(arg_blk1),
7240  BMGAP_PTR(arg_blk2),
7241  tmp_buf, res_len);
7242  blockman_.clone_gap_block(i, j, tmp_buf, res_len);
7243  return 0;
7244  }
7245 
7246  if (is_gap1)
7247  {
7249  blockman_.set_block_ptr(i, j, block);
7250  bm::gap_convert_to_bitset(block, BMGAP_PTR(arg_blk1));
7251  bm::id64_t acc = bm::bit_block_sub(block, arg_blk2);
7252  if (!acc)
7253  {
7254  blockman_.set_block_ptr(i, j, 0);
7255  blockman_.return_tempblock(block);
7256  return 0;
7257  }
7258  return true;
7259  }
7260  BM_ASSERT(is_gap2);
7261  bm::word_t* block = blockman_.clone_assign_block(i, j, arg_blk1);
7262  bm::gap_sub_to_bitset(block, BMGAP_PTR(arg_blk2));
7263 
7264  return true; // optimization may be needed
7265  }
7266 
7267  // 2 bit-blocks:
7268  //
7270  blockman_.set_block_ptr(i, j, block);
7271 
7272  bm::id64_t digest = bm::bit_block_sub_2way(block, arg_blk1, arg_blk2, ~0ull);
7273  if (!digest)
7274  {
7275  blockman_.set_block_ptr(i, j, 0);
7276  blockman_.return_tempblock(block);
7277  return 0;
7278  }
7279  return true;
7280 }
7281 
7282 
7283 //---------------------------------------------------------------------
7284 
7285 template<class Alloc>
7287  unsigned i, unsigned j,
7288  bm::word_t* blk, const bm::word_t* arg_blk)
7289 {
7290  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
7291  if (IS_FULL_BLOCK(blk) || !arg_blk) // all bits are set
7292  return; // nothing to do
7293 
7294  if (IS_FULL_BLOCK(arg_blk))
7295  {
7296  if (blk)
7297  blockman_.zero_block(i, j); // free target block and assign FULL
7299  return;
7300  }
7301 
7302  if (BM_IS_GAP(blk)) // our block GAP-type
7303  {
7304  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
7305  if (BM_IS_GAP(arg_blk)) // both blocks GAP-type
7306  {
7307  const bm::gap_word_t* res; unsigned res_len;
7308  res = bm::gap_operation_or(gap_blk, BMGAP_PTR(arg_blk),
7309  tmp_buf, res_len);
7310  BM_ASSERT(res == tmp_buf);
7311  blockman_.assign_gap_check(i, j, res, ++res_len, blk, tmp_buf);
7312  return;
7313  }
7314  // GAP or BIT
7315  //
7316  bm::word_t* new_blk = blockman_.get_allocator().alloc_bit_block();
7317  bm::bit_block_copy(new_blk, arg_blk);
7318  bm::gap_add_to_bitset(new_blk, gap_blk);
7319 
7320  blockman_.get_allocator().free_gap_block(gap_blk, blockman_.glen());
7321  blockman_.set_block_ptr(i, j, new_blk);
7322 
7323  return;
7324  }
7325  else // our block is BITSET-type (but NOT FULL_BLOCK we checked it)
7326  {
7327  if (BM_IS_GAP(arg_blk)) // argument block is GAP-type
7328  {
7329  const bm::gap_word_t* arg_gap = BMGAP_PTR(arg_blk);
7330  if (!blk)
7331  {
7332  bool gap = true;
7333  blk = blockman_.clone_gap_block(arg_gap, gap);
7334  blockman_.set_block(i, j, blk, gap);
7335  return;
7336  }
7337 
7338  // BIT & GAP
7339  bm::gap_add_to_bitset(blk, arg_gap);
7340  return;
7341  } // if arg_gap
7342  }
7343 
7344  if (!blk)
7345  {
7346  blk = blockman_.alloc_.alloc_bit_block();
7347  bm::bit_block_copy(blk, arg_blk);
7348  blockman_.set_block_ptr(i, j, blk);
7349  return;
7350  }
7351 
7352  bool all_one = bm::bit_block_or(blk, arg_blk);
7353  if (all_one)
7354  {
7356  blockman_.get_allocator().free_bit_block(blk);
7358  }
7359 
7360 }
7361 
7362 //---------------------------------------------------------------------
7363 
7364 template<class Alloc>
7366  unsigned i, unsigned j,
7367  bm::word_t* blk, const bm::word_t* arg_blk)
7368 {
7369  bm::gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
7370  if (!arg_blk) // all bits are set
7371  return; // nothing to do
7372 
7373  if (IS_FULL_BLOCK(arg_blk))
7374  {
7375  if (blk)
7376  {
7377  if (BM_IS_GAP(blk))
7378  bm::gap_invert(BMGAP_PTR(blk));
7379  else
7380  {
7381  if (IS_FULL_BLOCK(blk)) // 1 xor 1 = 0
7382  blockman_.set_block_ptr(i, j, 0);
7383  else
7384  bm::bit_invert((wordop_t*) blk);
7385  }
7386  }
7387  else // blk == 0
7388  {
7390  }
7391  return;
7392  }
7393  if (IS_FULL_BLOCK(blk))
7394  {
7395  if (!arg_blk)
7396  return;
7397  // deoptimize block
7398  blk = blockman_.get_allocator().alloc_bit_block();
7399  bm::bit_block_set(blk, ~0u);
7400  blockman_.set_block_ptr(i, j, blk);
7401  }
7402 
7403 
7404  if (BM_IS_GAP(blk)) // our block GAP-type
7405  {
7406  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
7407  if (BM_IS_GAP(arg_blk)) // both blocks GAP-type
7408  {
7409  const bm::gap_word_t* res;
7410  unsigned res_len;
7411  res = bm::gap_operation_xor(gap_blk,
7412  BMGAP_PTR(arg_blk),
7413  tmp_buf,
7414  res_len);
7415  BM_ASSERT(res == tmp_buf);
7416  blockman_.assign_gap_check(i, j, res, ++res_len, blk, tmp_buf);
7417  return;
7418  }
7419  // GAP or BIT
7420  //
7421  bm::word_t* new_blk = blockman_.get_allocator().alloc_bit_block();
7422  bm::bit_block_copy(new_blk, arg_blk);
7423  bm::gap_xor_to_bitset(new_blk, gap_blk);
7424 
7425  blockman_.get_allocator().free_gap_block(gap_blk, blockman_.glen());
7426  blockman_.set_block_ptr(i, j, new_blk);
7427 
7428  return;
7429  }
7430  else // our block is BITSET-type (but NOT FULL_BLOCK we checked it)
7431  {
7432  if (BM_IS_GAP(arg_blk)) // argument block is GAP-type
7433  {
7434  const bm::gap_word_t* arg_gap = BMGAP_PTR(arg_blk);
7435  if (!blk)
7436  {
7437  bool gap = true;
7438  blk = blockman_.clone_gap_block(arg_gap, gap);
7439  blockman_.set_block(i, j, blk, gap);
7440  return;
7441  }
7442  // BIT & GAP
7443  bm::gap_xor_to_bitset(blk, arg_gap);
7444  return;
7445  } // if arg_gap
7446  }
7447 
7448  if (!blk)
7449  {
7450  blk = blockman_.alloc_.alloc_bit_block();
7451  bm::bit_block_copy(blk, arg_blk);
7452  blockman_.set_block_ptr(i, j, blk);
7453  return;
7454  }
7455 
7456  auto any_bits = bm::bit_block_xor(blk, arg_blk);
7457  if (!any_bits)
7458  {
7459  blockman_.get_allocator().free_bit_block(blk);
7460  blockman_.set_block_ptr(i, j, 0);
7461  }
7462 }
7463 
7464 
7465 //---------------------------------------------------------------------
7466 
7467 
7468 template<class Alloc>
7470  unsigned i, unsigned j, bm::word_t* blk, const bm::word_t* arg_blk)
7471 {
7472  BM_ASSERT(arg_blk && blk);
7473 
7474  if (IS_FULL_BLOCK(arg_blk))
7475  return; // nothing to do
7476 
7477  gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
7478 
7479  if (BM_IS_GAP(blk)) // our block GAP-type
7480  {
7481  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
7482  if (BM_IS_GAP(arg_blk)) // both blocks GAP-type
7483  {
7484  const bm::gap_word_t* res;
7485  unsigned res_len;
7486  res = bm::gap_operation_and(gap_blk,
7487  BMGAP_PTR(arg_blk),
7488  tmp_buf,
7489  res_len);
7490  BM_ASSERT(res == tmp_buf);
7491  blockman_.assign_gap_check(i, j, res, ++res_len, blk, tmp_buf);
7492  return;
7493  }
7494  // GAP & BIT
7495  //
7496  bm::word_t* new_blk = blockman_.get_allocator().alloc_bit_block();
7497  bm::bit_block_copy(new_blk, arg_blk); // TODO: copy+digest in one pass
7498  bm::id64_t d0 = bm::calc_block_digest0(new_blk);
7499 
7500  bm::id64_t d0_1 = bm::gap_and_to_bitset(new_blk, gap_blk, d0);
7501 
7502 // bm::id64_t d0_1 = bm::update_block_digest0(new_blk, d0);
7504  if (!d0_1)
7505  {
7506  BM_ASSERT(bm::bit_is_all_zero(new_blk));
7507  blockman_.get_allocator().free_bit_block(new_blk);
7508  new_blk = 0;
7509  }
7510  else
7511  {
7512  BM_ASSERT(!bm::bit_is_all_zero(new_blk));
7513  }
7514  blockman_.get_allocator().free_gap_block(gap_blk, blockman_.glen());
7515  blockman_.set_block_ptr(i, j, new_blk);
7516 
7517  return;
7518  }
7519  else // our block is BITSET-type or FULL_BLOCK
7520  {
7521  if (BM_IS_GAP(arg_blk)) // argument block is GAP-type
7522  {
7523  const bm::gap_word_t* arg_gap = BMGAP_PTR(arg_blk);
7524  if (bm::gap_is_all_zero(arg_gap))
7525  {
7526  blockman_.zero_block(i, j);
7527  return;
7528  }
7529  // FULL & GAP is common when AND with set_range() mask
7530  //
7531  if (IS_FULL_BLOCK(blk)) // FULL & gap = gap
7532  {
7533  bool is_new_gap;
7534  bm::word_t* new_blk = blockman_.clone_gap_block(arg_gap, is_new_gap);
7535  if (is_new_gap)
7536  BMSET_PTRGAP(new_blk);
7537 
7538  blockman_.set_block_ptr(i, j, new_blk);
7539 
7540  return;
7541  }
7542  // BIT & GAP
7543  bm::gap_and_to_bitset(blk, arg_gap);
7544  bool empty = bm::bit_is_all_zero(blk);
7545  if (empty) // operation converged bit-block to empty
7546  blockman_.zero_block(i, j);
7547 
7548  return;
7549  } // if arg_gap
7550  }
7551 
7552  // FULL & bit is common when AND with set_range() mask
7553  //
7554  if (IS_FULL_BLOCK(blk)) // FULL & bit = bit
7555  {
7556  bm::word_t* new_blk = blockman_.get_allocator().alloc_bit_block();
7557  bm::bit_block_copy(new_blk, arg_blk);
7558  blockman_.set_block_ptr(i, j, new_blk);
7559 
7560  return;
7561  }
7562  auto any_bits = bm::bit_block_and(blk, arg_blk);
7563  if (!any_bits)
7564  {
7565  blockman_.get_allocator().free_bit_block(blk);
7566  blockman_.set_block_ptr(i, j, 0);
7567  }
7568 }
7569 
7570 //---------------------------------------------------------------------
7571 
7572 template<class Alloc>
7574  unsigned i, unsigned j, bm::word_t* blk, const bm::word_t* arg_blk)
7575 {
7576  BM_ASSERT(arg_blk && blk);
7577 
7578  if (IS_FULL_BLOCK(arg_blk))
7579  {
7580  blockman_.zero_block(i, j);
7581  return;
7582  }
7583 
7584  gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
7585 
7586  if (BM_IS_GAP(blk)) // our block GAP-type
7587  {
7588  bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
7589  if (BM_IS_GAP(arg_blk)) // both blocks GAP-type
7590  {
7591  const bm::gap_word_t* res;
7592  unsigned res_len;
7593  res = bm::gap_operation_sub(gap_blk,
7594  BMGAP_PTR(arg_blk),
7595  tmp_buf,
7596  res_len);
7597 
7598  BM_ASSERT(res == tmp_buf);
7599  BM_ASSERT(!(res == tmp_buf && res_len == 0));
7600 
7601  blockman_.assign_gap_check(i, j, res, ++res_len, blk, tmp_buf);
7602  return;
7603  }
7604  // else: argument is BITSET-type (own block is GAP)
7605  blk = blockman_.convert_gap2bitset(i, j, gap_blk);
7606  // fall through to bit-block to bit-block operation
7607  }
7608  else // our block is BITSET-type or FULL_BLOCK
7609  {
7610  if (BM_IS_GAP(arg_blk)) // argument block is GAP-type
7611  {
7612  if (!IS_FULL_BLOCK(blk)) // gap combined to bitset
7613  {
7614  bm::gap_sub_to_bitset(blk, BMGAP_PTR(arg_blk));
7615  bool empty = bm::bit_is_all_zero(blk);
7616  if (empty) // operation converged bit-block to empty
7617  blockman_.zero_block(i, j);
7618  return;
7619  }
7620  // the worst case: convert arg block to bitset
7621  arg_blk =
7623  BMGAP_PTR(arg_blk),
7625  }
7626  }
7627 
7628  // Now here we combine two plain bitblocks using supplied bit function.
7629  bm::word_t* dst = blk;
7630 
7631  bm::word_t* ret;
7632  if (!dst || !arg_blk)
7633  return;
7634 
7635  ret = bm::bit_operation_sub(dst, arg_blk);
7636  if (ret && ret == arg_blk)
7637  {
7638  ret = blockman_.get_allocator().alloc_bit_block();
7639  bm::bit_andnot_arr_ffmask(ret, arg_blk);
7640  }
7641 
7642  if (ret != dst) // block mutation
7643  {
7644  blockman_.set_block_ptr(i, j, ret);
7645  if (IS_VALID_ADDR(dst))
7646  blockman_.get_allocator().free_bit_block(dst);
7647  }
7648 }
7649 
7650 //---------------------------------------------------------------------
7651 
7652 template<class Alloc>
7653 void
7655  bool gap,
7656  bm::word_t* blk,
7657  const bm::word_t* arg_blk,
7658  bool arg_gap,
7659  bm::operation opcode)
7660 {
7661  gap_word_t tmp_buf[bm::gap_equiv_len * 3]; // temporary result
7662  const bm::gap_word_t* res;
7663  unsigned res_len;
7664 
7665  if (opcode == BM_OR || opcode == BM_XOR)
7666  {
7667  if (!blk && arg_gap)
7668  {
7669  blk = blockman_.clone_gap_block(BMGAP_PTR(arg_blk), gap);
7670  blockman_.set_block(nb, blk, gap);
7671  return;
7672  }
7673  }
7674 
7675  if (gap) // our block GAP-type
7676  {
7677  if (arg_gap) // both blocks GAP-type
7678  {
7679  {
7680  gap_operation_func_type gfunc =
7682  BM_ASSERT(gfunc);
7683  res = (*gfunc)(BMGAP_PTR(blk),
7684  BMGAP_PTR(arg_blk),
7685  tmp_buf,
7686  res_len);
7687  }
7688  BM_ASSERT(res == tmp_buf);
7689  BM_ASSERT(!(res == tmp_buf && res_len == 0));
7690 
7691  // if as a result of the operation gap block turned to zero
7692  // we can now replace it with NULL
7693  if (bm::gap_is_all_zero(res))
7694  blockman_.zero_block(nb);
7695  else
7696  blockman_.assign_gap(nb, res, ++res_len, blk, tmp_buf);
7697  return;
7698  }
7699  else // argument is BITSET-type (own block is GAP)
7700  {
7701  // since we can not combine blocks of mixed type
7702  // we need to convert our block to bitset
7703 
7704  if (arg_blk == 0) // Combining against an empty block
7705  {
7706  switch (opcode)
7707  {
7708  case BM_AND: // ("Value" AND 0) == 0
7709  blockman_.zero_block(nb);
7710  return;
7711  case BM_OR: case BM_SUB: case BM_XOR:
7712  return; // nothing to do
7713  default:
7714  return; // nothing to do
7715  }
7716  }
7717  gap_word_t* gap_blk = BMGAP_PTR(blk);
7718  blk = blockman_.convert_gap2bitset(nb, gap_blk);
7719  }
7720  }
7721  else // our block is BITSET-type
7722  {
7723  if (arg_gap) // argument block is GAP-type
7724  {
7725  if (IS_VALID_ADDR(blk))
7726  {
7727  // special case, maybe we can do the job without
7728  // converting the GAP argument to bitblock
7731  BM_ASSERT(gfunc);
7732  (*gfunc)(blk, BMGAP_PTR(arg_blk));
7733 
7734  // TODO: commented out optimization, because it can be very slow
7735  // need to take into account previous operation not to make
7736  // fruitless attempts here
7737  //blockman_.optimize_bit_block(nb);
7738  return;
7739  }
7740 
7741  // the worst case we need to convert argument block to
7742  // bitset type.
7744  arg_blk =
7746  BMGAP_PTR(arg_blk),
7748  }
7749  }
7750 
7751  // Now here we combine two plain bitblocks using supplied bit function.
7752  bm::word_t* dst = blk;
7753 
7754  bm::word_t* ret;
7755  if (dst == 0 && arg_blk == 0)
7756  return;
7757 
7758  switch (opcode)
7759  {
7760  case BM_AND:
7761  ret = bm::bit_operation_and(dst, arg_blk);
7762  goto copy_block;
7763  case BM_XOR:
7764  ret = bm::bit_operation_xor(dst, arg_blk);
7765  if (ret && (ret == arg_blk) && IS_FULL_BLOCK(dst))
7766  {
7767  ret = blockman_.get_allocator().alloc_bit_block();
7768 #ifdef BMVECTOPT
7769  VECT_XOR_ARR_2_MASK(ret,
7770  arg_blk,
7771  arg_blk + bm::set_block_size,
7772  ~0u);
7773 #else
7774  bm::wordop_t* dst_ptr = (wordop_t*)ret;
7775  const bm::wordop_t* wrd_ptr = (wordop_t*) arg_blk;
7776  const bm::wordop_t* wrd_end =
7777  (wordop_t*) (arg_blk + bm::set_block_size);
7778 
7779  do
7780  {
7781  dst_ptr[0] = bm::all_bits_mask ^ wrd_ptr[0];
7782  dst_ptr[1] = bm::all_bits_mask ^ wrd_ptr[1];
7783  dst_ptr[2] = bm::all_bits_mask ^ wrd_ptr[2];
7784  dst_ptr[3] = bm::all_bits_mask ^ wrd_ptr[3];
7785 
7786  dst_ptr+=4;
7787  wrd_ptr+=4;
7788 
7789  } while (wrd_ptr < wrd_end);
7790 #endif
7791  break;
7792  }
7793  goto copy_block;
7794  case BM_OR:
7795  ret = bm::bit_operation_or(dst, arg_blk);
7796  copy_block:
7797  if (ret && (ret == arg_blk) && !IS_FULL_BLOCK(ret))
7798  {
7799  ret = blockman_.get_allocator().alloc_bit_block();
7800  bm::bit_block_copy(ret, arg_blk);
7801  }
7802  break;
7803 
7804  case BM_SUB:
7805  ret = bit_operation_sub(dst, arg_blk);
7806  if (ret && ret == arg_blk)
7807  {
7808  ret = blockman_.get_allocator().alloc_bit_block();
7809  bm::bit_andnot_arr_ffmask(ret, arg_blk);
7810  }
7811  break;
7812  default:
7813  BM_ASSERT(0);
7814  ret = 0;
7815  }
7816 
7817  if (ret != dst) // block mutation
7818  {
7819  blockman_.set_block(nb, ret);
7820  if (IS_VALID_ADDR(dst))
7821  {
7822  blockman_.get_allocator().free_bit_block(dst);
7823  }
7824  }
7825 }
7826 
7827 //---------------------------------------------------------------------
7828 
7829 template<class Alloc>
7831  size_type right)
7832 {
7833  block_idx_type nblock_left = left >> bm::set_block_shift;
7834  block_idx_type nblock_right = right >> bm::set_block_shift;
7835 
7836  unsigned nbit_right = unsigned(right & bm::set_block_mask);
7837 
7838  unsigned r =
7839  (nblock_left == nblock_right) ? nbit_right :(bm::bits_in_block-1);
7840 
7841  bm::gap_word_t tmp_gap_blk[5];
7842  tmp_gap_blk[0] = 0; // just to silence GCC warning on uninit var
7843 
7844  // Set bits in the starting block
7845  //
7846  block_idx_type nb;
7847  unsigned i, j;
7848  bm::word_t* block;
7849  unsigned nbit_left = unsigned(left & bm::set_block_mask);
7850  if ((nbit_left == 0) && (r == bm::bits_in_block - 1)) // full block
7851  {
7852  nb = nblock_left;
7853  }
7854  else
7855  {
7856  gap_init_range_block<gap_word_t>(tmp_gap_blk,
7857  (gap_word_t)nbit_left,
7858  (gap_word_t)r,
7859  (gap_word_t)1);
7860  bm::get_block_coord(nblock_left, i, j);
7861  block = blockman_.get_block_ptr(i, j);
7862  combine_operation_with_block(nblock_left,
7863  BM_IS_GAP(block),
7864  block,
7865  (bm::word_t*) tmp_gap_blk,
7866  1, BM_OR);
7867 
7868  if (nblock_left == nblock_right) // in one block
7869  return;
7870  nb = nblock_left+1;
7871  }
7872 
7873  // Set all full blocks between left and right
7874  //
7875  block_idx_type nb_to = nblock_right + (nbit_right ==(bm::bits_in_block-1));
7876  BM_ASSERT(nb_to >= nblock_right);
7877  if (nb < nb_to)
7878  {
7879  BM_ASSERT(nb_to);
7880  blockman_.set_all_set(nb, nb_to-1);
7881  }
7882 
7883  if (nb_to > nblock_right)
7884  return;
7885 
7886  bm::get_block_coord(nblock_right, i, j);
7887  block = blockman_.get_block_ptr(i, j);
7888 
7889  gap_init_range_block<gap_word_t>(tmp_gap_blk,
7890  (gap_word_t)0,
7891  (gap_word_t)nbit_right,
7892  (gap_word_t)1);
7893 
7894  combine_operation_with_block(nblock_right,
7895  BM_IS_GAP(block),
7896  block,
7897  (bm::word_t*) tmp_gap_blk,
7898  1, BM_OR);
7899 }
7900 
7901 //---------------------------------------------------------------------
7902 
7903 template<class Alloc>
7905  size_type right)
7906 {
7907  block_idx_type nb;
7908  unsigned i, j;
7909 
7910  // calculate logical number of start and destination blocks
7911  block_idx_type nblock_left = left >> bm::set_block_shift;
7912  block_idx_type nblock_right = right >> bm::set_block_shift;
7913 
7914  unsigned nbit_right = unsigned(right & bm::set_block_mask);
7915  unsigned r =
7916  (nblock_left == nblock_right) ? nbit_right : (bm::bits_in_block - 1);
7917 
7918  bm::gap_word_t tmp_gap_blk[5];
7919  tmp_gap_blk[0] = 0; // just to silence GCC warning on uninit var
7920 
7921  // Set bits in the starting block
7922  bm::word_t* block;
7923 
7924  unsigned nbit_left = unsigned(left & bm::set_block_mask);
7925  if ((nbit_left == 0) && (r == bm::bits_in_block - 1)) // full block
7926  {
7927  nb = nblock_left;
7928  }
7929  else
7930  {
7931  bm::gap_init_range_block<gap_word_t>(tmp_gap_blk,
7932  (gap_word_t)nbit_left,
7933  (gap_word_t)r,
7934  (gap_word_t)0);
7935  bm::get_block_coord(nblock_left, i, j);
7936  block = blockman_.get_block_ptr(i, j);
7937  combine_operation_with_block(nblock_left,
7938  BM_IS_GAP(block),
7939  block,
7940  (bm::word_t*) tmp_gap_blk,
7941  1,
7942  BM_AND);
7943 
7944  if (nblock_left == nblock_right) // in one block
7945  return;
7946  nb = nblock_left + 1;
7947  }
7948 
7949  // Clear all full blocks between left and right
7950 
7951  block_idx_type nb_to = nblock_right + (nbit_right == (bm::bits_in_block - 1));
7952  BM_ASSERT(nb_to >= nblock_right);
7953  if (nb < nb_to)
7954  {
7955  BM_ASSERT(nb_to);
7956  blockman_.set_all_zero(nb, nb_to - 1u);
7957  }
7958 
7959  if (nb_to > nblock_right)
7960  return;
7961 
7962  bm::get_block_coord(nblock_right, i, j);
7963  block = blockman_.get_block_ptr(i, j);
7964  gap_init_range_block<gap_word_t>(tmp_gap_blk,
7965  (gap_word_t)0,
7966  (gap_word_t)nbit_right,
7967  (gap_word_t)0);
7968 
7969  combine_operation_with_block(nblock_right,
7970  BM_IS_GAP(block),
7971  block,
7972  (bm::word_t*) tmp_gap_blk,
7973  1,
7974  BM_AND);
7975 }
7976 
7977 
7978 //---------------------------------------------------------------------
7979 
7980 template<class Alloc>
7982  size_type left,
7983  size_type right)
7984 {
7985  if (!bvect.blockman_.is_init())
7986  {
7987  clear();
7988  return;
7989  }
7990 
7991  if (blockman_.is_init())
7992  {
7994  }
7995  if (left > right)
7996  bm::xor_swap(left, right);
7997 
7998  copy_range_no_check(bvect, left, right);
7999 }
8000 
8001 //---------------------------------------------------------------------
8002 
8003 template<class Alloc>
8005 {
8006  BM_ASSERT(left <= right);
8007  BM_ASSERT_THROW(right < bm::id_max, BM_ERR_RANGE);
8008 
8009  if (left)
8010  {
8011  clear_range_no_check(0, left - 1); // TODO: optimize clear from
8012  }
8013  if (right < bm::id_max - 1)
8014  {
8015  size_type last;
8016  bool found = find_reverse(last);
8017  if (found && (last > right))
8018  clear_range_no_check(right + 1, last);
8019  }
8020  BM_ASSERT(count() == count_range(left, right));
8021 }
8022 
8023 //---------------------------------------------------------------------
8024 
8025 template<class Alloc>
8027  size_type left,
8028  size_type right)
8029 {
8030  BM_ASSERT(left <= right);
8031  BM_ASSERT_THROW(right < bm::id_max, BM_ERR_RANGE);
8032 
8033  // copy all block(s) belonging to our range
8034  block_idx_type nblock_left = (left >> bm::set_block_shift);
8035  block_idx_type nblock_right = (right >> bm::set_block_shift);
8036 
8037  blockman_.copy(bvect.blockman_, nblock_left, nblock_right);
8038 
8039  if (left)
8040  {
8041  size_type from =
8042  (left < bm::gap_max_bits) ? 0 : (left - bm::gap_max_bits);
8043  clear_range_no_check(from, left-1); // TODO: optimize clear from
8044  }
8045  if (right < bm::id_max-1)
8046  {
8047  size_type last;
8048  bool found = find_reverse(last);
8049  if (found && (last > right))
8050  clear_range_no_check(right+1, last);
8051  }
8052  //keep_range_no_check(left, right); // clear the flanks
8053 }
8054 
8055 //---------------------------------------------------------------------
8056 
8057 template<class Alloc>
8059 {
8060  if (is_ro())
8061  return; // nothing to do read-only vector already
8063  swap(bv_ro);
8064 }
8065 
8066 //---------------------------------------------------------------------
8067 
8068 template<class Alloc>
8070 {
8071 #ifndef BM_NO_STL
8072  throw std::bad_alloc();
8073 #else
8074  BM_THROW(BM_ERR_BADALLOC);
8075 #endif
8076 }
8077 
8078 //---------------------------------------------------------------------
8079 //
8080 //---------------------------------------------------------------------
8081 
8082 template<class Alloc>
8084 {
8085  BM_ASSERT(this->valid());
8086 
8087  block_descr_type* bdescr = &(this->bdescr_);
8088  if (this->block_type_) // GAP
8089  {
8090  BM_ASSERT(this->block_type_ == 1);
8091  ++this->position_;
8092  if (--(bdescr->gap_.gap_len))
8093  return true;
8094  // next gap is "OFF" by definition.
8095  if (*(bdescr->gap_.ptr) != bm::gap_max_bits - 1)
8096  {
8097  gap_word_t prev = *(bdescr->gap_.ptr);
8098  unsigned val = *(++(bdescr->gap_.ptr));
8099  this->position_ += val - prev;
8100  // next gap is now "ON"
8101  if (*(bdescr->gap_.ptr) != bm::gap_max_bits - 1)
8102  {
8103  prev = *(bdescr->gap_.ptr);
8104  val = *(++(bdescr->gap_.ptr));
8105  bdescr->gap_.gap_len = (gap_word_t)(val - prev);
8106  return true; // next "ON" found;
8107  }
8108  }
8109  }
8110  else // BIT
8111  {
8112  unsigned short idx = ++(bdescr->bit_.idx);
8113  if (idx < bdescr->bit_.cnt)
8114  {
8115  this->position_ = bdescr->bit_.pos + bdescr->bit_.bits[idx];
8116  return true;
8117  }
8118  this->position_ +=
8119  (bm::set_bitscan_wave_size * 32) - bdescr->bit_.bits[--idx];
8120  bdescr->bit_.ptr += bm::set_bitscan_wave_size;
8121  if (decode_bit_group(bdescr))
8122  return true;
8123  }
8124 
8125  if (search_in_blocks())
8126  return true;
8127 
8128  this->invalidate();
8129  return false;
8130 }
8131 
8132 //---------------------------------------------------------------------
8133 
8134 
8135 template<class Alloc>
8137 {
8138  if (!this->valid())
8139  return false;
8140  if (!rank)
8141  return this->valid(); // nothing to do
8142 
8143  for (; rank; --rank)
8144  {
8145  block_descr_type* bdescr = &(this->bdescr_);
8146  switch (this->block_type_)
8147  {
8148  case 0: // BitBlock
8149  for (; rank; --rank)
8150  {
8151  unsigned short idx = ++(bdescr->bit_.idx);
8152  if (idx < bdescr->bit_.cnt)
8153  {
8154  this->position_ = bdescr->bit_.pos + bdescr->bit_.bits[idx];
8155  continue;
8156  }
8157  this->position_ +=
8158  (bm::set_bitscan_wave_size * 32) - bdescr->bit_.bits[--idx];
8159  bdescr->bit_.ptr += bm::set_bitscan_wave_size;
8160 
8161  if (!decode_bit_group(bdescr, rank))
8162  break;
8163  } // for rank
8164  break;
8165  case 1: // DGAP Block
8166  for (; rank; --rank) // TODO: better skip logic
8167  {
8168  ++this->position_;
8169  if (--(bdescr->gap_.gap_len))
8170  continue;
8171 
8172  // next gap is "OFF" by definition.
8173  if (*(bdescr->gap_.ptr) == bm::gap_max_bits - 1)
8174  break;
8175  gap_word_t prev = *(bdescr->gap_.ptr);
8176  unsigned int val = *(++(bdescr->gap_.ptr));
8177 
8178  this->position_ += val - prev;
8179  // next gap is now "ON"
8180  if (*(bdescr->gap_.ptr) == bm::gap_max_bits - 1)
8181  break;
8182  prev = *(bdescr->gap_.ptr);
8183  val = *(++(bdescr->gap_.ptr));
8184  bdescr->gap_.gap_len = (gap_word_t)(val - prev);
8185  } // for rank
8186  break;
8187  default:
8188  BM_ASSERT(0);
8189  } // switch
8190 
8191  if (!rank)
8192  return true;
8193 
8194  if (!search_in_blocks())
8195  {
8196  this->invalidate();
8197  return false;
8198  }
8199  } // for rank
8200 
8201  return this->valid();
8202 }
8203 
8204 
8205 //---------------------------------------------------------------------
8206 
8207 
8208 template<class Alloc>
8210 {
8211  if (pos == 0)
8212  {
8213  go_first();
8214  return this->valid();
8215  }
8216 
8217  size_type new_pos = this->bv_->check_or_next(pos); // find the true pos
8218  if (!new_pos) // no bits available
8219  {
8220  this->invalidate();
8221  return false;
8222  }
8223  BM_ASSERT(new_pos >= pos);
8224  pos = new_pos;
8225 
8226 
8227  this->position_ = pos;
8228  size_type nb = this->block_idx_ = (pos >> bm::set_block_shift);
8230  this->bv_->get_blocks_manager();
8231  unsigned i0, j0;
8232  bm::get_block_coord(nb, i0, j0);
8233  this->block_ = bman.get_block(i0, j0);
8234 
8235  BM_ASSERT(this->block_);
8236 
8237  this->block_type_ = (bool)BM_IS_GAP(this->block_);
8238 
8239  block_descr_type* bdescr = &(this->bdescr_);
8240  unsigned nbit = unsigned(pos & bm::set_block_mask);
8241 
8242  if (this->block_type_) // gap
8243  {
8244  this->position_ = nb * bm::set_block_size * 32;
8246 
8247  if (this->position_ == pos)
8248  return this->valid();
8249  this->position_ = pos;
8250 
8251  gap_word_t* gptr = BMGAP_PTR(this->block_);
8252  unsigned is_set;
8253  unsigned gpos = bm::gap_bfind(gptr, nbit, &is_set);
8254  BM_ASSERT(is_set);
8255 
8256  bdescr->gap_.ptr = gptr + gpos;
8257  if (gpos == 1)
8258  {
8259  bdescr->gap_.gap_len = bm::gap_word_t(gptr[gpos] - (nbit - 1));
8260  }
8261  else
8262  {
8263  bm::gap_word_t interval = bm::gap_word_t(gptr[gpos] - gptr[gpos - 1]);
8264  bm::gap_word_t interval2 = bm::gap_word_t(nbit - gptr[gpos - 1]);
8265  bdescr->gap_.gap_len = bm::gap_word_t(interval - interval2 + 1);
8266  }
8267  }
8268  else // bit
8269  {
8270  if (nbit == 0)
8271  {
8273  return this->valid();
8274  }
8275 
8276  unsigned nword = unsigned(nbit >> bm::set_word_shift);
8277 
8278  // check if we need to step back to match the wave
8279  unsigned parity = nword % bm::set_bitscan_wave_size;
8280  bdescr->bit_.ptr = this->block_ + (nword - parity);
8281  bdescr->bit_.cnt = bm::bitscan_wave(bdescr->bit_.ptr, bdescr->bit_.bits);
8282  BM_ASSERT(bdescr->bit_.cnt);
8283  bdescr->bit_.pos = (nb * bm::set_block_size * 32) + ((nword - parity) * 32);
8284  bdescr->bit_.idx = 0;
8285  nbit &= bm::set_word_mask;
8286  nbit += 32 * parity;
8287  for (unsigned i = 0; i < bdescr->bit_.cnt; ++i)
8288  {
8289  if (bdescr->bit_.bits[i] == nbit)
8290  return this->valid();
8291  bdescr->bit_.idx++;
8292  } // for
8293  BM_ASSERT(0);
8294  }
8295  return this->valid();
8296 }
8297 
8298 //---------------------------------------------------------------------
8299 
8300 template<class Alloc>
8302 {
8303  BM_ASSERT(this->bv_);
8304 
8305  blocks_manager_type* bman = &(this->bv_->blockman_);
8306  if (!bman->is_init())
8307  {
8308  this->invalidate();
8309  return;
8310  }
8311 
8312  bm::word_t*** blk_root = bman->top_blocks_root();
8313  this->block_idx_ = this->position_= 0;
8314  unsigned i, j;
8315 
8316  for (i = 0; i < bman->top_block_size(); ++i)
8317  {
8318  bm::word_t** blk_blk = blk_root[i];
8319  if (blk_blk == 0) // not allocated
8320  {
8322  this->position_ += bm::bits_in_array;
8323  continue;
8324  }
8325 
8326  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
8327  blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
8328 
8329  for (j = 0; j < bm::set_sub_array_size; ++j,++(this->block_idx_))
8330  {
8331  this->block_ = blk_blk[j];
8332  if (this->block_ == 0)
8333  {
8334  this->position_ += bits_in_block;
8335  continue;
8336  }
8337  if (BM_IS_GAP(this->block_))
8338  {
8339  this->block_type_ = 1;
8340  if (search_in_gapblock())
8341  return;
8342  }
8343  else
8344  {
8345  if (this->block_ == FULL_BLOCK_FAKE_ADDR)
8346  this->block_ = FULL_BLOCK_REAL_ADDR;
8347  this->block_type_ = 0;
8348  if (search_in_bitblock())
8349  return;
8350  }
8351  } // for j
8352  } // for i
8353 
8354  this->invalidate();
8355 }
8356 
8357 //---------------------------------------------------------------------
8358 
8359 template<class Alloc>
8360 bool
8362 {
8363  bdescr->bit_.cnt = bm::bitscan_wave(bdescr->bit_.ptr, bdescr->bit_.bits);
8364  if (bdescr->bit_.cnt) // found
8365  {
8366  bdescr->bit_.idx = 0;
8367  return true;
8368  }
8369  return false;
8370 }
8371 
8372 //---------------------------------------------------------------------
8373 
8374 template<class Alloc>
8375 bool
8377 {
8378  const word_t* block_end = this->block_ + bm::set_block_size;
8379  for (; bdescr->bit_.ptr < block_end;)
8380  {
8381  if (decode_wave(bdescr))
8382  {
8383  bdescr->bit_.pos = this->position_;
8384  this->position_ += bdescr->bit_.bits[0];
8385  return true;
8386  }
8387  this->position_ += bm::set_bitscan_wave_size * 32; // wave size
8388  bdescr->bit_.ptr += bm::set_bitscan_wave_size;
8389  } // for
8390  return false;
8391 }
8392 
8393 //---------------------------------------------------------------------
8394 
8395 template<class Alloc>
8396 bool
8399 {
8400  const word_t* BMRESTRICT block_end = this->block_ + bm::set_block_size;
8401  for (; bdescr->bit_.ptr < block_end;)
8402  {
8403  unsigned cnt;
8404  #if defined(BMAVX512OPT) || defined(BMAVX2OPT) || defined(BM64OPT) || defined(BM64_SSE4)
8405  {
8406  const bm::id64_t* w64_p = (bm::id64_t*)bdescr->bit_.ptr;
8408  cnt = bm::word_bitcount64(w64_p[0]);
8409  cnt += bm::word_bitcount64(w64_p[1]);
8410  }
8411  #else
8412  const bm::word_t* BMRESTRICT w = bdescr->bit_.ptr;
8413  unsigned c1= bm::word_bitcount(w[0]);
8414  unsigned c2 = bm::word_bitcount(w[1]);
8415  cnt = c1 + c2;
8416  c1= bm::word_bitcount(w[2]);
8417  c2 = bm::word_bitcount(w[3]);
8418  cnt += c1 + c2;
8419  #endif
8420 
8421  if (rank > cnt)
8422  {
8423  rank -= cnt;
8424  }
8425  else
8426  {
8427  if (decode_wave(bdescr))
8428  {
8429  bdescr->bit_.pos = this->position_;
8430  this->position_ += bdescr->bit_.bits[0];
8431  return true;
8432  }
8433  }
8434  this->position_ += bm::set_bitscan_wave_size * 32; // wave size
8435  bdescr->bit_.ptr += bm::set_bitscan_wave_size;
8436  } // for
8437  return false;
8438 }
8439 
8440 
8441 //---------------------------------------------------------------------
8442 
8443 template<class Alloc>
8445 {
8446  BM_ASSERT(this->block_type_ == 0);
8447 
8448  block_descr_type* bdescr = &(this->bdescr_);
8449  bdescr->bit_.ptr = this->block_;
8450  return decode_bit_group(bdescr);
8451 }
8452 
8453 //---------------------------------------------------------------------
8454 
8455 template<class Alloc>
8457 {
8458  BM_ASSERT(this->block_type_ == 1);
8459 
8460  block_descr_type* bdescr = &(this->bdescr_);
8461  bdescr->gap_.ptr = BMGAP_PTR(this->block_);
8462  unsigned bitval = *(bdescr->gap_.ptr) & 1;
8463 
8464  ++(bdescr->gap_.ptr);
8465 
8466  for (;true;)
8467  {
8468  unsigned val = *(bdescr->gap_.ptr);
8469  if (bitval)
8470  {
8471  gap_word_t* first = BMGAP_PTR(this->block_) + 1;
8472  if (bdescr->gap_.ptr == first)
8473  {
8474  bdescr->gap_.gap_len = (gap_word_t)(val + 1);
8475  }
8476  else
8477  {
8478  bdescr->gap_.gap_len =
8479  (gap_word_t)(val - *(bdescr->gap_.ptr-1));
8480  }
8481  return true;
8482  }
8483  this->position_ += val + 1;
8484  if (val == bm::gap_max_bits - 1)
8485  break;
8486  bitval ^= 1;
8487  ++(bdescr->gap_.ptr);
8488  }
8489  return false;
8490 }
8491 
8492 //---------------------------------------------------------------------
8493 
8494 template<class Alloc>
8496 {
8497  ++(this->block_idx_);
8498  const blocks_manager_type& bman = this->bv_->blockman_;
8499  block_idx_type i = this->block_idx_ >> bm::set_array_shift;
8500  block_idx_type top_block_size = bman.top_block_size();
8501  bm::word_t*** blk_root = bman.top_blocks_root();
8502  for (; i < top_block_size; ++i)
8503  {
8504  bm::word_t** blk_blk = blk_root[i];
8505  if (blk_blk == 0)
8506  {
8507  // fast scan fwd in top level
8509  size_type pos = this->position_ + bm::bits_in_array;
8510  for (++i; i < top_block_size; ++i)
8511  {
8512  if (blk_root[i])
8513  break;
8514  bn += bm::set_sub_array_size;
8515  pos += bm::bits_in_array;
8516  } // for i
8517  this->block_idx_ = bn;
8518  this->position_ = pos;
8519  if ((i < top_block_size) && blk_root[i])
8520  --i;
8521  continue;
8522  }
8523  if ((bm::word_t*)blk_blk == FULL_BLOCK_FAKE_ADDR)
8524  blk_blk = FULL_SUB_BLOCK_REAL_ADDR;
8525 
8527 
8528  for(; j < bm::set_sub_array_size; ++j, ++(this->block_idx_))
8529  {
8530  this->block_ = blk_blk[j];
8531  if (this->block_ == 0)
8532  {
8533  this->position_ += bm::bits_in_block;
8534  continue;
8535  }
8536  this->block_type_ = BM_IS_GAP(this->block_);
8537  if (this->block_type_)
8538  {
8539  if (search_in_gapblock())
8540  return true;
8541  }
8542  else
8543  {
8544  if (this->block_ == FULL_BLOCK_FAKE_ADDR)
8545  this->block_ = FULL_BLOCK_REAL_ADDR;
8546  if (search_in_bitblock())
8547  return true;
8548  }
8549  } // for j
8550  } // for i
8551  return false;
8552 }
8553 
8554 //---------------------------------------------------------------------
8555 
8556 
8557 } // namespace
8558 
8559 
8560 #ifdef _MSC_VER
8561 #pragma warning( pop )
8562 #endif
8563 
8564 
8565 #endif
static void * Alloc(size_t size)
Definition: asntypes.cpp:59
ncbi::TMaskedQueryRegions mask
#define BM_BORDER_TEST(blk, idx)
Definition: bm.h:2649
#define BM_SUB_OP(x)
Definition: bm.h:6680
#define BM_XOR_OP(x)
Definition: bm.h:6492
#define BM_AND_OP(x)
Definition: bm.h:6585
#define BM_OR_OP(x)
Definition: bm.h:6419
#define BM_DECLARE_TEMP_BLOCK(x)
Definition: bm.h:47
Default SIMD friendly allocator.
#define VECT_XOR_ARR_2_MASK(dst, src, src_end, mask)
Definition: bmavx2.h:3432
Constants, lookup tables and typedefs.
Definitions(internal)
#define IS_FULL_BLOCK(addr)
Definition: bmdef.h:162
#define IS_VALID_ADDR(addr)
Definition: bmdef.h:161
#define BMRESTRICT
Definition: bmdef.h:203
#define BMNOEXCEPT
Definition: bmdef.h:82
#define BMGAP_PTR(ptr)
Definition: bmdef.h:189
#define BM_IS_GAP(ptr)
Definition: bmdef.h:191
#define BMSET_PTRGAP(ptr)
Definition: bmdef.h:190
#define BLOCK_ADDR_SAN(addr)
Definition: bmdef.h:160
#define BM_ASSERT
Definition: bmdef.h:139
#define BM_ASSERT_THROW(x, xerrcode)
Definition: bmdef.h:338
#define FULL_BLOCK_FAKE_ADDR
Definition: bmdef.h:158
#define FULL_SUB_BLOCK_REAL_ADDR
Definition: bmdef.h:159
#define FULL_BLOCK_REAL_ADDR
Definition: bmdef.h:157
Bit manipulation primitives (internal)
Forward declarations.
Rank-Select index structures.
SIMD target version definitions.
Algorithms for fast aggregation of a group of bit-vectors.
Definition: bmaggregator.h:122
Functor detects if any bit set.
Definition: bmblocks.h:250
Bitcounting functor filling the block counts array.
Definition: bmblocks.h:150
id_type last_block() const BMNOEXCEPT
Definition: bmblocks.h:168
id_type count() const BMNOEXCEPT
Definition: bmblocks.h:134
bitvector blocks manager Embedded class managing bit-blocks on very low level. Includes number of fun...
Definition: bmblocks.h:42
unsigned top_block_size_
Size of the top level block array in blocks_ tree.
Definition: bmblocks.h:2839
void set_glen(const gap_word_t *glevel_len) BMNOEXCEPT
Definition: bmblocks.h:1861
void set_all_zero(block_idx_type nb, block_idx_type nb_to) BMNOEXCEPT
set all-Zero block pointers for [start..end]
Definition: bmblocks.h:709
bm::word_t *** top_blocks_
Tree of blocks.
Definition: bmblocks.h:2837
arena * arena_
memory arena pointer
Definition: bmblocks.h:2847
bm::word_t * check_allocate_tempblock()
Definition: bmblocks.h:1815
unsigned find_max_top_blocks() const BMNOEXCEPT
calculate max top blocks size whithout NULL-tail
Definition: bmblocks.h:2154
bm::word_t * deoptimize_block(block_idx_type nb)
Make sure block turns into true bit-block if it is GAP or a full block.
Definition: bmblocks.h:1562
void return_tempblock(bm::word_t *block) BMNOEXCEPT
Definition: bmblocks.h:1849
void set_all_set(block_idx_type nb, block_idx_type nb_to)
set all-set block pointers for [start..end]
Definition: bmblocks.h:644
const bm::word_t *const * get_topblock(unsigned i) const BMNOEXCEPT
Function returns top-level block in 2-level blocks array.
Definition: bmblocks.h:587
void destroy_arena() BMNOEXCEPT
free all arena memory
Definition: bmblocks.h:2644
void move_from(blocks_manager &bm) BMNOEXCEPT
implementation of moving semantics
Definition: bmblocks.h:417
bm::gap_word_t * extend_gap_block(block_idx_type nb, gap_word_t *blk)
Extends GAP block to the next level or converts it to bit block.
Definition: bmblocks.h:1783
void assign_gap_check(unsigned i, unsigned j, const bm::gap_word_t *res, unsigned res_len, bm::word_t *blk, gap_word_t *tmp_buf)
Attach the result of a GAP logical operation but check if it is all 000.
Definition: bmblocks.h:958
bm::word_t ** check_alloc_top_subblock(unsigned nblk_blk)
Allocate top sub-block if not allocated.
Definition: bmblocks.h:1189
bm::word_t * temp_block_
Temp block.
Definition: bmblocks.h:2841
bm::word_t *** top_blocks_root() const BMNOEXCEPT
Returns root block in the tree.
Definition: bmblocks.h:595
void deinit_tree() BMNOEXCEPT
Definition: bmblocks.h:2124
const bm::word_t * get_block(block_idx_type nb, int *no_more_blocks) const BMNOEXCEPT
Returns current capacity (bits)
Definition: bmblocks.h:475
unsigned top_block_size() const BMNOEXCEPT
Returns size of the top block array in the tree.
Definition: bmblocks.h:1916
void free_temp_block() BMNOEXCEPT
Definition: bmblocks.h:1822
size_t calc_serialization_null_full() const BMNOEXCEPT
Calculate approximate memory needed to serialize big runs of 0000s and 111s (as blocks)
Definition: bmblocks.h:2205
void free_top_subblock(unsigned nblk_blk) BMNOEXCEPT
Definition: bmblocks.h:1167
const bm::word_t * get_block_ptr(unsigned i, unsigned j) const BMNOEXCEPT
Finds block in 2-level blocks array (unsinitized)
Definition: bmblocks.h:556
void assign_gap(block_idx_type nb, const bm::gap_word_t *res, unsigned res_len, bm::word_t *blk, gap_word_t *tmp_buf)
Attach the result of a GAP logical operation.
Definition: bmblocks.h:944
bm::id_t block_idx_type
Definition: bmblocks.h:52
allocator_type alloc_
allocator
Definition: bmblocks.h:2845
void init_tree()
allocate first level of descr. of blocks
Definition: bmblocks.h:2003
allocator_type & get_allocator() BMNOEXCEPT
Returns reference on the allocator.
Definition: bmblocks.h:1990
bool is_init() const BMNOEXCEPT
if tree of blocks already up
Definition: bmblocks.h:1998
void swap(blocks_manager &bm) BMNOEXCEPT
Swaps content.
Definition: bmblocks.h:397
void deallocate_top_subblock(unsigned nblk_blk) BMNOEXCEPT
Definition: bmblocks.h:2054
void copy_to_arena(const blocks_manager &bman)
calculate arena statistics, calculate and copy all blocks there
Definition: bmblocks.h:2538
bm::word_t * check_allocate_block(block_idx_type nb, unsigned content_flag, int initial_block_type, int *actual_block_type, bool allow_null_ret=true)
Function checks if block is not yet allocated, allocates it and sets to all-zero or all-one bits.
Definition: bmblocks.h:1069
void copy(const blocks_manager &blockman, block_idx_type block_from=0, block_idx_type block_to=bm::set_total_blocks)
Definition: bmblocks.h:2744
const gap_word_t * glen() const BMNOEXCEPT
Returns current GAP level vector.
Definition: bmblocks.h:1901
unsigned find_real_top_blocks() const BMNOEXCEPT
calculate top blocks which are not NULL and not FULL
Definition: bmblocks.h:2136
void zero_block(block_idx_type nb) BMNOEXCEPT
Free block, make it zero pointer in the tree.
Definition: bmblocks.h:1622
bm::word_t * deoptimize_block_no_check(bm::word_t *block, unsigned i, unsigned j)
Definition: bmblocks.h:1590
void optimize_bit_block(unsigned i, unsigned j, int opt_mode)
Optimize bit-block at i-j position.
Definition: bmblocks.h:1406
bm::word_t * borrow_tempblock()
Definition: bmblocks.h:1836
void optimize_block(unsigned i, unsigned j, bm::word_t *block, bm::word_t *temp_block, int opt_mode, bv_statistics *bv_stat)
Definition: bmblocks.h:2273
bm::word_t ** alloc_top_subblock(unsigned nblk_blk)
Definition: bmblocks.h:1176
unsigned reserve_top_blocks(unsigned top_blocks)
Make sure blocks manager has enough blocks capacity.
Definition: bmblocks.h:1936
bm::word_t * set_block(block_idx_type nb, bm::word_t *block)
Places new block into descriptors table, returns old block's address.
Definition: bmblocks.h:1202
bm::word_t * convert_gap2bitset(block_idx_type nb, const gap_word_t *gap_block=0)
Converts block from type gap to conventional bitset block.
Definition: bmblocks.h:1513
void optimize_tree(bm::word_t *temp_block, int opt_mode, bv_statistics *bv_stat)
Definition: bmblocks.h:2390
void set_block_ptr(block_idx_type nb, bm::word_t *block)
Places new block into blocks table.
Definition: bmblocks.h:1474
bm::word_t * clone_gap_block(const bm::gap_word_t *gap_block, bool &gap_res)
Clone GAP block from another GAP It can mutate into a bit-block if does not fit.
Definition: bmblocks.h:838
static bm::id_t block_bitcount(const bm::word_t *block) BMNOEXCEPT
Count number of bits ON in the block.
Definition: bmblocks.h:1698
bm::word_t * clone_assign_block(unsigned i, unsigned j, const bm::word_t *src_block, bool invert=false)
Clone block, assign to i-j position.
Definition: bmblocks.h:894
void reserve(id_type max_bits)
reserve capacity for specified number of bits
Definition: bmblocks.h:1924
void stat_correction(bv_statistics *stat) noexcept
Definition: bmblocks.h:2443
Output iterator iterator designed to set "ON" bits based on input sequence of integers.
Definition: bm.h:465
bulk_insert_iterator(const insert_iterator &iit)
Definition: bm.h:506
size_type * buf_
bulk insert buffer
Definition: bm.h:592
bulk_insert_iterator & operator++()
Definition: bm.h:561
bm::sort_order sorted_
sort order hint
Definition: bm.h:594
bulk_insert_iterator(const bulk_insert_iterator &iit)
Definition: bm.h:497
bulk_insert_iterator & operator=(size_type n)
Definition: bm.h:544
bvector_type::size_type size_type
Definition: bm.h:471
bulk_insert_iterator & operator=(const bulk_insert_iterator &ii)
Definition: bm.h:522
bulk_insert_iterator(bulk_insert_iterator &&iit) noexcept
Definition: bm.h:514
bulk_insert_iterator & operator*()
Definition: bm.h:559
size_type buf_size_
current buffer size
Definition: bm.h:593
std::output_iterator_tag iterator_category
Definition: bm.h:468
static size_type buf_size_max() noexcept
Definition: bm.h:581
bulk_insert_iterator(bvector< Alloc > &bvect, bm::sort_order so=BM_UNKNOWN) noexcept
Definition: bm.h:487
bvector_type * bvect_
target bvector
Definition: bm.h:591
bulk_insert_iterator & operator++(int)
Definition: bm.h:563
bulk_insert_iterator() noexcept
Definition: bm.h:477
bvector_type * get_bvector() const noexcept
Definition: bm.h:577
bulk_insert_iterator & operator=(bulk_insert_iterator &&ii) noexcept
Definition: bm.h:533
bvector_type::size_type value_type
Definition: bm.h:472
bm::bvector< Alloc > bvector_type
Definition: bm.h:470
Constant iterator designed to enumerate "ON" bits counted_enumerator keeps bitcount,...
Definition: bm.h:734
counted_enumerator(const enumerator &en) noexcept
Definition: bm.h:741
counted_enumerator operator++(int)
Definition: bm.h:762
counted_enumerator() noexcept
Definition: bm.h:739
std::input_iterator_tag iterator_category
Definition: bm.h:737
counted_enumerator & operator=(const enumerator &en) noexcept
Definition: bm.h:746
counted_enumerator & go_to(size_type pos)
counted_enumerator & operator++() noexcept
Definition: bm.h:755
size_type count() const noexcept
Number of bits ON starting from the .
Definition: bm.h:775
Constant iterator designed to enumerate "ON" bits.
Definition: bm.h:603
unsigned & reference
Definition: bm.h:611
std::input_iterator_tag iterator_category
Definition: bm.h:606
size_type value() const noexcept
Get current position (value)
Definition: bm.h:659
static bool decode_wave(block_descr_type *bdescr) noexcept
Definition: bm.h:8361
void go_first() noexcept
Position enumerator to the first available bit.
Definition: bm.h:8301
enumerator(const bvector< Alloc > *bv) noexcept
Construct enumerator associated with a vector. Important: This construction creates unpositioned iter...
Definition: bm.h:622
enumerator & operator++() noexcept
Advance enumerator forward to the next available bit.
Definition: bm.h:662
bool search_in_blocks() noexcept
Definition: bm.h:8495
bool search_in_gapblock() noexcept
Definition: bm.h:8456
bool go_to(size_type pos) noexcept
go to a specific position in the bit-vector (or next)
Definition: bm.h:8209
bool advance() noexcept
Definition: bm.h:680
enumerator(const bvector< Alloc > *bv, size_type pos) noexcept
Construct enumerator for bit vector.
Definition: bm.h:648
enumerator operator++(int) noexcept
Advance enumerator forward to the next available bit. Possibly do NOT use this operator it is slower ...
Definition: bm.h:667
size_type operator*() const noexcept
Get current position (value)
Definition: bm.h:656
bool search_in_bitblock() noexcept
Definition: bm.h:8444
bool skip_to_rank(size_type rank) noexcept
Skip to specified relative rank.
Definition: bm.h:690
bool decode_bit_group(block_descr_type *bdescr) noexcept
Definition: bm.h:8376
unsigned difference_type
Definition: bm.h:609
bool decode_bit_group(block_descr_type *bdescr, size_type &rank) noexcept
Definition: bm.h:8397
size_type value_type
Definition: bm.h:608
iterator_base::block_descr block_descr_type
Definition: bm.h:712
unsigned * pointer
Definition: bm.h:610
bool skip(size_type rank) noexcept
Skip specified number of bits from enumeration.
Definition: bm.h:8136
bool go_up() noexcept
Advance enumerator to the next available bit.
Definition: bm.h:8083
enumerator(const bvector< Alloc > &bv, size_type pos=0) noexcept
Construct enumerator for bit vector.
Definition: bm.h:634
enumerator() noexcept
Definition: bm.h:614
Output iterator iterator designed to set "ON" bits based on input sequence of integers (bit indeces).
Definition: bm.h:381
insert_iterator(const insert_iterator &iit)
Definition: bm.h:402
bvector_type * get_bvector() const
Definition: bm.h:438
insert_iterator & operator++(int)
Definition: bm.h:436
insert_iterator(bvector< Alloc > &bvect) noexcept
Definition: bm.h:395
insert_iterator & operator=(const insert_iterator &ii)
Definition: bm.h:408
bvector_type * bvect_
Definition: bm.h:441
friend class bulk_insert_iterator
Definition: bm.h:382
insert_iterator & operator++()
Definition: bm.h:434
insert_iterator() noexcept
Definition: bm.h:393
insert_iterator & operator*()
Definition: bm.h:432
bm::bvector< Alloc > bvector_type
Definition: bm.h:387
insert_iterator & operator=(size_type n)
Definition: bm.h:414
std::output_iterator_tag iterator_category
Definition: bm.h:385
size_type value_type
Definition: bm.h:388
Base class for all iterators.
Definition: bm.h:240
bool operator!=(const iterator_base &it) const noexcept
Definition: bm.h:253
bool operator<=(const iterator_base &it) const noexcept
Definition: bm.h:263
size_type position_
Bit position (bit idx)
Definition: bm.h:350
bool operator==(const iterator_base &it) const noexcept
Definition: bm.h:248
bool valid() const noexcept
Checks if iterator is still valid.
Definition: bm.h:283
iterator_base() noexcept
Definition: bm.h:243
unsigned block_type_
Type of block. 0-Bit, 1-GAP.
Definition: bm.h:352
union bm::bvector::iterator_base::block_descr bdescr_
bool operator<(const iterator_base &it) const noexcept
Definition: bm.h:258
bm::bvector< Alloc > * bv_
Pointer on parent bitvector.
Definition: bm.h:349
bool compare_state(const iterator_base &ib) const noexcept
Compare FSMs for testing purposes.
Definition: bm.h:295
const bm::word_t * block_
Block pointer.(NULL-invalid)
Definition: bm.h:351
bool operator>=(const iterator_base &it) const noexcept
Definition: bm.h:273
bool operator>(const iterator_base &it) const noexcept
Definition: bm.h:268
void invalidate() noexcept
Turns iterator into an invalid state.
Definition: bm.h:289
block_idx_type block_idx_
Block index.
Definition: bm.h:353
Class reference implements an object for bit assignment.
Definition: bm.h:149
reference & flip()
Definition: bm.h:222
bool operator!() const noexcept
Definition: bm.h:210
const reference & operator=(bool value) const noexcept
Definition: bm.h:174
reference(bvector< Alloc > &bv, size_type position) noexcept
Definition: bm.h:151
size_type position_
Position in the parent bitvector.
Definition: bm.h:230
const reference & operator|=(bool value) const
Definition: bm.h:193
const reference & operator=(const reference &ref) const
Definition: bm.h:168
reference(const reference &ref) noexcept
Definition: bm.h:156
bvector< Alloc > & bv_
Reference variable on the parent.
Definition: bm.h:229
bool operator==(const reference &ref) const noexcept
Definition: bm.h:180
const reference & operator&=(bool value) const
Definition: bm.h:186
const reference & operator^=(bool value) const
Definition: bm.h:203
bool operator~() const noexcept
Definition: bm.h:216
Bitvector Bit-vector container with runtime compression of bits.
Definition: bm.h:115
bm::bvector< Alloc > & bit_or(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode=opt_none)
3-operand OR : this := bv1 OR bv2
Definition: bm.h:5906
void import_block(const size_type *ids, block_idx_type nblock, size_type start, size_type stop)
Definition: bm.h:4363
bool const_reference
Definition: bm.h:233
bool test(size_type n) const noexcept
returns true if bit n is set and false is bit n is 0.
Definition: bm.h:1502
optmode
Optimization mode Every next level means additional checks (better compression vs time)
Definition: bm.h:133
@ opt_compress
compress blocks when possible (GAP/prefix sum)
Definition: bm.h:137
@ opt_free_01
Free unused 0 and 1 blocks.
Definition: bm.h:136
@ opt_free_0
Free unused 0 blocks.
Definition: bm.h:135
@ opt_none
no optimization
Definition: bm.h:134
bool select(size_type rank, size_type &pos, const rs_index_type &rs_idx) const noexcept
select bit-vector position for the specified rank(bitcount)
Definition: bm.h:5283
void swap(size_type idx1, size_type idx2)
swap values of bits
Definition: bm.h:4406
bvector(const bvector< Alloc > &bvect, bm::finalization is_final)
Copy-constructor for mutable/immutable initialization.
Definition: bm.h:892
~bvector() noexcept
Definition: bm.h:906
void operator&=(const bvector< Alloc > &bv)
Definition: bm.h:1020
bool find_rank(size_type rank, size_type from, size_type &pos, const rs_index_type &rs_idx) const noexcept
Find bit-vector position for the specified rank(bitcount)
Definition: bm.h:5212
size_type rank_corrected(size_type n, const rs_index_type &rs_idx) const noexcept
Returns rank corrceted by the requested border value (as -1)
Definition: bm.h:3197
void clear(bool free_mem=true) noexcept
Clears every bit in the bitvector.
Definition: bm.h:4135
bool combine_operation_block_and_or(unsigned i, unsigned j, const bm::word_t *arg_blk1, const bm::word_t *arg_blk2)
Definition: bm.h:7112
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:3726
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:843
bool get_bit(size_type n) const noexcept
returns true if bit n is set and false is bit n is 0.
Definition: bm.h:3602
strategy get_new_blocks_strat() const noexcept
Returns blocks allocation strategy.
Definition: bm.h:1920
void combine_operation_with_block(block_idx_type nb, bool gap, bm::word_t *blk, const bm::word_t *arg_blk, bool arg_gap, bm::operation opcode)
Definition: bm.h:7654
void merge(bm::bvector< Alloc > &bvect)
Merge/move content from another vector.
Definition: bm.h:5816
void clear_range_no_check(size_type left, size_type right)
Clear range without validity/bounds checking.
Definition: bm.h:7904
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:3550
void combine_operation_block_or(unsigned i, unsigned j, bm::word_t *blk, const bm::word_t *arg_blk)
Definition: bm.h:7286
bool set_bit_and(size_type n, bool val=true)
Sets bit n using bit AND with the provided value.
Definition: bm.h:4213
allocator_type::allocator_pool_type allocator_pool_type
Definition: bm.h:118
void init(unsigned top_size, bool alloc_subs)
Explicit post-construction initialization. Must be caled right after construction strickly before any...
Definition: bm.h:2289
void combine_operation_xor(const bm::bvector< Alloc > &bvect)
perform a set-algebra operation XOR
Definition: bm.h:6499
bool set_bit_conditional_impl(size_type n, bool val, bool condition)
Definition: bm.h:4784
bool clear_bit(size_type n)
Clears bit n.
Definition: bm.h:1247
bm::bvector< Alloc > & bit_and(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode=opt_none)
3-operand AND : this := bv1 AND bv2
Definition: bm.h:6118
static void throw_bad_alloc()
Definition: bm.h:8069
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:5443
bool combine_operation_block_or(unsigned i, unsigned j, const bm::word_t *arg_blk1, const bm::word_t *arg_blk2)
Definition: bm.h:6872
bvector & operator=(const bvector< Alloc > &bvect)
Copy assignment operator.
Definition: bm.h:930
size_type rank(size_type n, const rs_index_type &rs_idx) const noexcept
Returns rank of specified bit position (same as count_to())
Definition: bm.h:1433
bool any() const noexcept
Returns true if any bits in this bitset are set, and otherwise returns false.
Definition: bm.h:2451
size_type check_or_next(size_type prev) const noexcept
Definition: bm.h:5324
void keep_range_no_check(size_type left, size_type right)
Clear outside the range without validity/bounds checking.
Definition: bm.h:8004
void sync_size()
Syncronize size if it got extended due to bulk import.
Definition: bm.h:2486
bvector(bvector< Alloc > &&bvect) noexcept
Move constructor.
Definition: bm.h:940
bool test_first_block_bit(block_idx_type nb) const noexcept
Return value of first bit in the block.
Definition: bm.h:5805
bvector< Alloc > operator~() const
Definition: bm.h:1032
size_type check_or_next_extract(size_type prev)
check if specified bit is 1, and set it to 0 if specified bit is 0, scan for the next 1 and returns i...
Definition: bm.h:5408
bool find_rank(size_type rank, size_type from, size_type &pos) const noexcept
Find bit-vector position for the specified rank(bitcount)
Definition: bm.h:5159
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:4188
void resize(size_type new_size)
Change size of the bvector.
Definition: bm.h:2463
reference operator[](size_type n)
Definition: bm.h:1004
bm::bvector< Alloc > & bit_sub(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode=opt_none)
3-operand SUB : this := bv1 MINUS bv2 SUBtraction is also known as AND NOT
Definition: bm.h:6330
bool empty() const noexcept
Returns true if the set is empty (no bits are set, otherwise returns false) Please note that this is ...
Definition: bm.h:1562
bvector(const bvector< Alloc > &bvect)
Copy constructor.
Definition: bm.h:867
size_type size() const noexcept
Returns bvector's capacity (number of bits it can store)
Definition: bm.h:1300
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:3635
void set_new_blocks_strat(strategy strat)
Sets new blocks allocation strategy.
Definition: bm.h:1912
bool find_range(size_type &first, size_type &last) const noexcept
Finds dynamic range of bit-vector [first, last].
Definition: bm.h:5139
bvector(std::initializer_list< size_type > il)
Brace constructor.
Definition: bm.h:950
void swap(bvector< Alloc > &bvect) noexcept
Exchanges content of bv and this bvector.
Definition: bm.h:3966
void fill_alloc_digest(bvector< Alloc > &bv_blocks) const
Calculate blocks digest vector (for diagnostics purposes) 1 is added if NB is a real,...
Definition: bm.h:4058
size_type count_range(size_type left, size_type right, const rs_index_type &rs_idx) const noexcept
Returns count of 1 bits in the given range [left..right] Uses rank-select index to accelerate the sea...
Definition: bm.h:3516
bool set_bit(size_type n, bool val=true)
Sets bit n.
Definition: bm.h:4227
bool find(size_type from, size_type &pos) const noexcept
Find index of 1 bit starting from position.
Definition: bm.h:4896
insert_iterator inserter()
Definition: bm.h:1287
blocks_manager< Alloc > blocks_manager_type
Definition: bm.h:119
friend class enumerator
Definition: bm.h:793
bool find(size_type &pos) const noexcept
Finds index of first 1 bit.
Definition: bm.h:5093
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:2353
void combine_operation_block_sub(unsigned i, unsigned j, bm::word_t *blk, const bm::word_t *arg_blk)
Definition: bm.h:7573
bool find_first_mismatch(const bvector< Alloc > &bvect, size_type &pos, size_type search_to=bm::id_max) const noexcept
Find index of first bit different between this and the agr vector.
Definition: bm.h:3862
void operator-=(const bvector< Alloc > &bv)
Definition: bm.h:1023
static size_type block_count_to(const bm::word_t *block, block_idx_type nb, unsigned nbit_right, const rs_index_type &rs_idx) noexcept
Compute rank in bit-block using rank-select index.
Definition: bm.h:2846
Alloc get_allocator() const
Definition: bm.h:1034
bool and_bit_no_check(size_type n, bool val)
AND specified bit without checking preconditions (size, etc)
Definition: bm.h:4836
bvector_size_type size_type
Definition: bm.h:121
bvector< Alloc > & flip(size_type n)
Flips bit n.
Definition: bm.h:1273
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:1216
bool combine_operation_block_and(unsigned i, unsigned j, const bm::word_t *arg_blk1, const bm::word_t *arg_blk2)
Definition: bm.h:7027
void combine_operation_and(const bm::bvector< Alloc > &bvect, optmode opt_mode)
perform a set-algebra operation AND
Definition: bm.h:6598
enumerator first() const
Returns enumerator pointing on the first non-zero bit.
Definition: bm.h:1871
bool is_ro() const noexcept
Returns true if vector is read-only.
Definition: bm.h:1060
bool combine_operation_block_sub(unsigned i, unsigned j, const bm::word_t *arg_blk1, const bm::word_t *arg_blk2)
Definition: bm.h:7212
bool find_reverse(size_type &pos) const noexcept
Finds last index of 1 bit.
Definition: bm.h:4911
strategy new_blocks_strat_
block allocation strategy
Definition: bm.h:2227
bool find_reverse(size_type from, size_type &pos) const noexcept
Reverse finds next(prev) index of 1 bit.
Definition: bm.h:4968
bool combine_operation_block_xor(unsigned i, unsigned j, const bm::word_t *arg_blk1, const bm::word_t *arg_blk2)
Definition: bm.h:6945
enumerator end() const
Returns enumerator pointing on the next bit after the last.
Definition: bm.h:1877
bvector< Alloc > & set()
Sets every bit in this bitset to 1.
Definition: bm.h:4177
bool shift_left()
Shift left by 1 bit, fill with zero return carry out.
Definition: bm.h:5432
bm::bvector< Alloc > & bit_and(const bm::bvector< Alloc > &bv, optmode opt_mode=opt_none)
2 operand logical AND
Definition: bm.h:1802
void freeze()
Turn current vector to read-only (immutable vector).
Definition: bm.h:8058
bvector< Alloc > & reset() noexcept
Clears every bit in the bitvector.
Definition: bm.h:1267
const blocks_manager_type & get_blocks_manager() const noexcept
get access to memory manager (internal) Use only if you are BitMagic library
Definition: bm.h:2058
size_type count_range_no_check(size_type left, size_type right) const noexcept
Definition: bm.h:3258
blocks_manager_type & get_blocks_manager() noexcept
get access to memory manager (internal) Use only if you are BitMagic library
Definition: bm.h:2066
void combine_operation_block_xor(unsigned i, unsigned j, bm::word_t *blk, const bm::word_t *arg_blk)
Definition: bm.h:7365
size_type recalc_count() noexcept
Definition: bm.h:1477
void optimize_gap_size()
Optimize sizes of GAP blocks.
Definition: bm.h:3700
bool set_bit_no_check(size_type n, bool val)
Set specified bit without checking preconditions (size, etc)
Definition: bm.h:4597
void init()
Explicit post-construction initialization. Must be caled to make sure safe use of *_no_check() method...
Definition: bm.h:2280
bool shift_right()
Shift right by 1 bit, fill with zero return carry out.
Definition: bm.h:5423
block_idx_type count_blocks(unsigned *arr) const noexcept
Computes bitcount values for all bvector blocks.
Definition: bm.h:2637
bvector< Alloc > & flip()
Flips all bits.
Definition: bm.h:1280
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:2368
void set_allocator_pool(allocator_pool_type *pool_ptr) noexcept
Set allocator pool for local (non-th readed) memory cyclic(lots of alloc-free ops) opertations.
Definition: bm.h:1040
void erase(size_type n)
Erase bit in the specified position All the vector content after erase position is shifted left.
Definition: bm.h:5646
bvector & operator=(bvector< Alloc > &&bvect) noexcept
Move assignment operator.
Definition: bm.h:965
void set(const size_type *ids, size_type ids_size, bm::sort_order so=bm::BM_UNKNOWN)
Set list of bits in this bitset to 1.
Definition: bm.h:4088
static size_type gap_count_to(const bm::gap_word_t *gap_block, block_idx_type nb, unsigned nbit_right, const rs_index_type &rs_idx, bool test_set=false) noexcept
Compute rank in GAP block using rank-select index.
Definition: bm.h:2952
size_type extract_next(size_type prev)
Finds the number of the next bit ON and sets it to 0.
Definition: bm.h:1619
size_type get_next(size_type prev) const noexcept
Finds the number of the next bit ON.
Definition: bm.h:1609
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:7981
enumerator get_enumerator(size_type pos) const
Returns enumerator pointing on specified or the next available bit.
Definition: bm.h:1883
void import(const size_type *ids, size_type ids_size, bm::sort_order sorted_idx)
Import integers (set bits).
Definition: bm.h:4245
void copy_range_no_check(const bvector< Alloc > &bvect, size_type left, size_type right)
Definition: bm.h:8026
void combine_operation_or(const bm::bvector< Alloc > &bvect)
perform a set-algebra operation OR
Definition: bm.h:6427
blocks_manager_type::block_idx_type block_idx_type
Definition: bm.h:120
void copy(const bvector< Alloc > &bvect, bm::finalization is_final)
Copy bvector from the argument bvector.
Definition: bm.h:2303
void combine_operation_block_and(unsigned i, unsigned j, bm::word_t *blk, const bm::word_t *arg_blk)
Definition: bm.h:7469
void operator^=(const bvector< Alloc > &bv)
Definition: bm.h:1021
void operator|=(const bvector< Alloc > &bv)
Definition: bm.h:1022
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:4149
void import_sorted(const size_type *ids, const size_type ids_size, bool opt_flag)
Import sorted integers (set bits).
Definition: bm.h:4297
bool equal(const bvector< Alloc > &bvect) const noexcept
Equal comparison with an agr bit-vector.
Definition: bm.h:2017
void optimize_range(size_type left, size_type right, bm::word_t *temp_block, optmode opt_mode=opt_compress)
Definition: bm.h:3671
rs_index< allocator_type > rs_index_type
Definition: bm.h:816
bvector(const bvector< Alloc > &bvect, size_type left, size_type right)
Copy constructor for range copy [left..right].
Definition: bm.h:877
void combine_operation_sub(const bm::bvector< Alloc > &bvect)
perform a set-algebra operation MINUS (AND NOT)
Definition: bm.h:6686
Alloc allocator_type
Definition: bm.h:117
void calc_stat(struct bm::bvector< Alloc >::statistics *st) const noexcept
Calculates bitvector statistics.
Definition: bm.h:3978
size_type get_first() const noexcept
find first 1 bit in vector. Function may return 0 and this requires an extra check if bit 0 is actual...
Definition: bm.h:1600
rs_index< allocator_type > blocks_count
Definition: bm.h:815
size_type count_to_test(size_type n, const rs_index_type &rs_idx) const noexcept
popcount in [0..right] range if test(right) == true
Definition: bm.h:3141
bool set_bit_conditional(size_type n, bool val, bool condition)
Sets bit n only if current value equals the condition.
Definition: bm.h:4199
void move_from(bvector< Alloc > &bvect) noexcept
Move bvector content from another bvector.
Definition: bm.h:2340
bool is_init() const noexcept
Return true if bvector is initialized at all.
Definition: bm.h:1983
int compare(const bvector< Alloc > &bvect) const noexcept
Lexicographical comparison with a bitvector.
Definition: bm.h:3744
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:2501
bool any_range(size_type left, size_type right) const noexcept
Returns true if any bits in the range are 1s (non-empty interval) Function uses closed interval [left...
Definition: bm.h:3422
void combine_operation_with_block(block_idx_type nb, const bm::word_t *arg_blk, bool arg_gap, bm::operation opcode)
Definition: bm.h:5889
bm::bvector< Alloc > & bit_xor(const bm::bvector< Alloc > &bv)
2 operand logical XOR
Definition: bm.h:1814
void clear_bit_no_check(size_type n)
Clears bit n without precondiion checks.
Definition: bm.h:4680
bool operator[](size_type n) const noexcept
Definition: bm.h:1014
void gap_block_set_no_ret(bm::gap_word_t *gap_blk, bool val, block_idx_type nblock, unsigned nbit)
set bit in GAP block with GAP block length control
Definition: bm.h:4733
bool none() const noexcept
Returns true if no bits are set, otherwise returns false.
Definition: bm.h:1556
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:855
void combine_operation(const bm::bvector< Alloc > &bvect, bm::operation opcode)
perform a set-algebra operation by operation code
Definition: bm.h:6750
size_type count() const noexcept
population count (count of ON bits)
Definition: bm.h:2401
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:4105
bm::bvector< Alloc > & bit_or_and(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode=opt_none)
3-operand AND where result is ORed into the terget vector : this |= bv1 AND bv2 TARGET := TARGET OR (...
Definition: bm.h:6213
size_type size_
size in bits
Definition: bm.h:2228
blocks_manager_type blockman_
bitblocks manager
Definition: bm.h:2226
bm::bvector< Alloc > & bit_sub(const bm::bvector< Alloc > &bv)
2 operand logical SUB(AND NOT). Also known as MINUS.
Definition: bm.h:1825
bm::bvector< Alloc > & bit_or(const bm::bvector< Alloc > &bv)
2 operand logical OR
Definition: bm.h:1790
void forget_count() noexcept
Definition: bm.h:1482
bool gap_block_set(bm::gap_word_t *gap_blk, bool val, block_idx_type nblock, unsigned nbit)
set bit in GAP block with GAP block length control
Definition: bm.h:4714
bm::bvector< Alloc > & bit_xor(const bm::bvector< Alloc > &bv1, const bm::bvector< Alloc > &bv2, typename bm::bvector< Alloc >::optmode opt_mode=opt_none)
3-operand XOR : this := bv1 XOR bv2
Definition: bm.h:6005
void set_range_no_check(size_type left, size_type right)
Set range without validity/bounds checking.
Definition: bm.h:7830
allocator_pool_type * get_allocator_pool() noexcept
Get curent allocator pool (if set)
Definition: bm.h:1045
bool is_all_one_range(size_type left, size_type right) const noexcept
Returns true if all bits in the range are 1s (saturated interval) Function uses closed interval [left...
Definition: bm.h:3338
bool inc(size_type n)
Increment the specified element.
Definition: bm.h:4751
void set_bit_no_check(size_type n)
Set bit without checking preconditions (size, etc)
Definition: bm.h:4646
size_type count_to(size_type n, const rs_index_type &rs_idx) const noexcept
Returns count of 1 bits (population) in [0..right] range.
Definition: bm.h:3088
Deserializer for bit-vector.
Definition: bmserial.h:570
Deserializer, performs logical operations between bit-vector and serialized bit-vector.
Definition: bmserial.h:927
Rank-Select acceleration index.
Definition: bmrs.h:41
void init() BMNOEXCEPT
init arrays to zeros
Definition: bmrs.h:283
void resize(block_idx_type new_size)
reserve the capacity for block count
Definition: bmrs.h:296
void resize_effective_super_blocks(size_type sb_eff)
set size of true super-blocks (not NULL and not FFFFF)
Definition: bmrs.h:679
void set_full_super_block(unsigned i) BMNOEXCEPT
set FULL (all bits set super-block)
Definition: bmrs.h:597
void set_null_super_block(unsigned i) BMNOEXCEPT
set empty (no bits set super-block)
Definition: bmrs.h:586
void set_total(size_type t)
set total blocks
Definition: bmrs.h:113
void register_super_block(unsigned i, const unsigned *bcount, const bm::id64_t *sub_count)
Add block list belonging to one super block.
Definition: bmrs.h:688
Encoding utilities for serialization (internal)
#define true
Definition: bool.h:35
#define bool
Definition: bool.h:34
static DLIST_TYPE *DLIST_NAME() last(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:51
static DLIST_TYPE *DLIST_NAME() prev(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:61
static char tmp[3200]
Definition: utf8.c:42
bool avx2_test_all_zero_wave2(const void *ptr0, const void *ptr1)
check if 2 wave of pointers are all NULL
Definition: bmavx2.h:1816
bool avx2_test_all_eq_wave2(const void *ptr0, const void *ptr1)
check if 2 wave of pointers are all the same (NULL or FULL)
Definition: bmavx2.h:1829
bool avx2_test_all_zero_wave(const void *ptr)
check if wave of pointers is all NULL
Definition: bmavx2.h:1805
bool sse42_test_all_zero_wave(const void *ptr) noexcept
check if wave of pointers is all NULL
Definition: bmsse4.h:910
bool sse42_test_all_zero_wave2(const void *ptr0, const void *ptr1) noexcept
check if 2 waves of pointers are all NULL
Definition: bmsse4.h:921
bool sse42_test_all_eq_wave2(const void *ptr0, const void *ptr1) noexcept
check if wave of 2 pointers are the same (null or FULL)
Definition: bmsse4.h:934
unsigned bit_find_last(const bm::word_t *block, unsigned *last) noexcept
BIT block find the last set bit (backward search)
Definition: bmfunc.h:8708
bool bit_find_first(const bm::word_t *block, unsigned *pos) noexcept
BIT block find the first set bit.
Definition: bmfunc.h:8742
bm::word_t * bit_operation_sub(bm::word_t *dst, const bm::word_t *src) noexcept
bitblock SUB operation.
Definition: bmfunc.h:8376
unsigned word_bitcount64(bm::id64_t x) noexcept
Definition: bmutil.h:605
bm::id64_t bit_block_xor(bm::word_t *dst, const bm::word_t *src) noexcept
Plain bitblock XOR operation. Function does not analyse availability of source and destination blocks...
Definition: bmfunc.h:8434
bm::id_t word_bitcount(bm::id_t w) noexcept
Definition: bmutil.h:582
void bit_invert(T *start) noexcept
Definition: bmfunc.h:6057
bool bit_block_or(bm::word_t *dst, const bm::word_t *src) noexcept
Plain bitblock OR operation. Function does not analyse availability of source and destination blocks.
Definition: bmfunc.h:7835
bm::id64_t bit_block_and(bm::word_t *dst, const bm::word_t *src) noexcept
Plain bitblock AND operation. Function does not analyse availability of source and destination blocks...
Definition: bmfunc.h:6858
void bit_andnot_arr_ffmask(bm::word_t *dst, const bm::word_t *src) noexcept
bitblock AND NOT with constant ~0 mask operation.
Definition: bmfunc.h:8470
bool bit_block_or_2way(bm::word_t *dst, const bm::word_t *src1, const bm::word_t *src2) noexcept
2 way (target := source1 | source2) bitblock OR operation.
Definition: bmfunc.h:7872
unsigned bit_block_find(const bm::word_t *block, unsigned nbit, unsigned *pos) noexcept
Searches for the next 1 bit in the BIT block.
Definition: bmfunc.h:8657
bool is_bits_one(const bm::wordop_t *start) noexcept
Returns "true" if all bits in the block are 1.
Definition: bmfunc.h:6081
bm::id_t bit_block_calc_count_range(const bm::word_t *block, bm::word_t left, bm::word_t right) noexcept
Definition: bmfunc.h:5390
unsigned short bitscan_wave(const bm::word_t *w_ptr, unsigned char *bits) noexcept
Unpacks word wave (Nx 32-bit words)
Definition: bmfunc.h:9635
bm::id64_t bit_block_and_or_2way(bm::word_t *dst, const bm::word_t *src1, const bm::word_t *src2, bm::id64_t digest) noexcept
digest based bit-block AND - OR
Definition: bmfunc.h:7210
bool bit_is_all_zero(const bm::word_t *start) noexcept
Returns "true" if all bits in the block are 0.
Definition: bmfunc.h:1550
bool bit_block_shift_r1_unr(bm::word_t *block, bm::word_t *empty_acc, bm::word_t co_flag) noexcept
Right bit-shift of bit-block by 1 bit (loop unrolled)
Definition: bmfunc.h:5711
void bit_block_set(bm::word_t *dst, bm::word_t value) noexcept
Bitblock memset operation.
Definition: bmfunc.h:4456
bm::id_t bit_block_calc_count_to(const bm::word_t *block, bm::word_t right) noexcept
Definition: bmfunc.h:5476
void bit_block_copy(bm::word_t *dst, const bm::word_t *src) noexcept
Bitblock copy operation.
Definition: bmfunc.h:6777
bm::id64_t bit_block_and_2way(bm::word_t *dst, const bm::word_t *src1, const bm::word_t *src2, bm::id64_t digest) noexcept
digest based bit-block AND
Definition: bmfunc.h:7076
bool bit_block_shift_l1_unr(bm::word_t *block, bm::word_t *empty_acc, bm::word_t co_flag) noexcept
Left bit-shift of bit-block by 1 bit (loop unrolled)
Definition: bmfunc.h:5811
bm::word_t bit_block_insert(bm::word_t *block, unsigned bitpos, bool value) noexcept
insert bit into position and shift the rest right with carryover
Definition: bmfunc.h:5585
bm::word_t * bit_operation_xor(bm::word_t *dst, const bm::word_t *src) noexcept
bitblock XOR operation.
Definition: bmfunc.h:8505
void bit_block_erase(bm::word_t *block, unsigned bitpos, bool carry_over) noexcept
erase bit from position and shift the rest right with carryover
Definition: bmfunc.h:5834
bm::word_t * bit_operation_and(bm::word_t *dst, const bm::word_t *src) noexcept
bitblock AND operation.
Definition: bmfunc.h:7578
int bitcmp(const T *buf1, const T *buf2, unsigned len) noexcept
Lexicographical comparison of BIT buffers.
Definition: bmfunc.h:4700
bm::id64_t bit_block_sub_2way(bm::word_t *dst, const bm::word_t *src1, const bm::word_t *src2, bm::id64_t digest) noexcept
digest based bitblock SUB (AND NOT) operation (3 operand)
Definition: bmfunc.h:8201
bm::word_t * bit_operation_or(bm::word_t *dst, const bm::word_t *src) noexcept
Block OR operation. Makes analysis if block is 0 or FULL.
Definition: bmfunc.h:8045
bm::id64_t calc_block_digest0(const bm::word_t *const block) noexcept
Compute digest for 64 non-zero areas.
Definition: bmfunc.h:1120
bm::id64_t bit_block_xor_2way(bm::word_t *dst, const bm::word_t *src1, const bm::word_t *src2) noexcept
2 way (target := source1 ^ source2) bitblock XOR operation.
Definition: bmfunc.h:7911
bm::id64_t bit_block_sub(bm::word_t *dst, const bm::word_t *src) noexcept
Plain bitblock SUB (AND NOT) operation. Function does not analyse availability of source and destinat...
Definition: bmfunc.h:8105
sort_order
Sort order declaration.
Definition: bmconst.h:204
bm::alloc_pool_guard< allocator_pool_type, bvector< Alloc > > mem_pool_guard
Definition: bm.h:790
operation
Bit operations.
Definition: bmconst.h:191
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:72
finalization
copy strategy
Definition: bmconst.h:156
strategy
Block allocation strategies.
Definition: bmconst.h:146
@ BM_SORTED
input set is sorted (ascending order)
Definition: bmconst.h:206
@ BM_UNKNOWN
sort order unknown
Definition: bmconst.h:208
@ BM_OR
Definition: bmconst.h:193
@ BM_SUB
Definition: bmconst.h:194
@ BM_XOR
Definition: bmconst.h:195
@ BM_AND
Definition: bmconst.h:192
@ READWRITE
mutable (read-write object)
@ READONLY
immutable (read-only object)
@ BM_BIT
No GAP compression strategy. All new blocks are bit blocks.
Definition: bmconst.h:147
@ BM_GAP
GAP compression is ON.
Definition: bmconst.h:148
unsigned gap_bit_count_range(const T *const buf, unsigned left, unsigned right) noexcept
Counts 1 bits in GAP buffer in the closed [left, right] range.
Definition: bmfunc.h:2393
unsigned gap_limit(const T *buf, const T *glevel_len) noexcept
Returs GAP block capacity limit.
Definition: bmfunc.h:1635
gap_word_t * gap_operation_xor(const gap_word_t *vect1, const gap_word_t *vect2, gap_word_t *tmp_buf, unsigned &dsize) noexcept
GAP XOR operation.
Definition: bmfunc.h:6585
bool gap_shift_r1(T *buf, unsigned co_flag, unsigned *new_len) noexcept
Right shift GAP block by 1 bit.
Definition: bmfunc.h:3431
void gap_invert(T *buf) noexcept
Inverts all bits in the GAP buffer.
Definition: bmfunc.h:4620
void gap_add_to_bitset(unsigned *dest, const T *pcurr, unsigned len) noexcept
Adds(OR) GAP block to bitblock.
Definition: bmfunc.h:4039
gap_word_t * gap_operation_or(const gap_word_t *vect1, const gap_word_t *vect2, gap_word_t *tmp_buf, unsigned &dsize) noexcept
GAP OR operation.
Definition: bmfunc.h:6666
bool improve_gap_levels(const T *length, const T *length_end, T *glevel_len) noexcept
Finds optimal gap blocks lengths.
Definition: bmfunc.h:9170
unsigned gap_test_unr(const T *buf, const unsigned pos) noexcept
Tests if bit = pos is true. Analog of bm::gap_test with SIMD unrolling.
Definition: bmfunc.h:1833
bool gap_is_all_zero(const bm::gap_word_t *buf) noexcept
Checks if GAP block is all-zero.
Definition: bmfunc.h:1577
void gap_convert_to_bitset(unsigned *dest, const T *buf, unsigned len=0) noexcept
GAP block to bitblock conversion.
Definition: bmfunc.h:4475
gap_word_t * gap_operation_sub(const gap_word_t *vect1, const gap_word_t *vect2, gap_word_t *tmp_buf, unsigned &dsize) noexcept
GAP SUB (AND NOT) operation.
Definition: bmfunc.h:6712
void gap_xor_to_bitset(unsigned *dest, const T *pcurr) noexcept
XOR GAP block to bitblock.
Definition: bmfunc.h:4011
unsigned gap_set_value_cpos(unsigned val, T *buf, unsigned pos, unsigned *is_set, unsigned curr) noexcept
Sets or clears bit in the GAP buffer.
Definition: bmfunc.h:3168
gap_word_t * gap_operation_and(const gap_word_t *vect1, const gap_word_t *vect2, gap_word_t *tmp_buf, unsigned &dsize) noexcept
GAP AND operation.
Definition: bmfunc.h:6518
unsigned gap_find_first(const T *buf, unsigned *first) noexcept
GAP block find the first set bit.
Definition: bmfunc.h:1698
unsigned gap_find_last(const T *buf, unsigned *last) noexcept
GAP block find the last set bit.
Definition: bmfunc.h:1667
unsigned gap_capacity(const T *buf, const T *glevel_len) noexcept
Returs GAP block capacity.
Definition: bmfunc.h:1619
T gap_level(const T *buf) noexcept
Returs GAP blocks capacity level.
Definition: bmfunc.h:1649
unsigned gap_block_find(const T *buf, unsigned nbit, bm::id_t *prev) noexcept
Searches for the next 1 bit in the GAP block.
Definition: bmfunc.h:3694
unsigned gap_set_value(unsigned val, T *buf, unsigned pos, unsigned *is_set) noexcept
Sets or clears bit in the GAP buffer.
Definition: bmfunc.h:3254
bool gap_shift_l1(T *buf, unsigned co_flag, unsigned *new_len) noexcept
Left shift GAP block by 1 bit.
Definition: bmfunc.h:3540
void gap_and_to_bitset(unsigned *dest, const T *pcurr) noexcept
ANDs GAP block to bitblock.
Definition: bmfunc.h:4090
int gapcmp(const T *buf1, const T *buf2) noexcept
Lexicographical comparison of GAP buffers.
Definition: bmfunc.h:2848
unsigned gap_bit_count_range_hint(const T *const buf, unsigned left, unsigned right, unsigned hint) noexcept
Counts 1 bits in GAP buffer in the closed [left, right] range using position hint to avoid bfind.
Definition: bmfunc.h:2441
bm::gap_word_t gap_length(const bm::gap_word_t *buf) noexcept
Returs GAP block length.
Definition: bmfunc.h:1603
void gap_sub_to_bitset(unsigned *dest, const T *pcurr) noexcept
SUB (AND NOT) GAP block to bitblock.
Definition: bmfunc.h:3912
unsigned * gap_convert_to_bitset_smart(unsigned *dest, const T *buf, id_t set_max) noexcept
Smart GAP block to bitblock conversion.
Definition: bmfunc.h:4500
bool gap_insert(T *buf, unsigned pos, unsigned val, unsigned *new_len) noexcept
isnert bit into GAP compressed block
Definition: bmfunc.h:3484
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
int i
if(yy_accept[yy_current_state])
yy_size_t n
int len
#include<zmmintrin.h>
Definition: bm.h:78
const unsigned set_array_mask
Definition: bmconst.h:97
void for_each_nzblock(T ***root, unsigned size1, F &f)
Definition: bmfunc.h:1908
SIZE_TYPE block_find_rank(const bm::word_t *const block, SIZE_TYPE rank, unsigned nbit_from, unsigned &nbit_pos) noexcept
Find rank in block (GAP or BIT)
Definition: bmfunc.h:8997
const unsigned id_max
Definition: bmconst.h:109
void xor_swap(W &x, W &y) noexcept
XOR swap two variables.
Definition: bmutil.h:534
unsigned int word_t
Definition: bmconst.h:39
bool block_find_reverse(const bm::word_t *block, unsigned nbit_from, unsigned *found_nbit) noexcept
Reverse find 1.
Definition: bmfunc.h:6431
const unsigned set_block_mask
Definition: bmconst.h:57
bool find_not_null_ptr(const bm::word_t *const *const *arr, N start, N size, N *pos) noexcept
Definition: bmfunc.h:1427
unsigned gap_bit_count_to(const T *const buf, T right) noexcept
Definition: bmfunc.h:2696
bool block_any(const bm::word_t *const block) noexcept
Returns "true" if one bit is set in the block Function check for block varieties.
Definition: bmfunc.h:6482
bvector< Alloc > operator-(const bvector< Alloc > &bv1, const bvector< Alloc > &bv2)
Definition: bm.h:2268
const unsigned set_sub_array_size
Definition: bmconst.h:95
void get_block_coord(BI_TYPE nb, unsigned &i, unsigned &j) noexcept
Recalc linear bvector block index into 2D matrix coordinates.
Definition: bmfunc.h:180
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) noexcept
block boundaries look ahead U32
Definition: bmfunc.h:9755
const unsigned bits_in_array
Definition: bmconst.h:115
const unsigned set_total_blocks
Definition: bmconst.h:111
void for_each_nzblock_range(T ***root, N top_size, N nb_from, N nb_to, F &f) noexcept
Definition: bmfunc.h:1851
bool block_is_all_one_range(const bm::word_t *const block, unsigned left, unsigned right) noexcept
Returns "true" if all bits are 1 in the block [left, right] Function check for block varieties.
Definition: bmfunc.h:6107
bool check_block_one(const bm::word_t *blk, bool deep_scan) noexcept
Checks if block has only 1 bits.
Definition: bmfunc.h:9120
const unsigned set_block_size_op
Definition: bmconst.h:137
word_t wordop_t
Definition: bmconst.h:135
const unsigned rs3_half_span
Definition: bmconst.h:121
unsigned idx_arr_block_lookup_u32(const unsigned *idx, unsigned size, unsigned nb, unsigned start) noexcept
block boundaries look ahead U32
Definition: bmfunc.h:9781
const unsigned gap_levels
Definition: bmconst.h:85
gap_word_t *(* gap_operation_func_type)(const gap_word_t *, const gap_word_t *, gap_word_t *, unsigned &)
Definition: bmfunc.h:9541
const unsigned set_word_shift
Definition: bmconst.h:72
unsigned char get_nibble(const unsigned char *arr, unsigned idx) noexcept
get nibble from the array
Definition: bmfunc.h:10280
bool for_each_nzblock_if(T ***root, BI size1, F &f) noexcept
Definition: bmfunc.h:2139
const unsigned set_block_size
Definition: bmconst.h:55
unsigned long long int id64_t
Definition: bmconst.h:35
const unsigned gap_equiv_len
Definition: bmconst.h:82
unsigned gap_bfind(const T *buf, unsigned pos, unsigned *is_set) noexcept
Definition: bmfunc.h:1725
const unsigned rs3_border0_1
Definition: bmconst.h:122
unsigned int id_t
Definition: bmconst.h:38
bvector< Alloc > operator|(const bvector< Alloc > &bv1, const bvector< Alloc > &bv2)
Definition: bm.h:2246
bool block_find_first_diff(const bm::word_t *blk, const bm::word_t *arg_blk, unsigned *pos) noexcept
Find first bit which is different between two blocks (GAP or bit)
Definition: bmfunc.h:9268
const unsigned rs3_border1
Definition: bmconst.h:120
bvector< Alloc > operator^(const bvector< Alloc > &bv1, const bvector< Alloc > &bv2)
Definition: bm.h:2257
const unsigned short set_bitscan_wave_size
Size of bit decode wave in words.
Definition: bmfunc.h:9623
const unsigned set_array_shift
Definition: bmconst.h:96
unsigned short gap_word_t
Definition: bmconst.h:78
const unsigned rs3_border1_1
Definition: bmconst.h:123
void(* gap_operation_to_bitset_func_type)(unsigned *, const gap_word_t *)
Definition: bmfunc.h:9537
bm::id_t bvector_size_type
Definition: bm.h:103
const unsigned rs3_border0
Definition: bmconst.h:119
const unsigned gap_max_bits
Definition: bmconst.h:81
const unsigned set_top_array_size
Definition: bmconst.h:110
void set_block_bits_u64(bm::word_t *block, const bm::id64_t *idx, bm::id64_t start, bm::id64_t stop) noexcept
set bits in a bit-block using global index
Definition: bmfunc.h:9814
const word_t all_bits_mask
Definition: bmconst.h:136
const unsigned set_block_shift
Definition: bmconst.h:56
void set_block_bits_u32(bm::word_t *block, const unsigned *idx, unsigned start, unsigned stop) noexcept
set bits in a bit-block using global index
Definition: bmfunc.h:9844
const unsigned set_word_mask
Definition: bmconst.h:73
const unsigned bits_in_block
Definition: bmconst.h:114
bool block_any_range(const bm::word_t *const block, unsigned left, unsigned right) noexcept
Returns "true" if one bit is set in the block [left, right] Function check for block varieties.
Definition: bmfunc.h:6461
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
double f(double x_, const double &y_)
Definition: njn_root.hpp:188
static unsigned cnt[256]
Allocation arena for ReadOnly vectors.
Definition: bmblocks.h:61
Structure with statistical information about memory allocation footprint, serialization projection,...
Definition: bmfunc.h:56
void reset() noexcept
Reset statisctics.
Definition: bmfunc.h:94
gap_word_t gap_levels[bm::gap_levels]
GAP block lengths in the bvect.
Definition: bmfunc.h:64
size_t max_serialize_mem
estimated maximum memory for serialization
Definition: bmfunc.h:61
size_t memory_used
memory usage for all blocks and service tables
Definition: bmfunc.h:62
memory allocation policy
Definition: bm.h:805
allocation_policy(bm::strategy s=BM_BIT, const gap_word_t *glevels=bm::gap_len_table< true >::_len) noexcept
Definition: bm.h:809
bm::strategy strat
Definition: bm.h:806
const gap_word_t * glevel_len
Definition: bm.h:807
unsigned short idx
Current position in the bit list.
Definition: bm.h:334
unsigned char bits[set_bitscan_wave_size *32]
bit list
Definition: bm.h:333
size_type pos
Last bit position decode before.
Definition: bm.h:336
unsigned short cnt
Number of ON bits.
Definition: bm.h:335
const bm::word_t * ptr
Word pointer.
Definition: bm.h:332
Information about current DGAP block.
Definition: bm.h:343
const gap_word_t * ptr
Word pointer.
Definition: bm.h:344
gap_word_t gap_len
Current dgap length.
Definition: bm.h:345
Statistical information about bitset's memory allocation details.
Definition: bm.h:125
Default GAP lengths table.
Definition: bmconst.h:396
static gap_operation_to_bitset_func_type gap_op_to_bit(unsigned i)
Definition: bmfunc.h:9562
static gap_operation_func_type gap_operation(unsigned i)
Definition: bmfunc.h:9568
Precalculated decision table fdr interval selection.
Definition: bmrs.h:162
dgap_descr gap_
DGAP block related info.
Definition: bm.h:359
bitblock_descr bit_
BitBlock related info.
Definition: bm.h:358
#define const
Definition: zconf.h:232
static void copy_block(deflate_state *s, uint8_t *buf, unsigned len, int header)
Definition: trees.c:1205
Modified on Thu Apr 25 08:17:43 2024 by modify_doxy.py rev. 669887