BitMagic-C++
bmsparsevec.h
Go to the documentation of this file.
1#ifndef BMSPARSEVEC_H__INCLUDED__
2#define BMSPARSEVEC_H__INCLUDED__
3/*
4Copyright(c) 2002-2017 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12Unless required by applicable law or agreed to in writing, software
13distributed under the License is distributed on an "AS IS" BASIS,
14WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15See the License for the specific language governing permissions and
16limitations under the License.
17
18For more information please visit: http://bitmagic.io
19*/
20
21/*! \file bmsparsevec.h
22 \brief Sparse constainer sparse_vector<> for integer types using
23 bit-transposition transform
24*/
25
26#include <memory.h>
27
28#ifndef BM_NO_STL
29#include <stdexcept>
30#include <limits>
31#endif
32
33#ifndef BM__H__INCLUDED__
34// BitMagic utility headers do not include main "bm.h" declaration
35// #include "bm.h" or "bm64.h" explicitly
36# error missing include (bm.h or bm64.h)
37#endif
38
39
40#include "bmtrans.h"
41#include "bmalgo_impl.h"
42#include "bmbuffer.h"
43#include "bmbmatrix.h"
44#include "bmdef.h"
45
46namespace bm
47{
48
49/** \defgroup svector Sparse and compressed vectors
50 Sparse vector for integer types using bit transposition transform
51
52 @ingroup bmagic
53 */
54
55
56/** \defgroup sv bit-sliced (bitwise transposition) succinct sparse vectors
57 Sparse vector for integer types using bit transposition transform
58
59 @ingroup bmagic
60 */
61
62
63/*!
64 \brief succinct sparse vector with runtime compression using bit-slicing / transposition method
65
66 Sparse vector implements variable bit-depth storage model.
67 Initial data is bit-sliced into bit-vectors (all bits 0 become bv[0] so each element
68 may use less memory than the original native data type.
69 For example, 32-bit integer may only use 20 bits.
70
71 Container supports both signed and unsigned integer types.
72
73 Another level of compression is provided by bit-vector (BV template parameter)
74 used for storing bit planes. bvector<> implements varians of on the fly block
75 compression, so if a significant area of a sparse vector uses less bits - it
76 will save memory.
77 bm::bvector<> is a sparse data strucrture, so is bm::sparse_vector<>. It should be noted
78 that as succinct data it works for both sparse or dense vectors.
79
80 Container also supports notion of NULL (unassigned value) which can be treated
81 differently than 0.
82
83 @ingroup sv
84*/
85template<class Val, class BV>
86class sparse_vector : public base_sparse_vector<Val, BV, 1>
87{
88public:
89 typedef Val value_type;
90 typedef BV bvector_type;
96 typedef typename BV::allocator_type allocator_type;
99 typedef typename allocator_type::allocator_pool_type allocator_pool_type;
103
104
105 /*! Statistical information about memory allocation details. */
106 struct statistics : public bv_statistics
107 {};
108
109 /*! Traits and features used in algorithms to correctly run
110 on a particular type of sparse vector
111 */
112 struct is_remap_support { enum trait { value = false }; };
113 struct is_rsc_support { enum trait { value = false }; };
114 struct is_dynamic_splices { enum trait { value = false }; };
115
116 /**
117 Reference class to access elements via common [] operator
118 @ingroup sv
119 */
121 {
122 public:
124 : sv_(sv), idx_(idx)
125 {}
126 operator value_type() const BMNOEXCEPT { return sv_.get(idx_); }
128 {
129 sv_.set(idx_, (value_type)ref);
130 return *this;
131 }
133 {
134 sv_.set(idx_, val);
135 return *this;
136 }
137 bool operator==(const reference& ref) const BMNOEXCEPT
138 { return bool(*this) == bool(ref); }
139 bool is_null() const BMNOEXCEPT { return sv_.is_null(idx_); }
140 private:
142 size_type idx_;
143 };
144
145
146 /**
147 Const iterator to traverse the sparse vector.
148
149 Implementation uses buffer for decoding so, competing changes
150 to the original vector may not match the iterator returned values.
151
152 This iterator keeps an operational buffer for 8K elements,
153 so memory footprint is not negligable (about 64K for unsigned int)
154
155 @ingroup sv
156 */
158 {
159 public:
160 friend class sparse_vector;
161
162#ifndef BM_NO_STL
163 typedef std::input_iterator_tag iterator_category;
164#endif
172 typedef bm::byte_buffer<allocator_type> buffer_type;
173
174 typedef unsigned difference_type;
175 typedef unsigned* pointer;
177
178 public:
183
184
185 bool operator==(const const_iterator& it) const BMNOEXCEPT
186 { return (pos_ == it.pos_) && (sv_ == it.sv_); }
188 { return ! operator==(it); }
190 { return pos_ < it.pos_; }
192 { return pos_ <= it.pos_; }
194 { return pos_ > it.pos_; }
196 { return pos_ >= it.pos_; }
197
198 /// \brief Get current position (value)
199 value_type operator*() const { return this->value(); }
200
201
202 /// \brief Advance to the next available value
203 const_iterator& operator++() BMNOEXCEPT { this->advance(); return *this; }
204
205 /// \brief Advance to the next available value
206 ///
208 { const_iterator tmp(*this);this->advance(); return tmp; }
209
210
211 /// \brief Get current position (value)
213
214 /// \brief Get NULL status
215 bool is_null() const BMNOEXCEPT;
216
217 /// Returns true if iterator is at a valid position
218 bool valid() const BMNOEXCEPT { return pos_ != bm::id_max; }
219
220 /// Invalidate current iterator
222
223 /// Current position (index) in the vector
224 size_type pos() const BMNOEXCEPT{ return pos_; }
225
226 /// re-position to a specified position
228
229 /// advance iterator forward by one
230 /// @return true if it is still valid
232
234
235 private:
236 const sparse_vector_type* sv_; ///!< ptr to parent
237 size_type pos_; ///!< Position
238 mutable buffer_type buffer_; ///!< value buffer
239 mutable value_type* buf_ptr_; ///!< position in the buffer
240 };
241
242 /**
243 Back insert iterator implements buffered insert, faster than generic
244 access assignment.
245
246 Limitations for buffered inserter:
247 1. Do not use more than one inserter per vector at a time
248 2. Use method flush() at the end to send the rest of accumulated buffer
249 flush is happening automatically on destruction, but if flush produces an
250 exception (for whatever reason) it will be an exception in destructor.
251 As such, explicit flush() is safer way to finilize the sparse vector load.
252
253 @ingroup sv
254 */
256 {
257 public:
258#ifndef BM_NO_STL
259 typedef std::output_iterator_tag iterator_category;
260#endif
269 typedef bm::byte_buffer<allocator_type> buffer_type;
270
271 typedef void difference_type;
272 typedef void pointer;
273 typedef void reference;
274
275 public:
276 /*! @name Construction and assignment */
277 ///@{
278
282
283 /*back_insert_iterator&*/ void operator=(const back_insert_iterator& bi)
284 {
285 BM_ASSERT(bi.empty());
286 this->flush(); sv_ = bi.sv_; bv_null_ = bi.bv_null_;
287 buffer_.reserve(n_buf_size * sizeof(value_type));
288 buf_ptr_ = (unsigned_value_type*)(buffer_.data());
289 this->set_not_null_ = bi.set_not_null_;
290 //return *this;
291 }
292 /** move constructor */
294 /** move assignment*/
295 /*back_insert_iterator&*/void operator= (back_insert_iterator&& bi) BMNOEXCEPT
296 {
297 this->flush(); sv_ = bi.sv_; bv_null_ = bi.bv_null_;
298 this->buffer_.swap(bi.buffer_);
299 this->buf_ptr_ = bi.buf_ptr_;
300 this->set_not_null_ = bi.set_not_null_;
301 //return *this;
302 }
303
305 ///@}
306
307
308 /** push value to the vector */
309 //back_insert_iterator&
310 void operator=(value_type v) { this->add(v); /*return *this;*/ }
311 /** noop */
312 back_insert_iterator& operator*() { return *this; }
313 /** noop */
314 back_insert_iterator& operator++() { return *this; }
315 /** noop */
316 back_insert_iterator& operator++( int ) { return *this; }
317
318 /** add value to the container*/
320
321 /** add NULL (no-value) to the container */
322 void add_null();
323
324 /** add a series of consequitve NULLs (no-value) to the container */
325 void add_null(size_type count);
326
327 /** return true if insertion buffer is empty */
328 bool empty() const;
329
330 /** flush the accumulated buffer
331 @return true if actually flushed (back inserter had data to flush)
332 */
333 bool flush();
334
335 // ---------------------------------------------------------------
336 // open internals
337 // (TODO: create proper friend declarations)
338 //
339 /**
340 Get access to not-null vector
341 @internal
342 */
343 bvector_type* get_null_bvect() const BMNOEXCEPT { return bv_null_; }
344
345 /** add value to the buffer without changing the NULL vector
346 @param v - value to push back
347 @internal
348 */
350
351 /**
352 Reconfigure back inserter not to touch the NULL vector
353 */
354 void disable_set_null() BMNOEXCEPT { set_not_null_ = false; }
355 // ---------------------------------------------------------------
356
357 protected:
359
360 private:
361 buffer_type buffer_; ///!< value buffer
362 bm::sparse_vector<Val, BV>* sv_ = 0; ///!< pointer on the parent vector
363 bvector_type* bv_null_ = 0; ///!< not NULL vector pointer
364 unsigned_value_type* buf_ptr_ = 0; ///!< position in the buffer
365 bool set_not_null_ = true;
366
367 block_idx_type prev_nb_ = 0;///!< previous block added
368 typename
370 };
371
372 friend const_iterator;
373 friend back_insert_iterator;
374
375public:
376 // ------------------------------------------------------------
377 /*! @name Construction and assignment */
378 ///@{
379
380 /*!
381 \brief Sparse vector constructor
382
383 \param null_able - defines if vector supports NULL values flag
384 by default it is OFF, use bm::use_null to enable it
385 \param ap - allocation strategy for underlying bit-vectors
386 Default allocation policy uses BM_BIT setting (fastest access)
387 \param bv_max_size - maximum possible size of underlying bit-vectors
388 Please note, this is NOT size of svector itself, it is dynamic upper limit
389 which should be used very carefully if we surely know the ultimate size
390 \param alloc - allocator for bit-vectors
391
392 \sa bvector<>
393 \sa bm::bvector<>::allocation_policy
394 \sa bm::startegy
395 */
398 size_type bv_max_size = bm::id_max,
399 const allocator_type& alloc = allocator_type());
400
401 /*! copy-ctor */
403
404 /*! copy assignmment operator */
406 {
407 if (this != &sv)
409 return *this;
410 }
411
412 /*! move-ctor */
414
415 /*! move assignmment operator */
417 {
418 if (this != &sv)
419 {
420 clear_all(true, 0);
421 swap(sv);
422 }
423 return *this;
424 }
425
427 ///@}
428
429
430 // ------------------------------------------------------------
431 /*! @name Element access, editing */
432 ///@{
433
434 /** \brief Operator to get write access to an element */
435 reference operator[](size_type idx) BMNOEXCEPT
436 { return reference(*this, idx); }
437
438 /*!
439 \brief get specified element without bounds checking
440 \param idx - element index
441 \return value of the element
442 */
444 { return this->get(idx); }
445
446 /*!
447 \brief access specified element with bounds checking
448 \param idx - element index
449 \return value of the element
450 */
452 /*!
453 \brief get specified element without bounds checking
454 \param idx - element index
455 \return value of the element
456 */
458
459
460 /*!
461 \brief get specified element without checking boundary conditions
462 \param idx - element index
463 \return value of the element
464 */
466
467 /**
468 \brief get specified element with NOT NULL check
469 \param idx - element index
470 \param v - [out] value to get
471 \return true if value was aquired (NOT NULL), false otherwise
472 @sa is_null, get
473 */
475
476 /*!
477 \brief set specified element with bounds checking and automatic resize
478 \param idx - element index
479 \param v - element value
480 */
482
483 /*!
484 \brief increment specified element by one
485 \param idx - element index
486 */
487 void inc(size_type idx);
488
489 /*!
490 \brief push value back into vector
491 \param v - element value
492 */
494
495 /*!
496 \brief push back specified amount of NULL values
497 \param count - number of NULLs to push back
498 */
500
501 /*!
502 \brief push back NULL value
503 */
505
506 /*!
507 \brief insert specified element into container
508 \param idx - element index
509 \param v - element value
510 */
512
513 /*!
514 \brief erase specified element from container
515 \param idx - element index
516 \param erase_null - erase the NULL vector (if exists) (default: true)
517 */
518 void erase(size_type idx, bool erase_null = true);
519
520
521 /**
522 \brief swap two vector elements between each other
523 \param idx1 - element index 1
524 \param idx1 - element index 2
525 */
526 void swap(size_type idx1, size_type idx2);
527
528
529 /*!
530 \brief clear specified element with bounds checking and automatic resize
531 \param idx - element index
532 \param set_null - if true the value receives NULL (unassigned) value
533 */
534 void clear(size_type idx, bool set_null/* = false*/);
535
536 /** \brief set specified element to unassigned value (NULL)
537 \param idx - element index
538 */
540
541 /**
542 Set NULL all elements set as 1 in the argument vector.
543 Function also clears all the values to 0.
544 \param bv_idx - index bit-vector for elements which to be set to NULL
545 */
546 void set_null(const bvector_type& bv_idx)
547 { this->bit_sub_rows(bv_idx, true); }
548
549 /**
550 Set vector elements spcified by argument bit-vector to zero
551 Note that set to 0 elements are NOT going to tuned to NULL (NULL qualifier is preserved)
552 \param bv_idx - index bit-vector for elements which to be set to 0
553 */
554 void clear(const bvector_type& bv_idx)
555 { this->bit_sub_rows(bv_idx, false); }
556
557 /** Get raw unsigned value first N bits
558 \param idx - element index in the vector
559 \param N_bits - number of bits to be extracted (should be > 0)
560 @return unsigned value for
561 */
563 size_type N_bits) const BMNOEXCEPT;
564
565 ///@}
566
567 // ------------------------------------------------------------
568 /*! @name Iterator access */
569 ///@{
570
571 /** Provide const iterator access to container content */
572 const_iterator begin() const BMNOEXCEPT;
573
574 /** Provide const iterator access to the end */
575 const_iterator end() const BMNOEXCEPT
576 { return const_iterator(this, bm::id_max); }
577
578 /** Get const_itertor re-positioned to specific element
579 @param idx - position in the sparse vector
580 */
581 const_iterator get_const_iterator(size_type idx) const BMNOEXCEPT
582 { return const_iterator(this, idx); }
583
584 /** Provide back insert iterator
585 Back insert iterator implements buffered insertion,
586 which is faster, than random access or push_back
587 */
588 back_insert_iterator get_back_inserter()
589 { return back_insert_iterator(this); }
590 ///@}
591
592
593 // ------------------------------------------------------------
594 /*! @name Various traits */
595 ///@{
596
597 /** \brief various type traits
598 */
599 static constexpr
600 bool is_compressed() BMNOEXCEPT { return false; }
601
602 static constexpr
603 bool is_str() BMNOEXCEPT { return false; }
604
605 ///@}
606
607
608 // ------------------------------------------------------------
609 /*! @name Loading of sparse vector from C-style array */
610 ///@{
611
612 /*!
613 \brief Import list of elements from a C-style array
614 \param arr - source array
615 \param arr_size - source size
616 \param offset - target index in the sparse vector
617 \param set_not_null - import should register in not null vector
618 */
619 void import(const value_type* arr,
620 size_type arr_size,
621 size_type offset = 0,
622 bool set_not_null = true);
623
624 /*!
625 \brief Import list of elements from a C-style array (pushed back)
626 \param arr - source array
627 \param arr_size - source array size
628 \param set_not_null - import should register in not null vector
629 */
630 void import_back(const value_type* arr,
631 size_type arr_size,
632 bool set_not_null = true);
633 ///@}
634
635 // ------------------------------------------------------------
636 /*! @name Export content to C-style array */
637 ///@{
638
639 /*!
640 \brief Bulk export list of elements to a C-style array
641
642 For efficiency, this is left as a low level function,
643 it does not do any bounds checking on the target array, it will
644 override memory and crash if you are not careful with allocation
645 and request size.
646
647 \param arr - dest array
648 \param idx_from - index in the sparse vector to export from
649 \param dec_size - decoding size (array allocation should match)
650 \param zero_mem - set to false if target array is pre-initialized
651 with 0s to avoid performance penalty
652
653 \return number of actually exported elements (can be less than requested)
654
655 \sa gather
656 */
658 size_type idx_from,
659 size_type dec_size,
660 bool zero_mem = true) const;
661
662
663 /*!
664 \brief Gather elements to a C-style array
665
666 Gather collects values from different locations, for best
667 performance feed it with sorted list of indexes.
668
669 Faster than one-by-one random access.
670
671 For efficiency, this is left as a low level function,
672 it does not do any bounds checking on the target array, it will
673 override memory and crash if you are not careful with allocation
674 and request size.
675
676 \param arr - dest array
677 \param idx - index list to gather elements
678 \param size - decoding index list size (array allocation should match)
679 \param sorted_idx - sort order directive for the idx array
680 (BM_UNSORTED, BM_SORTED, BM_UNKNOWN)
681 Sort order affects both performance and correctness(!), use BM_UNKNOWN
682 if not sure.
683
684 \return number of actually exported elements (can be less than requested)
685
686 \sa decode
687 */
689 const size_type* idx,
691 bm::sort_order sorted_idx) const;
692 ///@}
693
694 /*! \brief content exchange
695 */
697
698 // ------------------------------------------------------------
699 /*! @name Clear */
700 ///@{
701
702 /*! \brief resize to zero, free memory
703 @param free_mem - true - indicates the need to free underlying memory in bit-vectors
704 */
705 void clear_all(bool free_mem, unsigned ) BMNOEXCEPT;
706
707 /*! \brief resize to zero, free memory */
708 void clear() BMNOEXCEPT { clear_all(true, 0); }
709
710 /*!
711 \brief clear range (assign bit 0 for all planes)
712 \param left - interval start
713 \param right - interval end (closed interval)
714 \param set_null - set cleared values to unassigned (NULL)
715 */
717 size_type right,
718 bool set_null = false);
719
720 ///@}
721
722 // ------------------------------------------------------------
723 /*! @name Size, etc */
724 ///@{
725
726 /*! \brief return size of the vector
727 \return size of sparse vector
728 */
729 size_type size() const BMNOEXCEPT { return this->size_; }
730
731 /*! \brief return true if vector is empty
732 \return true if empty
733 */
734 bool empty() const BMNOEXCEPT { return (size() == 0); }
735
736 /*! \brief resize vector
737 \param sz - new size
738 */
739 void resize(size_type sz) { parent_type::resize(sz, true); }
740
741 /**
742 \brief recalculate size to exclude tail NULL elements
743 After this call size() will return the true size of the vector
744 */
746
747 ///@}
748
749 // ------------------------------------------------------------
750 /*! @name Comparison */
751 ///@{
752
753 /*!
754 \brief check if another sparse vector has the same content and size
755
756 \param sv - sparse vector for comparison
757 \param null_able - flag to consider NULL vector in comparison (default)
758 or compare only value content planes
759
760 \return true, if it is the same
761 */
762 bool equal(const sparse_vector<Val, BV>& sv,
763 bm::null_support null_able = bm::use_null) const BMNOEXCEPT;
764
765 ///@}
766
767 // ------------------------------------------------------------
768 /*! @name Element comparison */
769 ///@{
770
771 /**
772 \brief Compare vector element with argument
773
774 \param idx - vactor element index
775 \param val - argument to compare with
776
777 \return 0 - equal, < 0 - vect[i] < val, >0 otherwise
778 */
779 int compare(size_type idx, const value_type val) const BMNOEXCEPT;
780
781 ///@}
782
783 // ------------------------------------------------------------
784 /*! @name Memory optimization */
785 ///@{
786
787 /*!
788 \brief run memory optimization for all vector planes
789 \param temp_block - pre-allocated memory block to avoid unnecessary re-allocs
790 \param opt_mode - requested compression depth
791 \param stat - memory allocation statistics after optimization
792 */
793 void optimize(bm::word_t* temp_block = 0,
794 typename bvector_type::optmode opt_mode = bvector_type::opt_compress,
795 typename sparse_vector<Val, BV>::statistics* stat = 0);
796
797 /*!
798 \brief Optimize sizes of GAP blocks
799
800 This method runs an analysis to find optimal GAP levels for all bit planes
801 of the vector.
802 */
804
805 /*!
806 @brief Calculates memory statistics.
807
808 Function fills statistics structure containing information about how
809 this vector uses memory and estimation of max. amount of memory
810 bvector needs to serialize itself.
811
812 @param st - pointer on statistics structure to be filled in.
813
814 @sa statistics
815 */
817 struct sparse_vector<Val, BV>::statistics* st) const BMNOEXCEPT;
818
819 /**
820 @brief Turn sparse vector into immutable mode
821 Read-only (immutable) vector uses less memory and allows faster searches.
822 Before freezing it is recommenede to call optimize() to get full memory saving effect
823 @sa optimize
824 */
825 void freeze() { this->freeze_matr(); }
826
827 /** Returns true if vector is read-only */
828 bool is_ro() const BMNOEXCEPT { return this->is_ro_; }
829
830 ///@}
831
832 // ------------------------------------------------------------
833 /*! @name Merge, split, partition data */
834 ///@{
835
836 /*!
837 \brief join all with another sparse vector using OR operation
838 \param sv - argument vector to join with
839 \return slf reference
840 @sa merge
841 */
843
844 /*!
845 \brief merge with another sparse vector using OR operation
846 Merge is different from join(), because it borrows data from the source
847 vector, so it gets modified.
848
849 \param sv - [in, out]argument vector to join with (vector mutates)
850
851 \return slf reference
852 @sa join
853 */
855
856
857 /**
858 @brief copy range of values from another sparse vector
859
860 Copy [left..right] values from the source vector,
861 clear everything outside the range.
862
863 \param sv - source vector
864 \param left - index from in losed diapason of [left..right]
865 \param right - index to in losed diapason of [left..right]
866 \param slice_null - "use_null" copy range for NULL vector or
867 do not copy it
868 */
870 size_type left, size_type right,
871 bm::null_support slice_null = bm::use_null);
872
873
874 /**
875 Keep only specified interval in the sparse vector, clear all other
876 elements.
877
878 \param left - interval start
879 \param right - interval end (closed interval)
880 \param slice_null - "use_null" copy range for NULL vector or not
881 */
883 bm::null_support slice_null = bm::use_null);
884
885 /**
886 @brief Apply value filter, defined by mask vector
887
888 All bit-planes are ANDed against the filter mask.
889 */
890 void filter(const bvector_type& bv_mask);
891
892 ///@}
893
894
895 // ------------------------------------------------------------
896 /*! @name Access to internals */
897 ///@{
898
899
900 /*! \brief syncronize internal structures, build fast access index
901 */
902 void sync(bool /*force*/) { this->sync_ro(); }
903
904
905 /*!
906 \brief Bulk export list of elements to a C-style array
907
908 Use of all extract() methods is restricted.
909 Please consider decode() for the same purpose.
910
911 \param arr - dest array
912 \param size - dest size
913 \param offset - target index in the sparse vector to export from
914 \param zero_mem - set to false if target array is pre-initialized
915 with 0s to avoid performance penalty
916 \return effective size(number) of exported elements
917
918 \sa decode
919
920 @internal
921 */
922 size_type extract(value_type* arr,
924 size_type offset = 0,
925 bool zero_mem = true) const BMNOEXCEPT2;
926
927 /** \brief extract small window without use of masking vector
928 \sa decode
929 @internal
930 */
933 size_type offset,
934 bool zero_mem = true) const;
935
936 /** \brief extract medium window without use of masking vector
937 \sa decode
938 @internal
939 */
942 size_type offset,
943 bool zero_mem = true) const;
944
945 /** \brief address translation for this type of container
946 \internal
947 */
948 static
950
951 /**
952 \brief throw range error
953 \internal
954 */
955 static
956 void throw_range_error(const char* err_msg);
957
958 /**
959 \brief throw bad alloc
960 \internal
961 */
962 static
964
965
966 /**
967 \brief find position of compressed element by its rank
968 */
969 static
971
972 /**
973 \brief size of sparse vector (may be different for RSC)
974 */
976
977 /**
978 \brief Always 1 (non-matrix type)
979 */
981
982 ///@}
983
984 /// Set allocator pool for local (non-threaded)
985 /// memory cyclic(lots of alloc-free ops) opertations
986 ///
988
989protected:
991 {
993 };
995 {
996 n_buf_size = 1024 * 8
997 };
998
999
1000 /*! \brief set value without checking boundaries */
1001 void set_value(size_type idx, value_type v, bool need_clear);
1002
1003 /*! \brief set value without checking boundaries or support of NULL
1004 @param idx - element index
1005 @param v - value to set
1006 @param need_clear - if clear 0 bits is necessary
1007 (or not if vector is resized)
1008 */
1009 void set_value_no_null(size_type idx, value_type v, bool need_clear);
1010
1011 /*! \brief push value back into vector without NULL semantics */
1013
1014 /*! \brief insert value without checking boundaries */
1016 /*! \brief insert value without checking boundaries or support of NULL */
1018
1022
1023 constexpr bool is_remap() const BMNOEXCEPT { return false; }
1024 size_t remap_size() const BMNOEXCEPT { return 0; }
1025 const unsigned char* get_remap_buffer() const BMNOEXCEPT { return 0; }
1026 unsigned char* init_remap_buffer() BMNOEXCEPT { return 0; }
1028
1029 /// unused remap matrix type for compatibility with the sparse serializer
1030 typedef
1031 bm::heap_matrix<unsigned char,
1032 sizeof(value_type), /* ROWS */
1033 256, /* COLS = number of chars in the ASCII set */
1036
1037 const remap_matrix_type* get_remap_matrix() const { return 0; }
1039
1041 size_type* idx_from, size_type* idx_to) const BMNOEXCEPT
1042 {
1043 *idx_from = from; *idx_to = to; return true;
1044 }
1045
1046 /// Increment element by 1 without chnaging NULL vector or size
1048
1049 /// increment by v without chnaging NULL vector or size
1051
1052 /*!
1053 \brief Import list of elements from a C-style array (pushed back)
1054 \param arr - source array
1055 \param arr_size - source array size
1056 \param set_not_null - import should register in not null vector
1057 */
1059 size_type arr_size,
1060 bool set_not_null = true);
1061
1062 /*!
1063 \brief Import list of elements from a C-style array
1064 \param arr - source array
1065 \param arr_size - source size
1066 \param offset - target index in the sparse vector
1067 \param set_not_null - import should register in not null vector
1068 */
1070 size_type arr_size, size_type offset,
1071 bool set_not_null);
1072
1074 size_type arr_size, size_type offset,
1075 bool set_not_null);
1076
1078
1079 static
1081
1082 /// get raw unsigned value
1084
1085
1086protected:
1087 template<class V, class SV> friend class rsc_sparse_vector;
1088 template<class SVect, unsigned S_FACTOR> friend class sparse_vector_scanner;
1089 template<class SVect> friend class sparse_vector_serializer;
1090 template<class SVect> friend class sparse_vector_deserializer;
1091
1092};
1093
1094
1095//---------------------------------------------------------------------
1096//---------------------------------------------------------------------
1097
1098
1099template<class Val, class BV>
1101 bm::null_support null_able,
1103 size_type bv_max_size,
1104 const allocator_type& alloc)
1105: parent_type(null_able, false, ap, bv_max_size, alloc)
1106{}
1107
1108//---------------------------------------------------------------------
1109
1110template<class Val, class BV>
1114
1115//---------------------------------------------------------------------
1116#ifndef BM_NO_CXX11
1117
1118template<class Val, class BV>
1123
1124#endif
1125
1126
1127//---------------------------------------------------------------------
1128
1129template<class Val, class BV>
1132
1133//---------------------------------------------------------------------
1134
1135template<class Val, class BV>
1140
1141//---------------------------------------------------------------------
1142
1143template<class Val, class BV>
1145{
1146#ifndef BM_NO_STL
1147 throw std::range_error(err_msg);
1148#else
1149 BM_ASSERT_THROW(false, BM_ERR_RANGE);
1150#endif
1151}
1152
1153//---------------------------------------------------------------------
1154
1155template<class Val, class BV>
1157{
1158 BV::throw_bad_alloc();
1159}
1160
1161//---------------------------------------------------------------------
1162
1163template<class Val, class BV>
1165{
1166 clear(idx, true);
1167}
1168
1169//---------------------------------------------------------------------
1170
1171template<class Val, class BV>
1173 size_type arr_size,
1174 size_type offset,
1175 bool set_not_null)
1176{
1177 if constexpr (std::is_signed<value_type>::value)
1178 {
1179 const unsigned tmp_size = 1024;
1180 unsigned_value_type arr_tmp[tmp_size];
1181 size_type k(0), i(0);
1182 while (i < arr_size)
1183 {
1184 arr_tmp[k++] = this->s2u(arr[i++]);
1185 if (k == tmp_size)
1186 {
1187 import_u(arr_tmp, k, offset, set_not_null);
1188 k = 0; offset += tmp_size;
1189 }
1190 } // while
1191 if (k)
1192 {
1193 import_u(arr_tmp, k, offset, set_not_null);
1194 }
1195 }
1196 else
1197 {
1198 import_u((const unsigned_value_type*) arr, arr_size, offset, set_not_null);
1199 }
1200}
1201
1202//---------------------------------------------------------------------
1203
1204template<class Val, class BV>
1206 size_type arr_size,
1207 size_type offset,
1208 bool set_not_null)
1209{
1210 if (arr_size == 0)
1211 throw_range_error("sparse_vector range error (import size 0)");
1212
1213 // clear all planes in the range to provide corrrect import of 0 values
1214 if (offset < this->size_) // in case it touches existing elements
1215 this->clear_range(offset, offset + arr_size - 1);
1216
1217 this->import_u_nocheck(arr, arr_size, offset, set_not_null);
1218}
1219//---------------------------------------------------------------------
1220
1221template<class Val, class BV>
1223 (const unsigned_value_type* arr,
1224 size_type arr_size,
1225 size_type offset,
1226 bool set_not_null)
1227{
1228 BM_ASSERT(arr);
1229 const unsigned bit_capacity = sizeof(Val)*8;
1230 unsigned char b_list[bit_capacity];
1231 unsigned row_len[bit_capacity] = {0, };
1232 bvector_type_ptr bv_slices[bit_capacity] = {0, };
1233
1234 const unsigned transpose_window = 256; // L1-sized for 32-bit int
1236
1237 // transposition algorithm uses bitscan to find index bits and store it
1238 // in temporary matrix (list for each bit plane), matrix here works
1239 // when array gets to big - the list gets loaded into bit-vector using
1240 // bulk load algorithm, which is faster than single bit access
1241 //
1242
1243 size_type i;
1244 for (i = 0; i < arr_size; ++i)
1245 {
1246 unsigned bcnt = bm::bitscan(arr[i], b_list);
1247 const size_type bit_idx = i + offset;
1248
1249 for (unsigned j = 0; j < bcnt; ++j)
1250 {
1251 unsigned p = b_list[j];
1252 unsigned rl = row_len[p];
1253 tm.row(p)[rl] = bit_idx;
1254 row_len[p] = ++rl;
1255
1256 if (rl == transpose_window)
1257 {
1258 bvector_type* bv = bv_slices[p];
1259 if (!bv)
1260 bv = bv_slices[p] = this->get_create_slice(p);
1261
1262 const size_type* r = tm.row(p);
1263 row_len[p] = 0;
1264 bv->import_sorted(r, rl, false);
1265
1266 }
1267 } // for j
1268 } // for i
1269
1270 // process incomplete transposition lines
1271 //
1272 unsigned rows = tm.rows();
1273 for (unsigned k = 0; k < rows; ++k)
1274 {
1275 if (unsigned rl = row_len[k])
1276 {
1277 bvector_type* bv = bv_slices[k];
1278 if (!bv)
1279 bv = this->get_create_slice(k);
1280 const size_type* row = tm.row(k);
1281 bv->import_sorted(row, rl, false);
1282 }
1283 } // for k
1284
1285
1286 if (i + offset > this->size_)
1287 this->size_ = i + offset;
1288
1289 if (set_not_null)
1290 {
1291 if (bvector_type* bv_null = this->get_null_bvect())
1292 bv_null->set_range(offset, offset + arr_size - 1);
1293 }
1294}
1295
1296
1297//---------------------------------------------------------------------
1298
1299template<class Val, class BV>
1301{
1302 const bvector_type* bv_null = this->get_null_bvector();
1303 if (!bv_null)
1304 return;
1305 bool found = bv_null->find_reverse(this->size_);
1306 this->size_ += found;
1307}
1308
1309//---------------------------------------------------------------------
1310
1311template<class Val, class BV>
1313 size_type arr_size,
1314 bool set_not_null)
1315{
1316 if constexpr (std::is_signed<value_type>::value)
1317 {
1318 const unsigned tmp_size = 1024;
1319 unsigned_value_type arr_tmp[tmp_size];
1320 size_type k(0), i(0);
1321 while (i < arr_size)
1322 {
1323 arr_tmp[k++] = this->s2u(arr[i++]);
1324 if (k == tmp_size)
1325 {
1326 import_back_u(arr_tmp, k, set_not_null);
1327 k = 0;
1328 }
1329 } // while
1330 if (k)
1331 {
1332 import_back_u(arr_tmp, k, set_not_null);
1333 }
1334 }
1335 else
1336 {
1337 this->import_back_u((const unsigned_value_type*)arr, arr_size, set_not_null);
1338 }
1339}
1340
1341
1342//---------------------------------------------------------------------
1343
1344template<class Val, class BV>
1346 size_type arr_size,
1347 bool set_not_null)
1348{
1349 this->import_u_nocheck(arr, arr_size, this->size(), set_not_null);
1350}
1351
1352//---------------------------------------------------------------------
1353
1354template<class Val, class BV>
1357 size_type idx_from,
1358 size_type dec_size,
1359 bool zero_mem) const
1360{
1361 return extract(arr, dec_size, idx_from, zero_mem);
1362}
1363
1364//---------------------------------------------------------------------
1365
1366template<class Val, class BV>
1369 const size_type* idx,
1371 bm::sort_order sorted_idx) const
1372{
1373 BM_ASSERT(arr);
1374 BM_ASSERT(idx);
1375 BM_ASSERT(size);
1376
1377 if (size == 1) // corner case: get 1 value
1378 {
1379 arr[0] = this->get(idx[0]);
1380 return size;
1381 }
1382 ::memset(arr, 0, sizeof(value_type)*size);
1383 for (size_type i = 0; i < size;)
1384 {
1385 bool sorted_block = true; // initial assumption
1386
1387 // look ahead for the depth of the same block
1388 // (speculate more than one index lookup per block)
1389 //
1390 block_idx_type nb = (idx[i] >> bm::set_block_shift);
1391 size_type r = i;
1392
1393 switch (sorted_idx)
1394 {
1395 case BM_UNKNOWN:
1396 {
1397 // check if sorted, it pays off to verify
1398 size_type idx_prev = idx[r];
1399 for (; (r < size) && (nb == (idx[r] >> bm::set_block_shift)); ++r)
1400 {
1401 if (sorted_block)
1402 {
1403 if (idx[r] < idx_prev) // sorted check
1404 sorted_block = false;
1405 idx_prev = idx[r];
1406 }
1407 } // for r
1408 }
1409 break;
1410 case BM_UNSORTED:
1411 sorted_block = false;
1412 for (; r < size; ++r)
1413 {
1414 block_idx_type nb_next = (idx[r] >> bm::set_block_shift);
1415 if (nb != nb_next)
1416 break;
1417 } // for r
1418 break;
1419 case BM_SORTED:
1420 #ifdef BM64ADDR
1421 r = bm::idx_arr_block_lookup_u64(idx, size, nb, r);
1422 #else
1423 r = bm::idx_arr_block_lookup_u32(idx, size, nb, r);
1424 #endif
1425 break;
1426 case BM_SORTED_UNIFORM:
1427 r = size;
1428 break;
1429 default:
1430 BM_ASSERT(0);
1431 } // switch
1432
1433 // single element hit, use random access
1434 if (r == i+1)
1435 {
1436 // (idx[i] < bm::id_max) ? is an out of bounds check
1437 // some code (RSC vector) uses it to
1438 // indicate NULL value and prsent it as 0
1439 //
1440 if (idx[i] < bm::id_max)
1441 {
1442 unsigned_value_type uv = this->get_unsigned(idx[i]);
1443 arr[i] = value_type(uv);
1444 }
1445 ++i;
1446 continue;
1447 }
1448
1449 // process block co-located elements at ones for best (CPU cache opt)
1450 //
1451 unsigned i0, j0;
1452 bm::get_block_coord(nb, i0, j0);
1453
1454 unsigned eff_planes = this->effective_slices(); // TODO: get real effective planes for [i,j]
1455 BM_ASSERT(eff_planes <= (sizeof(value_type) * 8));
1456
1457 for (unsigned j = 0; j < eff_planes; ++j)
1458 {
1459 const bm::word_t* blk = this->bmatr_.get_block(j, i0, j0);
1460 if (!blk)
1461 continue;
1463 const unsigned_value_type mask1 = 1u;
1464
1465 if (blk == FULL_BLOCK_FAKE_ADDR)
1466 {
1467 vm = (mask1 << j);
1468 for (size_type k = i; k < r; ++k)
1469 ((unsigned_value_type*)arr)[k] |= vm;
1470 continue;
1471 }
1472 if (BM_IS_GAP(blk))
1473 {
1474 const bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
1475 unsigned is_set;
1476
1477 if (sorted_block) // b-search hybrid with scan lookup
1478 {
1479 for (size_type k = i; k < r; )
1480 {
1481 unsigned nbit = unsigned(idx[k] & bm::set_block_mask);
1482
1483 unsigned gidx = bm::gap_bfind(gap_blk, nbit, &is_set);
1484 unsigned gap_value = gap_blk[gidx];
1485 if (is_set)
1486 {
1487 ((unsigned_value_type*)arr)[k] |= vm = (mask1 << j);
1488 for (++k; k < r; ++k) // speculative look-up
1489 {
1490 if (unsigned(idx[k] & bm::set_block_mask) <= gap_value)
1491 ((unsigned_value_type*)arr)[k] |= vm;
1492 else
1493 break;
1494 }
1495 }
1496 else // 0 GAP - skip. not set
1497 {
1498 for (++k;
1499 (k < r) &&
1500 (unsigned(idx[k] & bm::set_block_mask) <= gap_value);
1501 ++k) {}
1502 }
1503 } // for k
1504 }
1505 else // unsorted block gather request: b-search lookup
1506 {
1507 for (size_type k = i; k < r; ++k)
1508 {
1509 unsigned nbit = unsigned(idx[k] & bm::set_block_mask);
1510 is_set = bm::gap_test_unr(gap_blk, nbit);
1511 ((unsigned_value_type*)arr)[k] |= (unsigned_value_type(bool(is_set)) << j);
1512 } // for k
1513 }
1514 continue;
1515 }
1516 bm::bit_block_gather_scatter((unsigned_value_type*)arr, blk, idx, r, i, j);
1517 } // for (each plane)
1518
1519 i = r;
1520
1521 } // for i
1522
1523 if constexpr (parent_type::is_signed())
1524 u2s_translate(arr, size);
1525
1526 return size;
1527}
1528
1529//---------------------------------------------------------------------
1530
1531template<class Val, class BV>
1535 size_type offset,
1536 bool zero_mem) const
1537{
1538 if (size == 0)
1539 return 0;
1540 if (zero_mem)
1541 ::memset(arr, 0, sizeof(value_type)*size);
1542
1543 size_type start = offset;
1544 size_type end = start + size;
1545 if (end > this->size_)
1546 end = this->size_;
1547
1548 // calculate logical block coordinates and masks
1549 //
1550 block_idx_type nb = (start >> bm::set_block_shift);
1551 unsigned i0, j0;
1552 bm::get_block_coord(nb, i0, j0);
1553
1554 unsigned nbit = unsigned(start & bm::set_block_mask);
1555 unsigned nword = unsigned(nbit >> bm::set_word_shift);
1556 unsigned mask0 = 1u << (nbit & bm::set_word_mask);
1557 const bm::word_t* blk = 0;
1558 unsigned is_set;
1559
1560 auto planes = this->effective_slices();
1561 BM_ASSERT(planes <= (sizeof(value_type) * 8));
1562
1563 for (unsigned j = 0; j < planes; ++j)
1564 {
1565 blk = this->bmatr_.get_block(j, i0, j0);
1566 bool is_gap = BM_IS_GAP(blk);
1567
1568 for (size_type k = start; k < end; ++k)
1569 {
1571 if (nb1 != nb) // block switch boundaries
1572 {
1573 nb = nb1;
1574 bm::get_block_coord(nb, i0, j0);
1575 blk = this->bmatr_.get_block(j, i0, j0);
1576 is_gap = BM_IS_GAP(blk);
1577 }
1578 if (!blk)
1579 continue;
1580 nbit = unsigned(k & bm::set_block_mask);
1581 if (is_gap)
1582 {
1583 is_set = bm::gap_test_unr(BMGAP_PTR(blk), nbit);
1584 }
1585 else
1586 {
1587 if (blk == FULL_BLOCK_FAKE_ADDR)
1588 {
1589 is_set = 1;
1590 }
1591 else
1592 {
1593 BM_ASSERT(!IS_FULL_BLOCK(blk));
1594 nword = unsigned(nbit >> bm::set_word_shift);
1595 mask0 = 1u << (nbit & bm::set_word_mask);
1596 is_set = (blk[nword] & mask0);
1597 }
1598 }
1599 size_type idx = k - offset;
1600 unsigned_value_type vm = (bool) is_set;
1601 vm <<= j;
1602 arr[idx] |= vm;
1603
1604 } // for k
1605
1606 } // for j
1607
1608 if constexpr (parent_type::is_signed())
1609 u2s_translate(arr, size);
1610
1611 return 0;
1612}
1613
1614//---------------------------------------------------------------------
1615
1616template<class Val, class BV>
1620 size_type offset,
1621 bool zero_mem) const
1622{
1623 if (size == 0)
1624 return 0;
1625
1626 if (zero_mem)
1627 ::memset(arr, 0, sizeof(value_type)*size);
1628
1629 size_type start = offset;
1630 size_type end = start + size;
1631 if (end > this->size_)
1632 end = this->size_;
1633
1634 for (size_type i = 0; i < parent_type::value_bits(); ++i)
1635 {
1636 const bvector_type* bv = this->bmatr_.get_row(i);
1637 if (!bv)
1638 continue;
1639
1640 unsigned_value_type mask = 1u << i;
1641 typename BV::enumerator en(bv, offset);
1642 for (;en.valid(); ++en)
1643 {
1644 size_type idx = *en - offset;
1645 if (idx >= size)
1646 break;
1647 arr[idx] |= mask;
1648 } // for
1649
1650 } // for i
1651
1652 return 0;
1653}
1654
1655
1656//---------------------------------------------------------------------
1657
1658template<class Val, class BV>
1662 size_type offset,
1663 bool zero_mem) const BMNOEXCEPT2
1664{
1665 /// Decoder functor
1666 /// @internal
1667 struct sv_decode_visitor_func
1668 {
1669 sv_decode_visitor_func(value_type* BMRESTRICT varr,
1672 : arr_(varr), mask_(mask), sv_off_(off)
1673 {}
1674
1675 int add_bits(size_type bv_offset,
1676 const unsigned char* BMRESTRICT bits,
1677 unsigned bits_size) BMNOEXCEPT
1678 {
1679 // can be negative (-1) when bv base offset = 0 and sv = 1,2..
1680 size_type base = bv_offset - sv_off_;
1681 unsigned_value_type m = mask_;
1682 for (unsigned i = 0; i < bits_size; ++i)
1683 arr_[bits[i] + base] |= m;
1684 return 0;
1685 }
1686 int add_range(size_type bv_offset, size_type sz) BMNOEXCEPT
1687 {
1688 auto base = bv_offset - sv_off_;
1689 unsigned_value_type m = mask_;
1690 for (size_type i = 0; i < sz; ++i)
1691 arr_[i + base] |= m;
1692 return 0;
1693 }
1694
1695 value_type* BMRESTRICT arr_; ///< target array for de-transpose
1696 unsigned_value_type mask_; ///< bit-plane mask
1697 size_type sv_off_; ///< SV read offset
1698 };
1699
1700 if (!size)
1701 return 0;
1702
1703 if (zero_mem)
1704 ::memset(arr, 0, sizeof(value_type)*size);
1705
1706 size_type end = offset + size;
1707 if (end > this->size_)
1708 end = this->size_;
1709
1710 sv_decode_visitor_func func(arr, 0, offset);
1711
1712 auto planes = this->effective_slices();
1713 BM_ASSERT(planes <= (sizeof(value_type) * 8));
1714 for (size_type i = 0; i < planes; ++i)
1715 {
1716 if (const bvector_type* bv = this->bmatr_.get_row(i))
1717 {
1718 func.mask_ = (unsigned_value_type(1) << i); // set target plane OR mask
1719 bm::for_each_bit_range_no_check(*bv, offset, end-1, func);
1720 }
1721 } // for i
1722
1723 const size_type exported_size = end - offset;
1724 if constexpr (parent_type::is_signed())
1725 u2s_translate(arr, exported_size);
1726 return exported_size;
1727}
1728
1729//---------------------------------------------------------------------
1730
1731template<class Val, class BV>
1733{
1734 for (size_type i = 0; i < sz; ++i)
1735 {
1737 ::memcpy(&uv, &arr[i], sizeof(uv));
1738 arr[i] = parent_type::u2s(uv);
1739 } // for i
1740}
1741
1742
1743//---------------------------------------------------------------------
1744
1745template<class Val, class BV>
1748{
1749 if (idx >= this->size_)
1750 throw_range_error("sparse vector range error");
1751 return this->get(idx);
1752}
1753
1754//---------------------------------------------------------------------
1755
1756template<class Val, class BV>
1760{
1761 BM_ASSERT(i < size());
1762 return get_no_check(i);
1763}
1764
1765//---------------------------------------------------------------------
1766
1767template<class Val, class BV>
1771{
1773 if constexpr (parent_type::is_signed())
1774 return this->u2s(uv);
1775 else
1776 return uv;
1777}
1778
1779//---------------------------------------------------------------------
1780
1781template<class Val, class BV>
1785{
1786 BM_ASSERT(i < bm::id_max);
1787
1788 unsigned_value_type uv = 0;
1789 const unsigned eff_planes = this->effective_slices();
1790 BM_ASSERT(eff_planes <= (sizeof(value_type) * 8));
1791
1792 unsigned_value_type smask = this->slice_mask_;
1793 for (unsigned j = 0; smask && j < eff_planes; j+=4, smask >>= 4)
1794 {
1795 if (smask & 0x0F) // b1111
1796 {
1798 (unsigned_value_type)this->bmatr_.get_half_octet(i, j);
1799 uv |= unsigned_value_type(vm << j);
1800 }
1801 } // for j
1802 return uv;
1803}
1804
1805//---------------------------------------------------------------------
1806
1807template<class Val, class BV>
1810 size_type N_bits) const BMNOEXCEPT
1811{
1812 BM_ASSERT(idx < bm::id_max);
1813 const unsigned eff_planes = this->effective_slices();
1814 BM_ASSERT(eff_planes <= (sizeof(value_type) * 8));
1815 if (N_bits > eff_planes)
1816 N_bits = eff_planes;
1817 unsigned_value_type uv = 0;
1818
1819 for (unsigned j = 0; j < N_bits; ++j)
1820 {
1821 const bvector_type* bv = this->bmatr_.get_row(j);
1822 if (bv)
1823 {
1824 bool b = bv->test(idx);
1825 if (b)
1826 uv |= unsigned_value_type(1) << j;
1827 }
1828 } // for j
1829 return uv;
1830}
1831
1832
1833//---------------------------------------------------------------------
1834
1835template<class Val, class BV>
1837 size_type idx, value_type& v) const BMNOEXCEPT
1838{
1839 if (this->is_null(idx))
1840 return false;
1841 v = get(idx);
1842 return true;
1843}
1844
1845
1846//---------------------------------------------------------------------
1847
1848template<class Val, class BV>
1850{
1851 bool need_clear;
1852 if (idx >= size())
1853 {
1854 this->size_ = idx+1;
1855 need_clear = false;
1856 }
1857 else
1858 need_clear = true;
1859 set_value(idx, v, need_clear);
1860}
1861
1862//---------------------------------------------------------------------
1863
1864template<class Val, class BV>
1866{
1867 if (idx >= size())
1868 this->size_ = idx+1; // assumed there is nothing to do outside the size
1869 else
1870 {
1871 set_value(idx, value_type(0), true);
1872 if (set_null)
1873 {
1874 if (bvector_type* bv_null = this->get_null_bvect())
1875 bv_null->clear_bit_no_check(idx);
1876 }
1877 }
1878}
1879
1880//---------------------------------------------------------------------
1881
1882template<class Val, class BV>
1884{
1885 set_value(this->size_, v, false);
1886 ++(this->size_);
1887}
1888
1889//---------------------------------------------------------------------
1890
1891template<class Val, class BV>
1893{
1894 BM_ASSERT(count);
1895 BM_ASSERT(bm::id_max - count > this->size_);
1896 BM_ASSERT(this->is_nullable());
1897
1898 this->size_ += count;
1899}
1900
1901//---------------------------------------------------------------------
1902
1903template<class Val, class BV>
1905{
1906 BM_ASSERT(idx1 < this->size());
1907 BM_ASSERT(idx2 < this->size());
1908
1909 this->swap_elements(idx1, idx2);
1910}
1911
1912
1913//---------------------------------------------------------------------
1914
1915template<class Val, class BV>
1917{
1918 if (idx >= size())
1919 {
1920 this->size_ = idx+1;
1921 set_value(idx, v, false);
1922 return;
1923 }
1924 insert_value(idx, v);
1925}
1926
1927//---------------------------------------------------------------------
1928
1929template<class Val, class BV>
1931{
1932 insert_value_no_null(idx, v);
1933 this->insert_null(idx, true);
1934}
1935
1936//---------------------------------------------------------------------
1937
1938template<class Val, class BV>
1940{
1941 unsigned_value_type uv = this->s2u(v);
1942 unsigned bsr = uv ? bm::bit_scan_reverse(uv) : 0u;
1943
1944 unsigned_value_type mask = 1u;
1945 unsigned i = 0;
1946 for (; i <= bsr; ++i)
1947 {
1948 if (uv & mask)
1949 {
1950 bvector_type* bv = this->get_create_slice(i);
1951 bv->insert(idx, true);
1952 }
1953 else
1954 {
1955 if (bvector_type_ptr bv = this->bmatr_.get_row(i))
1956 bv->insert(idx, false);
1957 }
1958 mask = unsigned_value_type(mask << 1);
1959 } // for i
1960
1961 // insert 0 into all other existing planes
1962 unsigned eff_planes = this->effective_slices();
1963 BM_ASSERT(eff_planes <= (sizeof(value_type) * 8));
1964 for (; i < eff_planes; ++i)
1965 {
1966 if (bvector_type* bv = this->bmatr_.get_row(i))
1967 bv->insert(idx, false);
1968 } // for i
1969 this->size_++;
1970}
1971
1972//---------------------------------------------------------------------
1973
1974template<class Val, class BV>
1976{
1977 BM_ASSERT(idx < this->size_);
1978 if (idx >= this->size_)
1979 return;
1980 this->erase_column(idx, erase_null);
1981 this->size_ -= erase_null;
1982}
1983
1984
1985//---------------------------------------------------------------------
1986
1987template<class Val, class BV>
1989{
1990 set_value_no_null(this->size_, v, false);
1991 ++(this->size_);
1992}
1993
1994//---------------------------------------------------------------------
1995
1996template<class Val, class BV>
1998 value_type v, bool need_clear)
1999{
2000 set_value_no_null(idx, v, need_clear);
2001 if (bvector_type* bv_null = this->get_null_bvect())
2002 bv_null->set_bit_no_check(idx);
2003}
2004
2005//---------------------------------------------------------------------
2006
2007template<class Val, class BV>
2009 value_type v, bool need_clear)
2010{
2011 unsigned_value_type uv = this->s2u(v);
2012
2013 // clear the planes where needed
2014 unsigned bsr = uv ? bm::bit_scan_reverse(uv) : 0u;
2015 if (need_clear)
2016 {
2017 unsigned eff_planes = this->effective_slices();
2018 BM_ASSERT(eff_planes <= (sizeof(value_type) * 8));
2019 this->bmatr_.clear_slices_range(bsr, eff_planes, idx);
2020 }
2021 if (uv)
2022 {
2023 unsigned_value_type mask = 1u;
2024 for (unsigned j = 0; j <= bsr; ++j)
2025 {
2026 if (uv & mask)
2027 {
2028 bvector_type* bv = this->get_create_slice(j);
2029 bv->set_bit_no_check(idx);
2030 }
2031 else if (need_clear)
2032 {
2033 block_idx_type nb = (idx >> bm::set_block_shift);
2034 unsigned i0, j0;
2035 bm::get_block_coord(nb, i0, j0);
2036
2037 if (const bm::word_t* blk = this->bmatr_.get_block(j, i0, j0))
2038 {
2039 // TODO: more efficient set/clear on the block
2040 bvector_type* bv = this->bmatr_.get_row(j);
2041 bv->clear_bit_no_check(idx);
2042 }
2043 }
2044 mask <<= 1u;
2045 } // for j
2046 }
2047}
2048
2049//---------------------------------------------------------------------
2050
2051template<class Val, class BV>
2053{
2054 if (idx >= this->size_)
2055 {
2056 this->size_ = idx+1;
2057 set_value_no_null(idx, 1, false);
2058 }
2059 else
2060 inc_no_null(idx);
2061
2062 if (bvector_type* bv_null = this->get_null_bvect())
2063 bv_null->set_bit_no_check(idx);
2064}
2065
2066//---------------------------------------------------------------------
2067
2068template<class Val, class BV>
2070{
2071 if constexpr (parent_type::is_signed())
2072 {
2073 value_type v = get(idx);
2074 if (std::numeric_limits<value_type>::max() == v)
2075 v = 0;
2076 else
2077 ++v;
2078 set_value_no_null(idx, v, true);
2079 }
2080 else
2081 for (unsigned i = 0; i < parent_type::sv_value_slices; ++i)
2082 {
2083 bvector_type* bv = this->get_create_slice(i);
2084 if (bool carry_over = bv->inc(idx); !carry_over)
2085 break;
2086 } // for i
2087}
2088
2089//------------------------------------ ---------------------------------
2090
2091template<class Val, class BV>
2093{
2094 value_type v_prev = get(idx);
2095 set_value_no_null(idx, v + v_prev, true);
2096}
2097
2098//---------------------------------------------------------------------
2099
2100template<class Val, class BV>
2102{
2103 parent_type::clear_all(free_mem);
2104}
2105
2106//---------------------------------------------------------------------
2107
2108template<class Val, class BV>
2110{
2111 BM_ASSERT(rank);
2112 pos = rank - 1;
2113 return true;
2114}
2115
2116//---------------------------------------------------------------------
2117
2118template<class Val, class BV>
2122 typename sparse_vector<Val, BV>::size_type right,
2123 bool set_null)
2124{
2125 parent_type::clear_range(left, right, set_null);
2126 return *this;
2127}
2128
2129//---------------------------------------------------------------------
2130
2131template<class Val, class BV>
2134{
2135 BM_ASSERT(st);
2136 typename bvector_type::statistics stbv;
2138 if (st)
2139 {
2140 st->reset();
2141 st->add(stbv);
2142 }
2143}
2144
2145//---------------------------------------------------------------------
2146
2147template<class Val, class BV>
2149 bm::word_t* temp_block,
2150 typename bvector_type::optmode opt_mode,
2152{
2153 typename bvector_type::statistics stbv;
2154 stbv.reset();
2155 parent_type::optimize(temp_block, opt_mode, st ? &stbv : 0);
2156
2157 if (st)
2158 {
2159 st->reset();
2160 st->add(stbv);
2161 }
2162}
2163
2164//---------------------------------------------------------------------
2165
2166template<class Val, class BV>
2168{
2169 unsigned stored_slices = this->stored_slices();
2170 for (unsigned j = 0; j < stored_slices; ++j)
2171 {
2172 if (bvector_type* bv = this->bmatr_.get_row(j))
2173 bv->optimize_gap_size();
2174 }
2175}
2176
2177//---------------------------------------------------------------------
2178
2179template<class Val, class BV>
2182{
2183 size_type arg_size = sv.size();
2184 if (this->size_ < arg_size)
2185 resize(arg_size);
2186
2187 unsigned planes = (unsigned)this->bmatr_.rows();
2188 if (planes > sv.get_bmatrix().rows())
2189 --planes;
2190
2191 for (unsigned j = 0; j < planes; ++j)
2192 {
2193 if (const bvector_type* arg_bv = sv.bmatr_.row(j))
2194 {
2195 bvector_type* bv = this->get_create_slice(j);
2196 *bv |= *arg_bv;
2197 }
2198 } // for j
2199
2200 join_null_slice(sv);
2201 return *this;
2202}
2203
2204//---------------------------------------------------------------------
2205
2206template<class Val, class BV>
2209{
2210 size_type arg_size = sv.size();
2211 if (this->size_ < arg_size)
2212 resize(arg_size);
2213
2214 this->merge_matr(sv.bmatr_);
2215
2216 join_null_slice(sv);
2217
2218 return *this;
2219}
2220
2221//---------------------------------------------------------------------
2222
2223template<class Val, class BV>
2225{
2226 bvector_type* bv_null = this->get_null_bvect();
2227 size_type arg_size = sv.size();
2228
2229 // our vector is NULL-able but argument is not (assumed all values are real)
2230 if (bv_null)
2231 {
2232 if (!sv.is_nullable())
2233 bv_null->set_range(0, arg_size-1);
2234 }
2235 else // not NULL
2236 {
2237 if (sv.is_nullable())
2238 {
2239 this->bmatr_.set_null_idx(sv.bmatr_.get_null_idx());
2240 BM_ASSERT(this->get_null_bvect());
2241 }
2242 }
2243}
2244
2245
2246
2247template<class Val, class BV>
2249 const sparse_vector<Val, BV>& sv,
2251 typename sparse_vector<Val, BV>::size_type right,
2252 bm::null_support slice_null)
2253{
2254 if (left > right)
2255 bm::xor_swap(left, right);
2256 this->copy_range_slices(sv, left, right, slice_null);
2257 this->resize(sv.size());
2258}
2259
2260//---------------------------------------------------------------------
2261
2262template<class Val, class BV>
2264 bm::null_support slice_null)
2265{
2266 if (right < left)
2267 bm::xor_swap(left, right);
2268 this->keep_range_no_check(left, right, slice_null);
2269}
2270
2271
2272//---------------------------------------------------------------------
2273
2274template<class Val, class BV>
2276 const typename sparse_vector<Val, BV>::bvector_type& bv_mask)
2277{
2278 unsigned slices = (unsigned)this->get_bmatrix().rows();
2279 for (unsigned j = 0; j < slices/*planes*/; ++j)
2280 {
2281 if (bvector_type* bv = this->bmatr_.get_row(j))
2282 bv->bit_and(bv_mask);
2283 } // for j
2284}
2285
2286//---------------------------------------------------------------------
2287
2288template<class Val, class BV>
2290 const value_type val) const BMNOEXCEPT
2291{
2292 // TODO: consider bit-by-bit comparison to minimize CPU hit miss in plans get()
2293 value_type sv_value = get(idx);
2294 return (sv_value > val) - (sv_value < val);
2295}
2296
2297//---------------------------------------------------------------------
2298
2299template<class Val, class BV>
2301 bm::null_support null_able) const BMNOEXCEPT
2302{
2303 return parent_type::equal(sv, null_able);
2304}
2305
2306//---------------------------------------------------------------------
2307
2308template<class Val, class BV>
2311{
2312 typedef typename sparse_vector<Val, BV>::const_iterator it_type;
2313 return it_type(this);
2314}
2315
2316//---------------------------------------------------------------------
2317
2318template<class Val, class BV>
2321{
2322 this->bmatr_.set_allocator_pool(pool_ptr);
2323}
2324
2325
2326//---------------------------------------------------------------------
2327//
2328//---------------------------------------------------------------------
2329
2330
2331template<class Val, class BV>
2335
2336//---------------------------------------------------------------------
2337
2338template<class Val, class BV>
2341: sv_(it.sv_), pos_(it.pos_), buf_ptr_(0)
2342{}
2343
2344//---------------------------------------------------------------------
2345
2346template<class Val, class BV>
2349 ) BMNOEXCEPT
2350: sv_(sv), buf_ptr_(0)
2351{
2352 BM_ASSERT(sv_);
2353 pos_ = sv_->empty() ? bm::id_max : 0u;
2354}
2355
2356//---------------------------------------------------------------------
2357
2358template<class Val, class BV>
2362: sv_(sv), buf_ptr_(0)
2363{
2364 BM_ASSERT(sv_);
2365 this->go_to(pos);
2366}
2367
2368//---------------------------------------------------------------------
2369
2370template<class Val, class BV>
2372{
2373 pos_ = (!sv_ || pos >= sv_->size()) ? bm::id_max : pos;
2374 buf_ptr_ = 0;
2375}
2376
2377//---------------------------------------------------------------------
2378
2379template<class Val, class BV>
2381{
2382 if (pos_ == bm::id_max) // nothing to do, we are at the end
2383 return false;
2384 ++pos_;
2385 if (pos_ >= sv_->size())
2386 {
2387 this->invalidate();
2388 return false;
2389 }
2390 if (buf_ptr_)
2391 {
2392 ++buf_ptr_;
2393 if (buf_ptr_ - ((value_type*)buffer_.data()) >= n_buf_size)
2394 buf_ptr_ = 0;
2395 }
2396 return true;
2397}
2398
2399//---------------------------------------------------------------------
2400
2401template<class Val, class BV>
2404{
2405 BM_ASSERT(this->valid());
2406 value_type v;
2407
2408 if (!buf_ptr_)
2409 {
2410 buffer_.reserve(n_buf_size * sizeof(value_type));
2411 buf_ptr_ = (value_type*)(buffer_.data());
2412 sv_->extract(buf_ptr_, n_buf_size, pos_, true);
2413 }
2414 v = *buf_ptr_;
2415 return v;
2416}
2417
2418//---------------------------------------------------------------------
2419
2420template<class Val, class BV>
2422{
2423 value_type v = value();
2424 if (buf_ptr_)
2425 {
2426 v = *buf_ptr_;
2427 value_type* buf_end = ((value_type*)buffer_.data()) + n_buf_size;
2428 while(!v)
2429 {
2430 ++pos_;
2431 if (++buf_ptr_ < buf_end)
2432 v = *buf_ptr_;
2433 else
2434 break;
2435 }
2436 if (pos_ >= sv_->size())
2437 {
2438 pos_ = bm::id_max;
2439 return;
2440 }
2441 if (buf_ptr_ >= buf_end)
2442 buf_ptr_ = 0;
2443 }
2444}
2445
2446//---------------------------------------------------------------------
2447
2448template<class Val, class BV>
2450{
2451 return sv_->is_null(pos_);
2452}
2453
2454
2455//---------------------------------------------------------------------
2456//
2457//---------------------------------------------------------------------
2458
2459
2460template<class Val, class BV>
2463
2464//---------------------------------------------------------------------
2465
2466template<class Val, class BV>
2469: sv_(sv)
2470{
2471 if (sv)
2472 {
2473 prev_nb_ = sv_->size() >> bm::set_block_shift;
2474 bv_null_ = sv_->get_null_bvect();
2475 buffer_.reserve(n_buf_size * sizeof(value_type));
2476 buf_ptr_ = (unsigned_value_type*)(buffer_.data());
2477 }
2478 else
2479 {
2480 buf_ptr_ = 0; bv_null_ = 0;
2481 }
2482}
2483
2484//---------------------------------------------------------------------
2485
2486template<class Val, class BV>
2489: sv_(bi.sv_), bv_null_(bi.bv_null_), buf_ptr_(0),
2490 set_not_null_(bi.set_not_null_),
2491 prev_nb_(bi.prev_nb_), opt_mode_(bi.opt_mode_)
2492{
2493 if (sv_)
2494 {
2495 prev_nb_ = sv_->size() >> bm::set_block_shift;
2496 buffer_.reserve(n_buf_size * sizeof(value_type));
2497 buf_ptr_ = (unsigned_value_type*)(buffer_.data());
2498 }
2499}
2500
2501//---------------------------------------------------------------------
2502
2503template<class Val, class BV>
2506: sv_(bi.sv_), bv_null_(bi.bv_null_), buf_ptr_(bi.buf_ptr_),
2507 set_not_null_(bi.set_not_null_),
2508 prev_nb_(bi.prev_nb_), opt_mode_(bi.opt_mode_)
2509{
2510 buffer_.swap(bi.buffer_);
2511 buf_ptr_ = bi.buf_ptr_;
2512}
2513
2514//---------------------------------------------------------------------
2515
2516template<class Val, class BV>
2521
2522//---------------------------------------------------------------------
2523
2524template<class Val, class BV>
2527{
2528 BM_ASSERT(sv_);
2529 BM_ASSERT(buf_ptr_ && buffer_.data());
2530
2531 const unsigned_value_type* data_ptr = (const unsigned_value_type*)buffer_.data();
2532 size_type buf_idx = size_type(buf_ptr_ - data_ptr);
2533 typename sparse_vector<Val, BV>::size_type sz = sv_->size();
2534
2535 this->add_value_no_null(v);
2536
2537 if (bv_null_)
2538 {
2539 bv_null_->set_bit_no_check(sz + buf_idx);
2540 }
2541}
2542
2543//---------------------------------------------------------------------
2544
2545template<class Val, class BV>
2549{
2550 BM_ASSERT(sv_);
2551 BM_ASSERT(buf_ptr_ && buffer_.data());
2552
2555 size_type buf_idx = size_type(buf_ptr_ - (const unsigned_value_type*)buffer_.data());
2556 if (buf_idx >= n_buf_size)
2557 {
2558 this->flush();
2559 buf_ptr_ = (unsigned_value_type*)(buffer_.data());
2560 }
2561 *buf_ptr_++ = uv;
2562}
2563
2564//---------------------------------------------------------------------
2565
2566template<class Val, class BV>
2572
2573//---------------------------------------------------------------------
2574
2575template<class Val, class BV>
2578{
2579 if (count < 32)
2580 {
2581 for (size_type i = 0; i < count; ++i)
2582 this->add_value_no_null(value_type(0));
2583 }
2584 else
2585 {
2586 this->flush();
2587 sv_->push_back_null(count);
2588 }
2589}
2590
2591//---------------------------------------------------------------------
2592
2593template<class Val, class BV>
2595{
2596 return (!sv_ || (buf_ptr_ == (unsigned_value_type*)buffer_.data()));
2597}
2598
2599//---------------------------------------------------------------------
2600
2601template<class Val, class BV>
2603{
2604 if (!sv_)
2605 return false;
2606 unsigned_value_type* arr = (unsigned_value_type*)buffer_.data();
2607 size_type arr_size = size_type(buf_ptr_ - arr);
2608 if (!arr_size)
2609 return false;
2610 sv_->import_back_u(arr, arr_size, false);
2611 buf_ptr_ = (unsigned_value_type*) buffer_.data();
2612 block_idx_type nb = sv_->size() >> bm::set_block_shift;
2613 if (nb != prev_nb_)
2614 {
2615 sv_->optimize_block(prev_nb_, opt_mode_);
2616 prev_nb_ = nb;
2617 }
2618 return true;
2619}
2620
2621//---------------------------------------------------------------------
2622
2623
2624} // namespace bm
2625
2626
2627
2628#endif
Algorithms for bvector<>.
basic bit-matrix class and utilities
Definitions(internal).
#define IS_FULL_BLOCK(addr)
Definition bmdef.h:162
#define BMRESTRICT
Definition bmdef.h:203
#define BMNOEXCEPT
Definition bmdef.h:82
#define BMGAP_PTR(ptr)
Definition bmdef.h:189
#define BM_IS_GAP(ptr)
Definition bmdef.h:191
#define BMFORCEINLINE
Definition bmdef.h:213
#define BM_ASSERT
Definition bmdef.h:139
#define BM_ASSERT_THROW(x, xerrcode)
Definition bmdef.h:338
#define FULL_BLOCK_FAKE_ADDR
Definition bmdef.h:158
#define BMNOEXCEPT2
Definition bmdef.h:85
Utilities for bit transposition (internal) (experimental!).
void swap(base_sparse_vector< Val, BV, MAX_SIZE > &bsv) BMNOEXCEPT
void resize(size_type new_size, bool set_null)
unsigned effective_slices() const BMNOEXCEPT
Definition bmbmatrix.h:514
void merge_matr(bmatrix_type &bmatr)
static unsigned slices() BMNOEXCEPT
Definition bmbmatrix.h:503
static value_type u2s(unsigned_value_type v) BMNOEXCEPT
const bvector_type * get_null_bvector() const BMNOEXCEPT
Definition bmbmatrix.h:451
void copy_from(const base_sparse_vector< Val, BV, MAX_SIZE > &bsv)
static unsigned_value_type s2u(value_type v) BMNOEXCEPT
void clear_range(size_type left, size_type right, bool set_null)
bvector_type_ptr get_create_slice(unsigned i)
void erase_column(size_type idx, bool erase_null)
void swap_elements(size_type idx1, size_type idx2)
Definition bmbmatrix.h:420
bool is_ro_
read-only
Definition bmbmatrix.h:705
void copy_range_slices(const base_sparse_vector< Val, BV, MAX_SIZE > &bsv, typename base_sparse_vector< Val, BV, MAX_SIZE >::size_type left, typename base_sparse_vector< Val, BV, MAX_SIZE >::size_type right, bm::null_support slice_null)
static unsigned stored_slices() BMNOEXCEPT
Definition bmbmatrix.h:508
static constexpr unsigned value_bits() BMNOEXCEPT
Definition bmbmatrix.h:678
bool is_null(size_type idx) const BMNOEXCEPT
size_type size_
array size
Definition bmbmatrix.h:703
void keep_range_no_check(size_type left, size_type right, bm::null_support slice_null)
std::make_unsigned< value_type >::type unsigned_value_type
Definition bmbmatrix.h:376
const bmatrix_type & get_bmatrix() const BMNOEXCEPT
Definition bmbmatrix.h:553
bvector_type * get_null_bvect() BMNOEXCEPT
Definition bmbmatrix.h:525
void bit_sub_rows(const bvector_type &bv, bool use_null)
Definition bmbmatrix.h:665
void clear_all(bool free_mem=true) BMNOEXCEPT
static constexpr bool is_signed() BMNOEXCEPT
Definition bmbmatrix.h:433
void optimize(bm::word_t *temp_block=0, typename bvector_type::optmode opt_mode=bvector_type::opt_compress, typename bvector_type::statistics *stat=0)
void insert_null(size_type idx, bool not_null)
void calc_stat(typename bvector_type::statistics *st) const BMNOEXCEPT
bool is_nullable() const BMNOEXCEPT
Definition bmbmatrix.h:439
bool equal(const base_sparse_vector< Val, BV, MAX_SIZE > &sv, bm::null_support null_able=bm::use_null) const BMNOEXCEPT
Basic dense bit-matrix class.
Definition bmbmatrix.h:56
size_type get_null_idx() const BMNOEXCEPT
return index of the NULL vector
Definition bmbmatrix.h:162
const bvector_type * row(size_type i) const BMNOEXCEPT
Definition bmbmatrix.h:767
size_type rows() const BMNOEXCEPT
Definition bmbmatrix.h:140
Constant iterator designed to enumerate "ON" bits.
Definition bm.h:603
optmode
Optimization mode Every next level means additional checks (better compression vs time).
Definition bm.h:133
@ opt_compress
compress blocks when possible (GAP/prefix sum)
Definition bm.h:137
allocator_type::allocator_pool_type allocator_pool_type
Definition bm.h:118
bvector_size_type size_type
Definition bm.h:121
blocks_manager_type::block_idx_type block_idx_type
Definition bm.h:120
Alloc allocator_type
Definition bm.h:117
void add_null(size_type count)
add a series of consequitve NULLs (no-value) to the container
bm::byte_buffer< allocator_type > buffer_type
bvector_type::allocator_type::allocator_pool_type allocator_pool_type
void operator=(value_type v)
push value to the vector
bvector_type::block_idx_type block_idx_type
void operator=(const back_insert_iterator &bi)
sparse_vector_type::unsigned_value_type unsigned_value_type
back_insert_iterator & operator++()
noop
sparse_vector_type::size_type size_type
bool flush()
flush the accumulated buffer
bvector_type * get_null_bvect() const BMNOEXCEPT
Get access to not-null vector.
back_insert_iterator & operator++(int)
noop
back_insert_iterator(back_insert_iterator &&bi) BMNOEXCEPT
move constructor
back_insert_iterator(const back_insert_iterator &bi)
void add(value_type v)
add value to the container
void disable_set_null() BMNOEXCEPT
Reconfigure back inserter not to touch the NULL vector.
bool empty() const
return true if insertion buffer is empty
sparse_vector_type * sparse_vector_type_ptr
back_insert_iterator(sparse_vector_type *sv)
bvector_type::allocator_type allocator_type
back_insert_iterator & operator*()
noop
sparse_vector< Val, BV > sparse_vector_type
std::output_iterator_tag iterator_category
sparse_vector_type::value_type value_type
sparse_vector_type::bvector_type bvector_type
Const iterator to traverse the sparse vector.
const_iterator & operator++() BMNOEXCEPT
Advance to the next available value.
void go_to(size_type pos) BMNOEXCEPT
re-position to a specified position
std::input_iterator_tag iterator_category
bool operator==(const const_iterator &it) const BMNOEXCEPT
bool operator>(const const_iterator &it) const BMNOEXCEPT
bvector_type::allocator_type allocator_type
sparse_vector< Val, BV > sparse_vector_type
bool is_null() const BMNOEXCEPT
Get NULL status.
bool advance() BMNOEXCEPT
advance iterator forward by one
value_type operator*() const
Get current position (value).
sparse_vector_type::bvector_type bvector_type
bool operator!=(const const_iterator &it) const BMNOEXCEPT
bool operator<(const const_iterator &it) const BMNOEXCEPT
const_iterator operator++(int)
Advance to the next available value.
bool operator<=(const const_iterator &it) const BMNOEXCEPT
bool valid() const BMNOEXCEPT
Returns true if iterator is at a valid position.
bm::byte_buffer< allocator_type > buffer_type
void invalidate() BMNOEXCEPT
Invalidate current iterator.
value_type value() const
Get current position (value).
sparse_vector_type::size_type size_type
size_type pos() const BMNOEXCEPT
Current position (index) in the vector.
sparse_vector_type * sparse_vector_type_ptr
sparse_vector_type::value_type value_type
bvector_type::allocator_type::allocator_pool_type allocator_pool_type
bool operator>=(const const_iterator &it) const BMNOEXCEPT
bool operator==(const reference &ref) const BMNOEXCEPT
bool is_null() const BMNOEXCEPT
reference & operator=(const reference &ref)
reference & operator=(value_type val)
reference(sparse_vector< Val, BV > &sv, size_type idx) BMNOEXCEPT
succinct sparse vector with runtime compression using bit-slicing / transposition method
Definition bmsparsevec.h:87
void inc(size_type idx)
increment specified element by one
unsigned_value_type get_unsigned_bits(size_type idx, size_type N_bits) const BMNOEXCEPT
Get raw unsigned value first N bits.
bvector_type::size_type size_type
Definition bmsparsevec.h:92
void set_value(size_type idx, value_type v, bool need_clear)
set value without checking boundaries
value_type at(size_type idx) const
access specified element with bounds checking
void set_value_no_null(size_type idx, value_type v, bool need_clear)
set value without checking boundaries or support of NULL
value_type get(size_type idx) const BMNOEXCEPT
get specified element without bounds checking
allocator_type::allocator_pool_type allocator_pool_type
Definition bmsparsevec.h:99
void insert_value_no_null(size_type idx, value_type v)
insert value without checking boundaries or support of NULL
static constexpr bool is_str() BMNOEXCEPT
bool equal(const sparse_vector< unsigned, bm::bvector<> > &sv, bm::null_support null_able=bm::use_null) const BMNOEXCEPT
void sync(bool)
syncronize internal structures, build fast access index
const value_type & const_reference
Definition bmsparsevec.h:95
void push_back(value_type v)
push value back into vector
void sync_size() BMNOEXCEPT
recalculate size to exclude tail NULL elements After this call size() will return the true size of th...
size_type size_internal() const BMNOEXCEPT
void push_back_no_null(value_type v)
push value back into vector without NULL semantics
void insert_value(size_type idx, value_type v)
insert value without checking boundaries
unsigned_value_type get_unsigned(size_type idx) const BMNOEXCEPT
get raw unsigned value
bvector_type * bvector_type_ptr
Definition bmsparsevec.h:91
const remap_matrix_type * get_remap_matrix() const
unsigned char * init_remap_buffer() BMNOEXCEPT
void set_remap() BMNOEXCEPT
void clear_all(bool free_mem, unsigned) BMNOEXCEPT
resize to zero, free memory
sparse_vector(const sparse_vector< Val, BV > &sv)
sparse_vector(sparse_vector< Val, BV > &&sv) BMNOEXCEPT
bvector_type::enumerator bvector_enumerator_type
Definition bmsparsevec.h:98
void set(size_type idx, value_type v)
set specified element with bounds checking and automatic resize
void resize(size_type sz)
resize vector
bool try_get(size_type idx, value_type &v) const BMNOEXCEPT
get specified element with NOT NULL check
size_t remap_size() const BMNOEXCEPT
void clear(size_type idx, bool set_null)
clear specified element with bounds checking and automatic resize
static void throw_range_error(const char *err_msg)
throw range error
const_iterator end() const BMNOEXCEPT
back_insert_iterator get_back_inserter()
Provide back insert iterator Back insert iterator implements buffered insertion, which is faster,...
void resize_internal(size_type sz, bool set_null=true)
static constexpr bool is_compressed() BMNOEXCEPT
various type traits
constexpr bool is_remap() const BMNOEXCEPT
void inc_no_null(size_type idx, value_type v)
increment by v without chnaging NULL vector or size
bool resolve_range(size_type from, size_type to, size_type *idx_from, size_type *idx_to) const BMNOEXCEPT
void swap(size_type idx1, size_type idx2)
swap two vector elements between each other
friend back_insert_iterator
bvector_type::block_idx_type block_idx_type
Definition bmsparsevec.h:93
void import_u_nocheck(const unsigned_value_type *arr, size_type arr_size, size_type offset, bool set_not_null)
void inc_no_null(size_type idx)
Increment element by 1 without chnaging NULL vector or size.
size_type gather(value_type *arr, const size_type *idx, size_type size, bm::sort_order sorted_idx) const
Gather elements to a C-style array.
void push_back_null(size_type count)
push back specified amount of NULL values
sparse_vector< Val, BV > & merge(sparse_vector< Val, BV > &sv)
merge with another sparse vector using OR operation Merge is different from join(),...
const unsigned char * get_remap_buffer() const BMNOEXCEPT
int compare(size_type idx, const value_type val) const BMNOEXCEPT
bool empty() const BMNOEXCEPT
return true if vector is empty
~sparse_vector() BMNOEXCEPT
static bool find_rank(size_type rank, size_type &pos) BMNOEXCEPT
find position of compressed element by its rank
sparse_vector< Val, BV > & operator=(const sparse_vector< Val, BV > &sv)
void swap(sparse_vector< Val, BV > &sv) BMNOEXCEPT
content exchange
void set_null(const bvector_type &bv_idx)
Set NULL all elements set as 1 in the argument vector.
bm::heap_matrix< unsigned char, sizeof(value_type), 256, typename bvector_type::allocator_type > remap_matrix_type
unused remap matrix type for compatibility with the sparse serializer
remap_matrix_type * get_remap_matrix()
sparse_vector< Val, BV > & join(const sparse_vector< Val, BV > &sv)
join all with another sparse vector using OR operation
static size_type translate_address(size_type i) BMNOEXCEPT
void insert(size_type idx, value_type v)
insert specified element into container
void import_back(const value_type *arr, size_type arr_size, bool set_not_null=true)
Import list of elements from a C-style array (pushed back).
base_sparse_vector< Val, BV, 1 > parent_type
size_type extract_range(value_type *arr, size_type size, size_type offset, bool zero_mem=true) const
void calc_stat(struct sparse_vector< unsigned, bm::bvector<> >::statistics *st) const BMNOEXCEPT
size_type extract_planes(value_type *arr, size_type size, size_type offset, bool zero_mem=true) const
static void throw_bad_alloc()
throw bad alloc
void keep_range(size_type left, size_type right, bm::null_support slice_null=bm::use_null)
Keep only specified interval in the sparse vector, clear all other elements.
void import_u(const unsigned_value_type *arr, size_type arr_size, size_type offset, bool set_not_null)
Import list of elements from a C-style array.
void join_null_slice(const sparse_vector< Val, BV > &sv)
BV::allocator_type allocator_type
Definition bmsparsevec.h:96
sparse_vector(bm::null_support null_able=bm::no_null, allocation_policy_type ap=allocation_policy_type(), size_type bv_max_size=bm::id_max, const allocator_type &alloc=allocator_type())
Sparse vector constructor.
void push_back_null()
push back NULL value
sparse_vector< Val, BV > & clear_range(size_type left, size_type right, bool set_null=false)
clear range (assign bit 0 for all planes)
void erase(size_type idx, bool erase_null=true)
erase specified element from container
size_type effective_size() const BMNOEXCEPT
size of sparse vector (may be different for RSC)
void clear() BMNOEXCEPT
resize to zero, free memory
size_type decode(value_type *arr, size_type idx_from, size_type dec_size, bool zero_mem=true) const
Bulk export list of elements to a C-style array.
value_type get_no_check(size_type idx) const BMNOEXCEPT
get specified element without checking boundary conditions
bm::basic_bmatrix< BV > bmatrix_type
void clear(const bvector_type &bv_idx)
Set vector elements spcified by argument bit-vector to zero Note that set to 0 elements are NOT going...
size_type extract(value_type *arr, size_type size, size_type offset=0, bool zero_mem=true) const BMNOEXCEPT2
Bulk export list of elements to a C-style array.
size_type effective_vector_max() const BMNOEXCEPT
Always 1 (non-matrix type).
void copy_range(const sparse_vector< Val, BV > &sv, size_type left, size_type right, bm::null_support slice_null=bm::use_null)
copy range of values from another sparse vector
const_iterator get_const_iterator(size_type idx) const BMNOEXCEPT
Get const_itertor re-positioned to specific element.
parent_type::unsigned_value_type unsigned_value_type
const_iterator begin() const BMNOEXCEPT
Provide const iterator access to container content.
bvector_type::allocation_policy allocation_policy_type
Definition bmsparsevec.h:97
void import(const value_type *arr, size_type arr_size, size_type offset=0, bool set_not_null=true)
Import list of elements from a C-style array.
void import_back_u(const unsigned_value_type *arr, size_type arr_size, bool set_not_null=true)
Import list of elements from a C-style array (pushed back).
static void u2s_translate(value_type *arr, size_type sz) BMNOEXCEPT
void filter(const bvector_type &bv_mask)
Apply value filter, defined by mask vector.
const bvector_type * bvector_type_const_ptr
Definition bmsparsevec.h:94
bool is_ro() const BMNOEXCEPT
Returns true if vector is read-only.
void set_allocator_pool(allocator_pool_type *pool_ptr) BMNOEXCEPT
Set allocator pool for local (non-threaded) memory cyclic(lots of alloc-free ops) opertations.
value_type operator[](size_type idx) const BMNOEXCEPT
get specified element without bounds checking
void optimize(bm::word_t *temp_block=0, typename bvector_type::optmode opt_mode=bvector_type::opt_compress, typename sparse_vector< unsigned, bm::bvector<> >::statistics *stat=0)
unsigned short bitscan(V w, B *bits) BMNOEXCEPT
Templated Bitscan with dynamic dispatch for best type.
Definition bmfunc.h:769
void bit_block_gather_scatter(unsigned *BMRESTRICT arr, const bm::word_t *BMRESTRICT blk, const unsigned *BMRESTRICT idx, unsigned size, unsigned start, unsigned bit_idx) BMNOEXCEPT
bit index to word gather-scatter algorithm (SIMD)
Definition bmfunc.h:9679
unsigned bit_scan_reverse(T value) BMNOEXCEPT
Definition bmutil.h:453
sort_order
Sort order declaration.
Definition bmconst.h:204
null_support
NULL-able value support.
Definition bmconst.h:229
@ BM_UNSORTED
input set is NOT sorted
Definition bmconst.h:205
@ BM_SORTED
input set is sorted (ascending order)
Definition bmconst.h:206
@ BM_UNKNOWN
sort order unknown
Definition bmconst.h:208
@ BM_SORTED_UNIFORM
sorted and in one block (internal!)
Definition bmconst.h:207
@ use_null
support "non-assigned" or "NULL" logic
Definition bmconst.h:230
@ no_null
do not support NULL values
Definition bmconst.h:231
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:1833
Definition bm.h:78
const unsigned id_max
Definition bmconst.h:109
unsigned int word_t
Definition bmconst.h:39
int for_each_bit_range_no_check(const BV &bv, typename BV::size_type left, typename BV::size_type right, Func &bit_functor)
Implementation of for_each_bit_range without boilerplave checks.
const unsigned set_block_mask
Definition bmconst.h:57
unsigned gap_bfind(const T *BMRESTRICT buf, unsigned pos, unsigned *BMRESTRICT is_set) BMNOEXCEPT
Definition bmfunc.h:1725
BMFORCEINLINE void get_block_coord(BI_TYPE nb, unsigned &i, unsigned &j) BMNOEXCEPT
Recalc linear bvector block index into 2D matrix coordinates.
Definition bmfunc.h:180
const unsigned set_word_shift
Definition bmconst.h:72
BMFORCEINLINE void xor_swap(W &x, W &y) BMNOEXCEPT
XOR swap two variables.
Definition bmutil.h:534
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:9755
unsigned idx_arr_block_lookup_u32(const unsigned *idx, unsigned size, unsigned nb, unsigned start) BMNOEXCEPT
block boundaries look ahead U32
Definition bmfunc.h:9781
unsigned short gap_word_t
Definition bmconst.h:78
const unsigned set_block_shift
Definition bmconst.h:56
const unsigned set_word_mask
Definition bmconst.h:73
bv_statistics() BMNOEXCEPT
Definition bmfunc.h:67
void reset() BMNOEXCEPT
Reset statisctics.
Definition bmfunc.h:94
void add(const bv_statistics &st) BMNOEXCEPT
Sum data from another sttructure.
Definition bmfunc.h:103
memory allocation policy
Definition bm.h:805
Statistical information about bitset's memory allocation details.
Definition bm.h:125
Mini-matrix for bit transposition purposes.
Definition bmtrans.h:41
static unsigned rows() BMNOEXCEPT
Definition bmtrans.h:61
const T * row(unsigned row_idx) const BMNOEXCEPT
Definition bmtrans.h:64