BitMagic-C++: bm.h Source File

BitMagic-C++

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