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
304 ~~back_insert_iterator();
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*/
319 void add(value_type v);
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 */
349 void add_value_no_null(value_type v);
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
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);
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 */
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 \brief clear specified element with bounds checking and automatic resize
522 \param idx - element index
523 \param set_null - if true the value receives NULL (unassigned) value
524 */
525 void clear(size_type idx, bool set_null/* = false*/);
526
527 /** \brief set specified element to unassigned value (NULL)
528 \param idx - element index
529 */
531
532 /**
533 Set NULL all elements set as 1 in the argument vector.
534 Function also clears all the values to 0.
535 \param bv_idx - index bit-vector for elements which to be set to NULL
536 */
537 void set_null(const bvector_type& bv_idx)
538 { this->bit_sub_rows(bv_idx, true); }
539
540 /**
541 Set vector elements spcified by argument bit-vector to zero
542 Note that set to 0 elements are NOT going to tuned to NULL (NULL qualifier is preserved)
543 \param bv_idx - index bit-vector for elements which to be set to 0
544 */
545 void clear(const bvector_type& bv_idx)
546 { this->bit_sub_rows(bv_idx, false); }
547
548
549 ///@}
550
551 // ------------------------------------------------------------
552 /*! @name Iterator access */
553 ///@{
554
555 /** Provide const iterator access to container content */
557
558 /** Provide const iterator access to the end */
560 { return const_iterator(this, bm::id_max); }
561
562 /** Get const_itertor re-positioned to specific element
563 @param idx - position in the sparse vector
564 */
566 { return const_iterator(this, idx); }
567
568 /** Provide back insert iterator
569 Back insert iterator implements buffered insertion,
570 which is faster, than random access or push_back
571 */
573 { return back_insert_iterator(this); }
574 ///@}
575
576
577 // ------------------------------------------------------------
578 /*! @name Various traits */
579 ///@{
580
581 /** \brief various type traits
582 */
583 static constexpr
584 bool is_compressed() BMNOEXCEPT { return false; }
585
586 static constexpr
587 bool is_str() BMNOEXCEPT { return false; }
588
589 ///@}
590
591
592 // ------------------------------------------------------------
593 /*! @name Loading of sparse vector from C-style array */
594 ///@{
595
596 /*!
597 \brief Import list of elements from a C-style array
598 \param arr - source array
599 \param arr_size - source size
600 \param offset - target index in the sparse vector
601 \param set_not_null - import should register in not null vector
602 */
603 void import(const value_type* arr,
604 size_type arr_size,
605 size_type offset = 0,
606 bool set_not_null = true);
607
608 /*!
609 \brief Import list of elements from a C-style array (pushed back)
610 \param arr - source array
611 \param arr_size - source array size
612 \param set_not_null - import should register in not null vector
613 */
614 void import_back(const value_type* arr,
615 size_type arr_size,
616 bool set_not_null = true);
617 ///@}
618
619 // ------------------------------------------------------------
620 /*! @name Export content to C-style array */
621 ///@{
622
623 /*!
624 \brief Bulk export list of elements to a C-style array
625
626 For efficiency, this is left as a low level function,
627 it does not do any bounds checking on the target array, it will
628 override memory and crash if you are not careful with allocation
629 and request size.
630
631 \param arr - dest array
632 \param idx_from - index in the sparse vector to export from
633 \param dec_size - decoding size (array allocation should match)
634 \param zero_mem - set to false if target array is pre-initialized
635 with 0s to avoid performance penalty
636
637 \return number of actually exported elements (can be less than requested)
638
639 \sa gather
640 */
642 size_type idx_from,
643 size_type dec_size,
644 bool zero_mem = true) const;
645
646
647 /*!
648 \brief Gather elements to a C-style array
649
650 Gather collects values from different locations, for best
651 performance feed it with sorted list of indexes.
652
653 Faster than one-by-one random access.
654
655 For efficiency, this is left as a low level function,
656 it does not do any bounds checking on the target array, it will
657 override memory and crash if you are not careful with allocation
658 and request size.
659
660 \param arr - dest array
661 \param idx - index list to gather elements
662 \param size - decoding index list size (array allocation should match)
663 \param sorted_idx - sort order directive for the idx array
664 (BM_UNSORTED, BM_SORTED, BM_UNKNOWN)
665 Sort order affects both performance and correctness(!), use BM_UNKNOWN
666 if not sure.
667
668 \return number of actually exported elements (can be less than requested)
669
670 \sa decode
671 */
673 const size_type* idx,
675 bm::sort_order sorted_idx) const;
676 ///@}
677
678 /*! \brief content exchange
679 */
681
682 // ------------------------------------------------------------
683 /*! @name Clear */
684 ///@{
685
686 /*! \brief resize to zero, free memory */
687 void clear_all(bool free_mem) BMNOEXCEPT;
688
689 /*! \brief resize to zero, free memory */
690 void clear() BMNOEXCEPT { clear_all(true); }
691
692 /*!
693 \brief clear range (assign bit 0 for all planes)
694 \param left - interval start
695 \param right - interval end (closed interval)
696 \param set_null - set cleared values to unassigned (NULL)
697 */
699 size_type right,
700 bool set_null = false);
701
702 ///@}
703
704 // ------------------------------------------------------------
705 /*! @name Size, etc */
706 ///@{
707
708 /*! \brief return size of the vector
709 \return size of sparse vector
710 */
711 size_type size() const BMNOEXCEPT { return this->size_; }
712
713 /*! \brief return true if vector is empty
714 \return true if empty
715 */
716 bool empty() const BMNOEXCEPT { return (size() == 0); }
717
718 /*! \brief resize vector
719 \param sz - new size
720 */
721 void resize(size_type sz) { parent_type::resize(sz, true); }
722
723 /**
724 \brief recalculate size to exclude tail NULL elements
725 After this call size() will return the true size of the vector
726 */
728
729 ///@}
730
731 // ------------------------------------------------------------
732 /*! @name Comparison */
733 ///@{
734
735 /*!
736 \brief check if another sparse vector has the same content and size
737
738 \param sv - sparse vector for comparison
739 \param null_able - flag to consider NULL vector in comparison (default)
740 or compare only value content planes
741
742 \return true, if it is the same
743 */
744 bool equal(const sparse_vector<Val, BV>& sv,
745 bm::null_support null_able = bm::use_null) const BMNOEXCEPT;
746
747 ///@}
748
749 // ------------------------------------------------------------
750 /*! @name Element comparison */
751 ///@{
752
753 /**
754 \brief Compare vector element with argument
755
756 \param idx - vactor element index
757 \param val - argument to compare with
758
759 \return 0 - equal, < 0 - vect[i] < val, >0 otherwise
760 */
761 int compare(size_type idx, const value_type val) const BMNOEXCEPT;
762
763 ///@}
764
765 // ------------------------------------------------------------
766 /*! @name Memory optimization */
767 ///@{
768
769 /*!
770 \brief run memory optimization for all vector planes
771 \param temp_block - pre-allocated memory block to avoid unnecessary re-allocs
772 \param opt_mode - requested compression depth
773 \param stat - memory allocation statistics after optimization
774 */
775 void optimize(bm::word_t* temp_block = 0,
776 typename bvector_type::optmode opt_mode = bvector_type::opt_compress,
777 typename sparse_vector<Val, BV>::statistics* stat = 0);
778
779 /*!
780 \brief Optimize sizes of GAP blocks
781
782 This method runs an analysis to find optimal GAP levels for all bit planes
783 of the vector.
784 */
786
787 /*!
788 @brief Calculates memory statistics.
789
790 Function fills statistics structure containing information about how
791 this vector uses memory and estimation of max. amount of memory
792 bvector needs to serialize itself.
793
794 @param st - pointer on statistics structure to be filled in.
795
796 @sa statistics
797 */
799 struct sparse_vector<Val, BV>::statistics* st) const BMNOEXCEPT;
800
801 /**
802 @brief Turn sparse vector into immutable mode
803 Read-only (immutable) vector uses less memory and allows faster searches.
804 Before freezing it is recommenede to call optimize() to get full memory saving effect
805 @sa optimize
806 */
807 void freeze() { this->freeze_matr(); }
808
809 /** Returns true if vector is read-only */
810 bool is_ro() const BMNOEXCEPT { return this->is_ro_; }
811
812 ///@}
813
814 // ------------------------------------------------------------
815 /*! @name Merge, split, partition data */
816 ///@{
817
818 /*!
819 \brief join all with another sparse vector using OR operation
820 \param sv - argument vector to join with
821 \return slf reference
822 @sa merge
823 */
825
826 /*!
827 \brief merge with another sparse vector using OR operation
828 Merge is different from join(), because it borrows data from the source
829 vector, so it gets modified.
830
831 \param sv - [in, out]argument vector to join with (vector mutates)
832
833 \return slf reference
834 @sa join
835 */
837
838
839 /**
840 @brief copy range of values from another sparse vector
841
842 Copy [left..right] values from the source vector,
843 clear everything outside the range.
844
845 \param sv - source vector
846 \param left - index from in losed diapason of [left..right]
847 \param right - index to in losed diapason of [left..right]
848 \param slice_null - "use_null" copy range for NULL vector or
849 do not copy it
850 */
852 size_type left, size_type right,
853 bm::null_support slice_null = bm::use_null);
854
855
856 /**
857 Keep only specified interval in the sparse vector, clear all other
858 elements.
859
860 \param left - interval start
861 \param right - interval end (closed interval)
862 \param slice_null - "use_null" copy range for NULL vector or not
863 */
865 bm::null_support slice_null = bm::use_null);
866
867 /**
868 @brief Apply value filter, defined by mask vector
869
870 All bit-planes are ANDed against the filter mask.
871 */
872 void filter(const bvector_type& bv_mask);
873
874 ///@}
875
876
877 // ------------------------------------------------------------
878 /*! @name Access to internals */
879 ///@{
880
881
882 /*! \brief syncronize internal structures, build fast access index
883 */
884 void sync(bool /*force*/) {}
885
886
887 /*!
888 \brief Bulk export list of elements to a C-style array
889
890 Use of all extract() methods is restricted.
891 Please consider decode() for the same purpose.
892
893 \param arr - dest array
894 \param size - dest size
895 \param offset - target index in the sparse vector to export from
896 \param zero_mem - set to false if target array is pre-initialized
897 with 0s to avoid performance penalty
898 \return effective size(number) of exported elements
899
900 \sa decode
901
902 @internal
903 */
906 size_type offset = 0,
907 bool zero_mem = true) const BMNOEXCEPT2;
908
909 /** \brief extract small window without use of masking vector
910 \sa decode
911 @internal
912 */
915 size_type offset,
916 bool zero_mem = true) const;
917
918 /** \brief extract medium window without use of masking vector
919 \sa decode
920 @internal
921 */
924 size_type offset,
925 bool zero_mem = true) const;
926
927 /** \brief address translation for this type of container
928 \internal
929 */
930 static
932
933 /**
934 \brief throw range error
935 \internal
936 */
937 static
938 void throw_range_error(const char* err_msg);
939
940 /**
941 \brief throw bad alloc
942 \internal
943 */
944 static
946
947
948 /**
949 \brief find position of compressed element by its rank
950 */
951 static
953
954 /**
955 \brief size of sparse vector (may be different for RSC)
956 */
958
959 /**
960 \brief Always 1 (non-matrix type)
961 */
963
964 ///@}
965
966 /// Set allocator pool for local (non-threaded)
967 /// memory cyclic(lots of alloc-free ops) opertations
968 ///
970
971protected:
973 {
975 };
977 {
978 n_buf_size = 1024 * 8
979 };
980
981
982 /*! \brief set value without checking boundaries */
983 void set_value(size_type idx, value_type v, bool need_clear);
984
985 /*! \brief set value without checking boundaries or support of NULL
986 @param idx - element index
987 @param v - value to set
988 @param need_clear - if clear 0 bits is necessary
989 (or not if vector is resized)
990 */
991 void set_value_no_null(size_type idx, value_type v, bool need_clear);
992
993 /*! \brief push value back into vector without NULL semantics */
995
996 /*! \brief insert value without checking boundaries */
998 /*! \brief insert value without checking boundaries or support of NULL */
1000
1004
1005 constexpr bool is_remap() const BMNOEXCEPT { return false; }
1006 size_t remap_size() const BMNOEXCEPT { return 0; }
1007 const unsigned char* get_remap_buffer() const BMNOEXCEPT { return 0; }
1008 unsigned char* init_remap_buffer() BMNOEXCEPT { return 0; }
1010
1011 /// unused remap matrix type for compatibility with the sparse serializer
1012 typedef
1013 bm::heap_matrix<unsigned char,
1014 sizeof(value_type), /* ROWS */
1015 256, /* COLS = number of chars in the ASCII set */
1018
1019 const remap_matrix_type* get_remap_matrix() const { return 0; }
1021
1023 size_type* idx_from, size_type* idx_to) const BMNOEXCEPT
1024 {
1025 *idx_from = from; *idx_to = to; return true;
1026 }
1027
1028 /// Increment element by 1 without chnaging NULL vector or size
1030
1031 /// increment by v without chnaging NULL vector or size
1033
1034 /*!
1035 \brief Import list of elements from a C-style array (pushed back)
1036 \param arr - source array
1037 \param arr_size - source array size
1038 \param set_not_null - import should register in not null vector
1039 */
1041 size_type arr_size,
1042 bool set_not_null = true);
1043
1044 /*!
1045 \brief Import list of elements from a C-style array
1046 \param arr - source array
1047 \param arr_size - source size
1048 \param offset - target index in the sparse vector
1049 \param set_not_null - import should register in not null vector
1050 */
1052 size_type arr_size, size_type offset,
1053 bool set_not_null);
1054
1056 size_type arr_size, size_type offset,
1057 bool set_not_null);
1058
1060
1061 static
1063
1064 // get raw unsigned value
1066
1067protected:
1068 template<class V, class SV> friend class rsc_sparse_vector;
1069 template<class SVect> friend class sparse_vector_scanner;
1070 template<class SVect> friend class sparse_vector_serializer;
1071 template<class SVect> friend class sparse_vector_deserializer;
1072
1073
1074};
1075
1076
1077//---------------------------------------------------------------------
1078//---------------------------------------------------------------------
1079
1080
1081template<class Val, class BV>
1083 bm::null_support null_able,
1085 size_type bv_max_size,
1086 const allocator_type& alloc)
1087: parent_type(null_able, ap, bv_max_size, alloc)
1088{}
1089
1090//---------------------------------------------------------------------
1091
1092template<class Val, class BV>
1094: parent_type(sv)
1095{}
1096
1097//---------------------------------------------------------------------
1098#ifndef BM_NO_CXX11
1099
1100template<class Val, class BV>
1102{
1103 parent_type::swap(sv);
1104}
1105
1106#endif
1107
1108
1109//---------------------------------------------------------------------
1110
1111template<class Val, class BV>
1113{}
1114
1115//---------------------------------------------------------------------
1116
1117template<class Val, class BV>
1119{
1120 parent_type::swap(sv);
1121}
1122
1123//---------------------------------------------------------------------
1124
1125template<class Val, class BV>
1127{
1128#ifndef BM_NO_STL
1129 throw std::range_error(err_msg);
1130#else
1131 BM_ASSERT_THROW(false, BM_ERR_RANGE);
1132#endif
1133}
1134
1135//---------------------------------------------------------------------
1136
1137template<class Val, class BV>
1139{
1140 BV::throw_bad_alloc();
1141}
1142
1143//---------------------------------------------------------------------
1144
1145template<class Val, class BV>
1147{
1148 clear(idx, true);
1149}
1150
1151//---------------------------------------------------------------------
1152
1153template<class Val, class BV>
1155 size_type arr_size,
1156 size_type offset,
1157 bool set_not_null)
1158{
1159 if constexpr (std::is_signed<value_type>::value)
1160 {
1161 const unsigned tmp_size = 1024;
1162 unsigned_value_type arr_tmp[tmp_size];
1163 size_type k(0), i(0);
1164 while (i < arr_size)
1165 {
1166 arr_tmp[k++] = this->s2u(arr[i++]);
1167 if (k == tmp_size)
1168 {
1169 import_u(arr_tmp, k, offset, set_not_null);
1170 k = 0; offset += tmp_size;
1171 }
1172 } // while
1173 if (k)
1174 {
1175 import_u(arr_tmp, k, offset, set_not_null);
1176 }
1177 }
1178 else
1179 {
1180 import_u((const unsigned_value_type*) arr, arr_size, offset, set_not_null);
1181 }
1182}
1183
1184//---------------------------------------------------------------------
1185
1186template<class Val, class BV>
1188 size_type arr_size,
1189 size_type offset,
1190 bool set_not_null)
1191{
1192 if (arr_size == 0)
1193 throw_range_error("sparse_vector range error (import size 0)");
1194
1195 // clear all planes in the range to provide corrrect import of 0 values
1196 if (offset < this->size_) // in case it touches existing elements
1197 this->clear_range(offset, offset + arr_size - 1);
1198
1199 this->import_u_nocheck(arr, arr_size, offset, set_not_null);
1200}
1201//---------------------------------------------------------------------
1202
1203template<class Val, class BV>
1205 (const unsigned_value_type* arr,
1206 size_type arr_size,
1207 size_type offset,
1208 bool set_not_null)
1209{
1210 BM_ASSERT(arr);
1211 const unsigned bit_capacity = sizeof(Val)*8;
1212 unsigned char b_list[bit_capacity];
1213 unsigned row_len[bit_capacity] = {0, };
1214 bvector_type_ptr bv_slices[bit_capacity] = {0, };
1215
1216 const unsigned transpose_window = 256; // L1-sized for 32-bit int
1218
1219 // transposition algorithm uses bitscan to find index bits and store it
1220 // in temporary matrix (list for each bit plane), matrix here works
1221 // when array gets to big - the list gets loaded into bit-vector using
1222 // bulk load algorithm, which is faster than single bit access
1223 //
1224
1225 size_type i;
1226 for (i = 0; i < arr_size; ++i)
1227 {
1228 unsigned bcnt = bm::bitscan(arr[i], b_list);
1229 const size_type bit_idx = i + offset;
1230
1231 for (unsigned j = 0; j < bcnt; ++j)
1232 {
1233 unsigned p = b_list[j];
1234 unsigned rl = row_len[p];
1235 tm.row(p)[rl] = bit_idx;
1236 row_len[p] = ++rl;
1237
1238 if (rl == transpose_window)
1239 {
1240 bvector_type* bv = bv_slices[p];
1241 if (!bv)
1242 bv = bv_slices[p] = this->get_create_slice(p);
1243
1244 const size_type* r = tm.row(p);
1245 row_len[p] = 0;
1246 bv->import_sorted(r, rl, false);
1247
1248 }
1249 } // for j
1250 } // for i
1251
1252 // process incomplete transposition lines
1253 //
1254 unsigned rows = tm.rows();
1255 for (unsigned k = 0; k < rows; ++k)
1256 {
1257 if (unsigned rl = row_len[k])
1258 {
1259 bvector_type* bv = bv_slices[k];
1260 if (!bv)
1261 bv = this->get_create_slice(k);
1262 const size_type* row = tm.row(k);
1263 bv->import_sorted(row, rl, false);
1264 }
1265 } // for k
1266
1267
1268 if (i + offset > this->size_)
1269 this->size_ = i + offset;
1270
1271 if (set_not_null)
1272 {
1273 if (bvector_type* bv_null = this->get_null_bvect())
1274 bv_null->set_range(offset, offset + arr_size - 1);
1275 }
1276}
1277
1278
1279//---------------------------------------------------------------------
1280
1281template<class Val, class BV>
1283{
1284 const bvector_type* bv_null = this->get_null_bvector();
1285 if (!bv_null)
1286 return;
1287 bool found = bv_null->find_reverse(this->size_);
1288 this->size_ += found;
1289}
1290
1291//---------------------------------------------------------------------
1292
1293template<class Val, class BV>
1295 size_type arr_size,
1296 bool set_not_null)
1297{
1298 if constexpr (std::is_signed<value_type>::value)
1299 {
1300 const unsigned tmp_size = 1024;
1301 unsigned_value_type arr_tmp[tmp_size];
1302 size_type k(0), i(0);
1303 while (i < arr_size)
1304 {
1305 arr_tmp[k++] = this->s2u(arr[i++]);
1306 if (k == tmp_size)
1307 {
1308 import_back_u(arr_tmp, k, set_not_null);
1309 k = 0;
1310 }
1311 } // while
1312 if (k)
1313 {
1314 import_back_u(arr_tmp, k, set_not_null);
1315 }
1316 }
1317 else
1318 {
1319 this->import_back_u((const unsigned_value_type*)arr, arr_size, set_not_null);
1320 }
1321}
1322
1323
1324//---------------------------------------------------------------------
1325
1326template<class Val, class BV>
1328 size_type arr_size,
1329 bool set_not_null)
1330{
1331 this->import_u_nocheck(arr, arr_size, this->size(), set_not_null);
1332}
1333
1334//---------------------------------------------------------------------
1335
1336template<class Val, class BV>
1339 size_type idx_from,
1340 size_type dec_size,
1341 bool zero_mem) const
1342{
1343 return extract(arr, dec_size, idx_from, zero_mem);
1344}
1345
1346//---------------------------------------------------------------------
1347
1348template<class Val, class BV>
1351 const size_type* idx,
1352 size_type size,
1353 bm::sort_order sorted_idx) const
1354{
1355 BM_ASSERT(arr);
1356 BM_ASSERT(idx);
1357 BM_ASSERT(size);
1358
1359 if (size == 1) // corner case: get 1 value
1360 {
1361 arr[0] = this->get(idx[0]);
1362 return size;
1363 }
1364 ::memset(arr, 0, sizeof(value_type)*size);
1365
1366 for (size_type i = 0; i < size;)
1367 {
1368 bool sorted_block = true;
1369
1370 // look ahead for the depth of the same block
1371 // (speculate more than one index lookup per block)
1372 //
1373 block_idx_type nb = (idx[i] >> bm::set_block_shift);
1374 size_type r = i;
1375
1376 switch (sorted_idx)
1377 {
1378 case BM_UNKNOWN:
1379 {
1380 sorted_block = true; // initial assumption
1381 size_type idx_prev = idx[r];
1382 for (; (r < size) && (nb == (idx[r] >> bm::set_block_shift)); ++r)
1383 {
1384 if (sorted_block)
1385 {
1386 if (idx[r] < idx_prev) // sorted check
1387 sorted_block = false;
1388 idx_prev = idx[r];
1389 }
1390 } // for r
1391 }
1392 break;
1393 case BM_UNSORTED:
1394 sorted_block = false;
1395 for (; r < size; ++r)
1396 {
1397 block_idx_type nb_next = (idx[r] >> bm::set_block_shift);
1398 if (nb != nb_next)
1399 break;
1400 } // for r
1401 break;
1402 case BM_SORTED:
1403 #ifdef BM64ADDR
1404 r = bm::idx_arr_block_lookup_u64(idx, size, nb, r);
1405 #else
1406 r = bm::idx_arr_block_lookup_u32(idx, size, nb, r);
1407 #endif
1408 break;
1409 case BM_SORTED_UNIFORM:
1410 r = size;
1411 break;
1412 default:
1413 BM_ASSERT(0);
1414 } // switch
1415
1416 // single element hit, use random access
1417 if (r == i+1)
1418 {
1419 // (idx[i] < bm::id_max) ? is an out of bounds check
1420 // some code (RSC vector) uses it to
1421 // indicate NULL value and prsent it as 0
1422 //
1423 if (idx[i] < bm::id_max)
1424 {
1425 unsigned_value_type uv = this->get_unsigned(idx[i]);
1426 arr[i] = value_type(uv);
1427 }
1428 ++i;
1429 continue;
1430 }
1431
1432 // process block co-located elements at ones for best (CPU cache opt)
1433 //
1434 unsigned i0 = unsigned(nb >> bm::set_array_shift); // top block address
1435 unsigned j0 = unsigned(nb & bm::set_array_mask); // address in sub-block
1436
1437 unsigned eff_planes = this->effective_slices(); // TODO: get real effective planes for [i,j]
1438 BM_ASSERT(eff_planes <= (sizeof(value_type) * 8));
1439
1440 for (unsigned j = 0; j < eff_planes; ++j)
1441 {
1442 const bm::word_t* blk = this->bmatr_.get_block(j, i0, j0);
1443 if (!blk)
1444 continue;
1446 const unsigned_value_type mask1 = 1u;
1447
1448 if (blk == FULL_BLOCK_FAKE_ADDR)
1449 {
1450 vm = (mask1 << j);
1451 for (size_type k = i; k < r; ++k)
1452 ((unsigned_value_type*)arr)[k] |= vm;
1453 continue;
1454 }
1455 if (BM_IS_GAP(blk))
1456 {
1457 const bm::gap_word_t* gap_blk = BMGAP_PTR(blk);
1458 unsigned is_set;
1459
1460 if (sorted_block) // b-search hybrid with scan lookup
1461 {
1462 for (size_type k = i; k < r; )
1463 {
1464 unsigned nbit = unsigned(idx[k] & bm::set_block_mask);
1465
1466 unsigned gidx = bm::gap_bfind(gap_blk, nbit, &is_set);
1467 unsigned gap_value = gap_blk[gidx];
1468 if (is_set)
1469 {
1470 ((unsigned_value_type*)arr)[k] |= vm = (mask1 << j);
1471 for (++k; k < r; ++k) // speculative look-up
1472 {
1473 if (unsigned(idx[k] & bm::set_block_mask) <= gap_value)
1474 ((unsigned_value_type*)arr)[k] |= vm;
1475 else
1476 break;
1477 }
1478 }
1479 else // 0 GAP - skip. not set
1480 {
1481 for (++k;
1482 (k < r) &&
1483 (unsigned(idx[k] & bm::set_block_mask) <= gap_value);
1484 ++k) {}
1485 }
1486 } // for k
1487 }
1488 else // unsorted block gather request: b-search lookup
1489 {
1490 for (size_type k = i; k < r; ++k)
1491 {
1492 unsigned nbit = unsigned(idx[k] & bm::set_block_mask);
1493 is_set = bm::gap_test_unr(gap_blk, nbit);
1494 ((unsigned_value_type*)arr)[k] |= (unsigned_value_type(bool(is_set)) << j);
1495 } // for k
1496 }
1497 continue;
1498 }
1499 bm::bit_block_gather_scatter((unsigned_value_type*)arr, blk, idx, r, i, j);
1500 } // for (each plane)
1501
1502 i = r;
1503
1504 } // for i
1505
1506 if constexpr (parent_type::is_signed())
1507 u2s_translate(arr, size);
1508
1509 return size;
1510}
1511
1512//---------------------------------------------------------------------
1513
1514template<class Val, class BV>
1517 size_type size,
1518 size_type offset,
1519 bool zero_mem) const
1520{
1521 if (size == 0)
1522 return 0;
1523 if (zero_mem)
1524 ::memset(arr, 0, sizeof(value_type)*size);
1525
1526 size_type start = offset;
1527 size_type end = start + size;
1528 if (end > this->size_)
1529 end = this->size_;
1530
1531 // calculate logical block coordinates and masks
1532 //
1533 block_idx_type nb = (start >> bm::set_block_shift);
1534 unsigned i0 = unsigned(nb >> bm::set_array_shift); // top block address
1535 unsigned j0 = unsigned(nb & bm::set_array_mask); // address in sub-block
1536 unsigned nbit = unsigned(start & bm::set_block_mask);
1537 unsigned nword = unsigned(nbit >> bm::set_word_shift);
1538 unsigned mask0 = 1u << (nbit & bm::set_word_mask);
1539 const bm::word_t* blk = 0;
1540 unsigned is_set;
1541
1542 auto planes = this->effective_slices();
1543 BM_ASSERT(planes <= (sizeof(value_type) * 8));
1544
1545 for (unsigned j = 0; j < planes; ++j)
1546 {
1547 blk = this->bmatr_.get_block(j, i0, j0);
1548 bool is_gap = BM_IS_GAP(blk);
1549
1550 for (size_type k = start; k < end; ++k)
1551 {
1553 if (nb1 != nb) // block switch boundaries
1554 {
1555 nb = nb1;
1556 i0 = unsigned(nb >> bm::set_array_shift);
1557 j0 = unsigned(nb & bm::set_array_mask);
1558 blk = this->bmatr_.get_block(j, i0, j0);
1559 is_gap = BM_IS_GAP(blk);
1560 }
1561 if (!blk)
1562 continue;
1563 nbit = unsigned(k & bm::set_block_mask);
1564 if (is_gap)
1565 {
1566 is_set = bm::gap_test_unr(BMGAP_PTR(blk), nbit);
1567 }
1568 else
1569 {
1570 if (blk == FULL_BLOCK_FAKE_ADDR)
1571 {
1572 is_set = 1;
1573 }
1574 else
1575 {
1576 BM_ASSERT(!IS_FULL_BLOCK(blk));
1577 nword = unsigned(nbit >> bm::set_word_shift);
1578 mask0 = 1u << (nbit & bm::set_word_mask);
1579 is_set = (blk[nword] & mask0);
1580 }
1581 }
1582 size_type idx = k - offset;
1583 unsigned_value_type vm = (bool) is_set;
1584 vm <<= j;
1585 arr[idx] |= vm;
1586
1587 } // for k
1588
1589 } // for j
1590
1591 if constexpr (parent_type::is_signed())
1592 u2s_translate(arr, size);
1593
1594 return 0;
1595}
1596
1597//---------------------------------------------------------------------
1598
1599template<class Val, class BV>
1602 size_type size,
1603 size_type offset,
1604 bool zero_mem) const
1605{
1606 if (size == 0)
1607 return 0;
1608
1609 if (zero_mem)
1610 ::memset(arr, 0, sizeof(value_type)*size);
1611
1612 size_type start = offset;
1613 size_type end = start + size;
1614 if (end > this->size_)
1615 end = this->size_;
1616
1617 for (size_type i = 0; i < parent_type::value_bits(); ++i)
1618 {
1619 const bvector_type* bv = this->bmatr_.get_row(i);
1620 if (!bv)
1621 continue;
1622
1623 unsigned_value_type mask = 1u << i;
1624 typename BV::enumerator en(bv, offset);
1625 for (;en.valid(); ++en)
1626 {
1627 size_type idx = *en - offset;
1628 if (idx >= size)
1629 break;
1630 arr[idx] |= mask;
1631 } // for
1632
1633 } // for i
1634
1635 return 0;
1636}
1637
1638
1639//---------------------------------------------------------------------
1640
1641template<class Val, class BV>
1644 size_type size,
1645 size_type offset,
1646 bool zero_mem) const BMNOEXCEPT2
1647{
1648 /// Decoder functor
1649 /// @internal
1650 struct sv_decode_visitor_func
1651 {
1652 sv_decode_visitor_func(value_type* BMRESTRICT varr,
1655 : arr_(varr), mask_(mask), sv_off_(off)
1656 {}
1657
1658 int add_bits(size_type bv_offset,
1659 const unsigned char* BMRESTRICT bits,
1660 unsigned bits_size) BMNOEXCEPT
1661 {
1662 // can be negative (-1) when bv base offset = 0 and sv = 1,2..
1663 size_type base = bv_offset - sv_off_;
1664 unsigned_value_type m = mask_;
1665 for (unsigned i = 0; i < bits_size; ++i)
1666 arr_[bits[i] + base] |= m;
1667 return 0;
1668 }
1669 int add_range(size_type bv_offset, size_type sz) BMNOEXCEPT
1670 {
1671 auto base = bv_offset - sv_off_;
1672 unsigned_value_type m = mask_;
1673 for (size_type i = 0; i < sz; ++i)
1674 arr_[i + base] |= m;
1675 return 0;
1676 }
1677
1678 value_type* BMRESTRICT arr_; ///< target array for de-transpose
1679 unsigned_value_type mask_; ///< bit-plane mask
1680 size_type sv_off_; ///< SV read offset
1681 };
1682
1683 if (!size)
1684 return 0;
1685
1686 if (zero_mem)
1687 ::memset(arr, 0, sizeof(value_type)*size);
1688
1689 size_type end = offset + size;
1690 if (end > this->size_)
1691 end = this->size_;
1692
1693 sv_decode_visitor_func func(arr, 0, offset);
1694
1695 auto planes = this->effective_slices();
1696 BM_ASSERT(planes <= (sizeof(value_type) * 8));
1697 for (size_type i = 0; i < planes; ++i)
1698 {
1699 if (const bvector_type* bv = this->bmatr_.get_row(i))
1700 {
1701 func.mask_ = (unsigned_value_type(1) << i); // set target plane OR mask
1702 bm::for_each_bit_range_no_check(*bv, offset, end-1, func);
1703 }
1704 } // for i
1705
1706 const size_type exported_size = end - offset;
1707 if constexpr (parent_type::is_signed())
1708 u2s_translate(arr, exported_size);
1709 return exported_size;
1710}
1711
1712//---------------------------------------------------------------------
1713
1714template<class Val, class BV>
1716{
1717 for (size_type i = 0; i < sz; ++i)
1718 {
1720 ::memcpy(&uv, &arr[i], sizeof(uv));
1721 arr[i] = parent_type::u2s(uv);
1722 } // for i
1723}
1724
1725
1726//---------------------------------------------------------------------
1727
1728template<class Val, class BV>
1731{
1732 if (idx >= this->size_)
1733 throw_range_error("sparse vector range error");
1734 return this->get(idx);
1735}
1736
1737//---------------------------------------------------------------------
1738
1739template<class Val, class BV>
1743{
1744 BM_ASSERT(i < size());
1745 return get_no_check(i);
1746}
1747
1748//---------------------------------------------------------------------
1749
1750template<class Val, class BV>
1754{
1755 unsigned_value_type uv = get_unsigned(i);
1756 if constexpr (parent_type::is_signed())
1757 return this->u2s(uv);
1758 else
1759 return uv;
1760}
1761
1762//---------------------------------------------------------------------
1763
1764template<class Val, class BV>
1768{
1769 BM_ASSERT(i < bm::id_max);
1770
1771 unsigned_value_type uv = 0;
1772 unsigned eff_planes = this->effective_slices();
1773 BM_ASSERT(eff_planes <= (sizeof(value_type) * 8));
1774
1775 unsigned_value_type smask = this->slice_mask_;
1776 for (unsigned j = 0; smask && j < eff_planes; j+=4, smask >>= 4)
1777 {
1778 if (smask & 0x0F) // b1111
1779 {
1781 (unsigned_value_type)this->bmatr_.get_half_octet(i, j);
1782 uv |= unsigned_value_type(vm << j);
1783 }
1784 } // for j
1785 return uv;
1786}
1787
1788//---------------------------------------------------------------------
1789
1790template<class Val, class BV>
1792 size_type idx, value_type& v) const BMNOEXCEPT
1793{
1794 if (this->is_null(idx))
1795 return false;
1796 v = get(idx);
1797 return true;
1798}
1799
1800
1801//---------------------------------------------------------------------
1802
1803template<class Val, class BV>
1805{
1806 bool need_clear;
1807 if (idx >= size())
1808 {
1809 this->size_ = idx+1;
1810 need_clear = false;
1811 }
1812 else
1813 need_clear = true;
1814 set_value(idx, v, need_clear);
1815}
1816
1817//---------------------------------------------------------------------
1818
1819template<class Val, class BV>
1821{
1822 if (idx >= size())
1823 this->size_ = idx+1; // assumed there is nothing to do outside the size
1824 else
1825 {
1826 set_value(idx, value_type(0), true);
1827 if (set_null)
1828 {
1829 if (bvector_type* bv_null = this->get_null_bvect())
1830 bv_null->clear_bit_no_check(idx);
1831 }
1832 }
1833}
1834
1835//---------------------------------------------------------------------
1836
1837template<class Val, class BV>
1839{
1840 set_value(this->size_, v, false);
1841 ++(this->size_);
1842}
1843
1844//---------------------------------------------------------------------
1845
1846template<class Val, class BV>
1848{
1849 BM_ASSERT(count);
1850 BM_ASSERT(bm::id_max - count > this->size_);
1851 BM_ASSERT(this->is_nullable());
1852
1853 this->size_ += count;
1854}
1855
1856
1857//---------------------------------------------------------------------
1858
1859template<class Val, class BV>
1861{
1862 if (idx >= size())
1863 {
1864 this->size_ = idx+1;
1865 set_value(idx, v, false);
1866 return;
1867 }
1868 insert_value(idx, v);
1869}
1870
1871//---------------------------------------------------------------------
1872
1873template<class Val, class BV>
1875{
1876 insert_value_no_null(idx, v);
1877 this->insert_null(idx, true);
1878}
1879
1880//---------------------------------------------------------------------
1881
1882template<class Val, class BV>
1884{
1885 unsigned_value_type uv = this->s2u(v);
1886 unsigned bsr = uv ? bm::bit_scan_reverse(uv) : 0u;
1887
1888 unsigned_value_type mask = 1u;
1889 unsigned i = 0;
1890 for (; i <= bsr; ++i)
1891 {
1892 if (uv & mask)
1893 {
1894 bvector_type* bv = this->get_create_slice(i);
1895 bv->insert(idx, true);
1896 }
1897 else
1898 {
1899 if (bvector_type_ptr bv = this->bmatr_.get_row(i))
1900 bv->insert(idx, false);
1901 }
1902 mask = unsigned_value_type(mask << 1);
1903 } // for i
1904
1905 // insert 0 into all other existing planes
1906 unsigned eff_planes = this->effective_slices();
1907 BM_ASSERT(eff_planes <= (sizeof(value_type) * 8));
1908 for (; i < eff_planes; ++i)
1909 {
1910 if (bvector_type* bv = this->bmatr_.get_row(i))
1911 bv->insert(idx, false);
1912 } // for i
1913 this->size_++;
1914}
1915
1916//---------------------------------------------------------------------
1917
1918template<class Val, class BV>
1920{
1921 BM_ASSERT(idx < this->size_);
1922 if (idx >= this->size_)
1923 return;
1924 this->erase_column(idx, erase_null);
1925 this->size_ -= erase_null;
1926}
1927
1928
1929//---------------------------------------------------------------------
1930
1931template<class Val, class BV>
1933{
1934 set_value_no_null(this->size_, v, false);
1935 ++(this->size_);
1936}
1937
1938//---------------------------------------------------------------------
1939
1940template<class Val, class BV>
1942 value_type v, bool need_clear)
1943{
1944 set_value_no_null(idx, v, need_clear);
1945 if (bvector_type* bv_null = this->get_null_bvect())
1946 bv_null->set_bit_no_check(idx);
1947}
1948
1949//---------------------------------------------------------------------
1950
1951template<class Val, class BV>
1953 value_type v, bool need_clear)
1954{
1955 unsigned_value_type uv = this->s2u(v);
1956
1957 // calculate logical block coordinates and masks
1958 //
1959 block_idx_type nb = (idx >> bm::set_block_shift);
1960 unsigned i0 = unsigned(nb >> bm::set_array_shift); // top block address
1961 unsigned j0 = unsigned(nb & bm::set_array_mask); // address in sub-block
1962
1963 // clear the planes where needed
1964 unsigned bsr = uv ? bm::bit_scan_reverse(uv) : 0u;
1965 if (need_clear)
1966 {
1967 unsigned eff_planes = this->effective_slices();
1968 BM_ASSERT(eff_planes <= (sizeof(value_type) * 8));
1969 this->bmatr_.clear_slices_range(bsr, eff_planes, idx);
1970 }
1971 if (uv)
1972 {
1973 unsigned_value_type mask = 1u;
1974 for (unsigned j = 0; j <= bsr; ++j)
1975 {
1976 if (uv & mask)
1977 {
1978 bvector_type* bv = this->get_create_slice(j);
1979 bv->set_bit_no_check(idx);
1980 }
1981 else if (need_clear)
1982 {
1983 if (const bm::word_t* blk = this->bmatr_.get_block(j, i0, j0))
1984 {
1985 // TODO: more efficient set/clear on on block
1986 bvector_type* bv = this->bmatr_.get_row(j);
1987 bv->clear_bit_no_check(idx);
1988 }
1989 }
1990 mask <<= 1u;
1991 } // for j
1992 }
1993}
1994
1995//---------------------------------------------------------------------
1996
1997template<class Val, class BV>
1999{
2000 if (idx >= this->size_)
2001 {
2002 this->size_ = idx+1;
2003 set_value_no_null(idx, 1, false);
2004 }
2005 else
2006 inc_no_null(idx);
2007
2008 if (bvector_type* bv_null = this->get_null_bvect())
2009 bv_null->set_bit_no_check(idx);
2010}
2011
2012//---------------------------------------------------------------------
2013
2014template<class Val, class BV>
2016{
2017 if constexpr (parent_type::is_signed())
2018 {
2019 value_type v = get(idx);
2020 if (std::numeric_limits<value_type>::max() == v)
2021 v = 0;
2022 else
2023 ++v;
2024 set_value_no_null(idx, v, true);
2025 }
2026 else
2027 for (unsigned i = 0; i < parent_type::sv_value_slices; ++i)
2028 {
2029 bvector_type* bv = this->get_create_slice(i);
2030 if (bool carry_over = bv->inc(idx); !carry_over)
2031 break;
2032 } // for i
2033}
2034
2035//------------------------------------ ---------------------------------
2036
2037template<class Val, class BV>
2039{
2040 value_type v_prev = get(idx);
2041 set_value_no_null(idx, v + v_prev, true);
2042}
2043
2044//---------------------------------------------------------------------
2045
2046template<class Val, class BV>
2048{
2049 parent_type::clear_all(free_mem);
2050}
2051
2052//---------------------------------------------------------------------
2053
2054template<class Val, class BV>
2056{
2057 BM_ASSERT(rank);
2058 pos = rank - 1;
2059 return true;
2060}
2061
2062//---------------------------------------------------------------------
2063
2064template<class Val, class BV>
2068 typename sparse_vector<Val, BV>::size_type right,
2069 bool set_null)
2070{
2071 parent_type::clear_range(left, right, set_null);
2072 return *this;
2073}
2074
2075//---------------------------------------------------------------------
2076
2077template<class Val, class BV>
2080{
2081 BM_ASSERT(st);
2082 typename bvector_type::statistics stbv;
2083 parent_type::calc_stat(&stbv);
2084 if (st)
2085 {
2086 st->reset();
2087 st->add(stbv);
2088 }
2089}
2090
2091//---------------------------------------------------------------------
2092
2093template<class Val, class BV>
2095 bm::word_t* temp_block,
2096 typename bvector_type::optmode opt_mode,
2098{
2099 typename bvector_type::statistics stbv;
2100 stbv.reset();
2101 parent_type::optimize(temp_block, opt_mode, st ? &stbv : 0);
2102
2103 if (st)
2104 {
2105 st->reset();
2106 st->add(stbv);
2107 }
2108}
2109
2110//---------------------------------------------------------------------
2111
2112template<class Val, class BV>
2114{
2115 unsigned stored_slices = this->stored_slices();
2116 for (unsigned j = 0; j < stored_slices; ++j)
2117 {
2118 if (bvector_type* bv = this->bmatr_.get_row(j))
2119 bv->optimize_gap_size();
2120 }
2121}
2122
2123//---------------------------------------------------------------------
2124
2125template<class Val, class BV>
2128{
2129 size_type arg_size = sv.size();
2130 if (this->size_ < arg_size)
2131 resize(arg_size);
2132
2133 unsigned planes = (unsigned)this->bmatr_.rows();
2134 if (planes > sv.get_bmatrix().rows())
2135 --planes;
2136
2137 for (unsigned j = 0; j < planes; ++j)
2138 {
2139 if (const bvector_type* arg_bv = sv.bmatr_.row(j))
2140 {
2141 bvector_type* bv = this->get_create_slice(j);
2142 *bv |= *arg_bv;
2143 }
2144 } // for j
2145
2146 join_null_slice(sv);
2147 return *this;
2148}
2149
2150//---------------------------------------------------------------------
2151
2152template<class Val, class BV>
2155{
2156 size_type arg_size = sv.size();
2157 if (this->size_ < arg_size)
2158 resize(arg_size);
2159
2160 this->merge_matr(sv.bmatr_);
2161
2162 join_null_slice(sv);
2163
2164 return *this;
2165}
2166
2167//---------------------------------------------------------------------
2168
2169template<class Val, class BV>
2171{
2172 bvector_type* bv_null = this->get_null_bvect();
2173 size_type arg_size = sv.size();
2174
2175 // our vector is NULL-able but argument is not (assumed all values are real)
2176 if (bv_null)
2177 {
2178 if (!sv.is_nullable())
2179 bv_null->set_range(0, arg_size-1);
2180 }
2181 else // not NULL
2182 {
2183 if (sv.is_nullable())
2184 {
2185 this->bmatr_.set_null_idx(sv.bmatr_.get_null_idx());
2186 BM_ASSERT(this->get_null_bvect());
2187 }
2188 }
2189}
2190
2191
2192
2193template<class Val, class BV>
2195 const sparse_vector<Val, BV>& sv,
2197 typename sparse_vector<Val, BV>::size_type right,
2198 bm::null_support slice_null)
2199{
2200 if (left > right)
2201 bm::xor_swap(left, right);
2202 this->copy_range_slices(sv, left, right, slice_null);
2203 this->resize(sv.size());
2204}
2205
2206//---------------------------------------------------------------------
2207
2208template<class Val, class BV>
2210 bm::null_support slice_null)
2211{
2212 if (right < left)
2213 bm::xor_swap(left, right);
2214 this->keep_range_no_check(left, right, slice_null);
2215}
2216
2217
2218//---------------------------------------------------------------------
2219
2220template<class Val, class BV>
2222 const typename sparse_vector<Val, BV>::bvector_type& bv_mask)
2223{
2224 unsigned slices = (unsigned)this->get_bmatrix().rows();
2225 for (unsigned j = 0; j < slices/*planes*/; ++j)
2226 {
2227 if (bvector_type* bv = this->bmatr_.get_row(j))
2228 bv->bit_and(bv_mask);
2229 } // for j
2230}
2231
2232//---------------------------------------------------------------------
2233
2234template<class Val, class BV>
2236 const value_type val) const BMNOEXCEPT
2237{
2238 // TODO: consider bit-by-bit comparison to minimize CPU hit miss in plans get()
2239 value_type sv_value = get(idx);
2240 return (sv_value > val) - (sv_value < val);
2241}
2242
2243//---------------------------------------------------------------------
2244
2245template<class Val, class BV>
2247 bm::null_support null_able) const BMNOEXCEPT
2248{
2249 return parent_type::equal(sv, null_able);
2250}
2251
2252//---------------------------------------------------------------------
2253
2254template<class Val, class BV>
2257{
2258 typedef typename sparse_vector<Val, BV>::const_iterator it_type;
2259 return it_type(this);
2260}
2261
2262//---------------------------------------------------------------------
2263
2264template<class Val, class BV>
2267{
2268 this->bmatr_.set_allocator_pool(pool_ptr);
2269}
2270
2271
2272//---------------------------------------------------------------------
2273//
2274//---------------------------------------------------------------------
2275
2276
2277template<class Val, class BV>
2279: sv_(0), pos_(bm::id_max), buf_ptr_(0)
2280{}
2281
2282//---------------------------------------------------------------------
2283
2284template<class Val, class BV>
2287: sv_(it.sv_), pos_(it.pos_), buf_ptr_(0)
2288{}
2289
2290//---------------------------------------------------------------------
2291
2292template<class Val, class BV>
2295 ) BMNOEXCEPT
2296: sv_(sv), buf_ptr_(0)
2297{
2298 BM_ASSERT(sv_);
2299 pos_ = sv_->empty() ? bm::id_max : 0u;
2300}
2301
2302//---------------------------------------------------------------------
2303
2304template<class Val, class BV>
2308: sv_(sv), buf_ptr_(0)
2309{
2310 BM_ASSERT(sv_);
2311 this->go_to(pos);
2312}
2313
2314//---------------------------------------------------------------------
2315
2316template<class Val, class BV>
2318{
2319 pos_ = (!sv_ || pos >= sv_->size()) ? bm::id_max : pos;
2320 buf_ptr_ = 0;
2321}
2322
2323//---------------------------------------------------------------------
2324
2325template<class Val, class BV>
2327{
2328 if (pos_ == bm::id_max) // nothing to do, we are at the end
2329 return false;
2330 ++pos_;
2331 if (pos_ >= sv_->size())
2332 {
2333 this->invalidate();
2334 return false;
2335 }
2336 if (buf_ptr_)
2337 {
2338 ++buf_ptr_;
2339 if (buf_ptr_ - ((value_type*)buffer_.data()) >= n_buf_size)
2340 buf_ptr_ = 0;
2341 }
2342 return true;
2343}
2344
2345//---------------------------------------------------------------------
2346
2347template<class Val, class BV>
2350{
2351 BM_ASSERT(this->valid());
2352 value_type v;
2353
2354 if (!buf_ptr_)
2355 {
2356 buffer_.reserve(n_buf_size * sizeof(value_type));
2357 buf_ptr_ = (value_type*)(buffer_.data());
2358 sv_->extract(buf_ptr_, n_buf_size, pos_, true);
2359 }
2360 v = *buf_ptr_;
2361 return v;
2362}
2363
2364//---------------------------------------------------------------------
2365
2366template<class Val, class BV>
2368{
2369 value_type v = value();
2370 if (buf_ptr_)
2371 {
2372 v = *buf_ptr_;
2373 value_type* buf_end = ((value_type*)buffer_.data()) + n_buf_size;
2374 while(!v)
2375 {
2376 ++pos_;
2377 if (++buf_ptr_ < buf_end)
2378 v = *buf_ptr_;
2379 else
2380 break;
2381 }
2382 if (pos_ >= sv_->size())
2383 {
2384 pos_ = bm::id_max;
2385 return;
2386 }
2387 if (buf_ptr_ >= buf_end)
2388 buf_ptr_ = 0;
2389 }
2390}
2391
2392//---------------------------------------------------------------------
2393
2394template<class Val, class BV>
2396{
2397 return sv_->is_null(pos_);
2398}
2399
2400
2401//---------------------------------------------------------------------
2402//
2403//---------------------------------------------------------------------
2404
2405
2406template<class Val, class BV>
2408{}
2409
2410//---------------------------------------------------------------------
2411
2412template<class Val, class BV>
2415: sv_(sv)
2416{
2417 if (sv)
2418 {
2419 prev_nb_ = sv_->size() >> bm::set_block_shift;
2420 bv_null_ = sv_->get_null_bvect();
2421 buffer_.reserve(n_buf_size * sizeof(value_type));
2422 buf_ptr_ = (unsigned_value_type*)(buffer_.data());
2423 }
2424 else
2425 {
2426 buf_ptr_ = 0; bv_null_ = 0;
2427 }
2428}
2429
2430//---------------------------------------------------------------------
2431
2432template<class Val, class BV>
2435: sv_(bi.sv_), bv_null_(bi.bv_null_), buf_ptr_(0),
2436 set_not_null_(bi.set_not_null_),
2437 prev_nb_(bi.prev_nb_), opt_mode_(bi.opt_mode_)
2438{
2439 if (sv_)
2440 {
2441 prev_nb_ = sv_->size() >> bm::set_block_shift;
2442 buffer_.reserve(n_buf_size * sizeof(value_type));
2443 buf_ptr_ = (unsigned_value_type*)(buffer_.data());
2444 }
2445}
2446
2447//---------------------------------------------------------------------
2448
2449template<class Val, class BV>
2452: sv_(bi.sv_), bv_null_(bi.bv_null_), buf_ptr_(bi.buf_ptr_),
2453 set_not_null_(bi.set_not_null_),
2454 prev_nb_(bi.prev_nb_), opt_mode_(bi.opt_mode_)
2455{
2456 buffer_.swap(bi.buffer_);
2457 buf_ptr_ = bi.buf_ptr_;
2458}
2459
2460//---------------------------------------------------------------------
2461
2462template<class Val, class BV>
2464{
2465 this->flush();
2466}
2467
2468//---------------------------------------------------------------------
2469
2470template<class Val, class BV>
2473{
2474 BM_ASSERT(sv_);
2475 BM_ASSERT(buf_ptr_ && buffer_.data());
2476
2477 const unsigned_value_type* data_ptr = (const unsigned_value_type*)buffer_.data();
2478 size_type buf_idx = size_type(buf_ptr_ - data_ptr);
2479 typename sparse_vector<Val, BV>::size_type sz = sv_->size();
2480
2481 this->add_value_no_null(v);
2482
2483 if (bv_null_)
2484 {
2485 bv_null_->set_bit_no_check(sz + buf_idx);
2486 }
2487}
2488
2489//---------------------------------------------------------------------
2490
2491template<class Val, class BV>
2495{
2496 BM_ASSERT(sv_);
2497 BM_ASSERT(buf_ptr_ && buffer_.data());
2498
2501 size_type buf_idx = size_type(buf_ptr_ - (const unsigned_value_type*)buffer_.data());
2502 if (buf_idx >= n_buf_size)
2503 {
2504 this->flush();
2505 buf_ptr_ = (unsigned_value_type*)(buffer_.data());
2506 }
2507 *buf_ptr_++ = uv;
2508}
2509
2510//---------------------------------------------------------------------
2511
2512template<class Val, class BV>
2514{
2515 BM_ASSERT(bv_null_);
2516 this->add_value_no_null(value_type(0));
2517}
2518
2519//---------------------------------------------------------------------
2520
2521template<class Val, class BV>
2524{
2525 if (count < 32)
2526 {
2527 for (size_type i = 0; i < count; ++i)
2528 this->add_value_no_null(value_type(0));
2529 }
2530 else
2531 {
2532 this->flush();
2533 sv_->push_back_null(count);
2534 }
2535}
2536
2537//---------------------------------------------------------------------
2538
2539template<class Val, class BV>
2541{
2542 return (!sv_ || (buf_ptr_ == (unsigned_value_type*)buffer_.data()));
2543}
2544
2545//---------------------------------------------------------------------
2546
2547template<class Val, class BV>
2549{
2550 if (!sv_)
2551 return false;
2552 unsigned_value_type* arr = (unsigned_value_type*)buffer_.data();
2553 size_type arr_size = size_type(buf_ptr_ - arr);
2554 if (!arr_size)
2555 return false;
2556 sv_->import_back_u(arr, arr_size, false);
2557 buf_ptr_ = (unsigned_value_type*) buffer_.data();
2558 block_idx_type nb = sv_->size() >> bm::set_block_shift;
2559 if (nb != prev_nb_)
2560 {
2561 sv_->optimize_block(prev_nb_, opt_mode_);
2562 prev_nb_ = nb;
2563 }
2564 return true;
2565}
2566
2567//---------------------------------------------------------------------
2568
2569
2570} // namespace bm
2571
2572
2573
2574#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:108
Utilities for bit transposition (internal) (experimental!)
Base class for bit-transposed(bit-sliced) sparse vector construction.
Definition: bmbmatrix.h:336
void freeze_matr()
Turn on RO mode.
Definition: bmbmatrix.h:612
void resize(size_type new_size, bool set_null)
Definition: bmbmatrix.h:1691
void copy_from(const base_sparse_vector< Val, BV, MAX_SIZE > &bsv)
Definition: bmbmatrix.h:1543
static unsigned_value_type s2u(value_type v) BMNOEXCEPT
Convert signed value type to unsigned representation.
Definition: bmbmatrix.h:1947
const bmatrix_type & get_bmatrix() const BMNOEXCEPT
Definition: bmbmatrix.h:532
bmatrix_type bmatr_
bit-transposed matrix
Definition: bmbmatrix.h:677
allocator_type::allocator_pool_type allocator_pool_type
Definition: bmbmatrix.h:358
std::make_unsigned< value_type >::type unsigned_value_type
Definition: bmbmatrix.h:360
void bit_sub_rows(const bvector_type &bv, bool use_null)
Set SUB (MINUS) operation on all existing bit-slices.
Definition: bmbmatrix.h:644
bool is_nullable() const BMNOEXCEPT
check if container supports NULL(unassigned) values
Definition: bmbmatrix.h:418
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:161
const bvector_type * row(size_type i) const BMNOEXCEPT
Definition: bmbmatrix.h:751
size_type rows() const BMNOEXCEPT
Definition: bmbmatrix.h:139
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
Rank-Select compressed sparse vector.
Back insert iterator implements buffered insert, faster than generic access assignment.
Definition: bmsparsevec.h:256
back_insert_iterator & operator*()
noop
Definition: bmsparsevec.h:312
void add_null(size_type count)
add a series of consequitve NULLs (no-value) to the container
bm::byte_buffer< allocator_type > buffer_type
Definition: bmsparsevec.h:269
bvector_type::allocator_type::allocator_pool_type allocator_pool_type
Definition: bmsparsevec.h:268
void operator=(value_type v)
push value to the vector
Definition: bmsparsevec.h:310
bvector_type::block_idx_type block_idx_type
Definition: bmsparsevec.h:358
void operator=(const back_insert_iterator &bi)
Definition: bmsparsevec.h:283
back_insert_iterator & operator++()
noop
Definition: bmsparsevec.h:314
back_insert_iterator & operator++(int)
noop
Definition: bmsparsevec.h:316
sparse_vector_type::unsigned_value_type unsigned_value_type
Definition: bmsparsevec.h:264
void add_null()
add NULL (no-value) to the container
Definition: bmsparsevec.h:2513
bvector_type * get_null_bvect() const BMNOEXCEPT
Get access to not-null vector.
Definition: bmsparsevec.h:343
sparse_vector_type::size_type size_type
Definition: bmsparsevec.h:265
bool flush()
flush the accumulated buffer
Definition: bmsparsevec.h:2548
back_insert_iterator(back_insert_iterator &&bi) BMNOEXCEPT
move constructor
back_insert_iterator(const back_insert_iterator &bi)
void add_value_no_null(value_type v)
add value to the buffer without changing the NULL vector
Definition: bmsparsevec.h:2493
void add(value_type v)
add value to the container
Definition: bmsparsevec.h:2471
void disable_set_null() BMNOEXCEPT
Reconfigure back inserter not to touch the NULL vector.
Definition: bmsparsevec.h:354
bool empty() const
return true if insertion buffer is empty
Definition: bmsparsevec.h:2540
sparse_vector_type * sparse_vector_type_ptr
Definition: bmsparsevec.h:262
back_insert_iterator(sparse_vector_type *sv)
bvector_type::allocator_type allocator_type
Definition: bmsparsevec.h:267
sparse_vector< Val, BV > sparse_vector_type
Definition: bmsparsevec.h:261
std::output_iterator_tag iterator_category
Definition: bmsparsevec.h:259
sparse_vector_type::value_type value_type
Definition: bmsparsevec.h:263
sparse_vector_type::bvector_type bvector_type
Definition: bmsparsevec.h:266
Const iterator to traverse the sparse vector.
Definition: bmsparsevec.h:158
void go_to(size_type pos) BMNOEXCEPT
re-position to a specified position
Definition: bmsparsevec.h:2317
std::input_iterator_tag iterator_category
Definition: bmsparsevec.h:163
bool operator==(const const_iterator &it) const BMNOEXCEPT
Definition: bmsparsevec.h:185
bool operator>(const const_iterator &it) const BMNOEXCEPT
Definition: bmsparsevec.h:193
bvector_type::allocator_type allocator_type
Definition: bmsparsevec.h:170
sparse_vector< Val, BV > sparse_vector_type
Definition: bmsparsevec.h:165
bool is_null() const BMNOEXCEPT
Get NULL status.
Definition: bmsparsevec.h:2395
bool advance() BMNOEXCEPT
advance iterator forward by one
Definition: bmsparsevec.h:2326
value_type operator*() const
Get current position (value)
Definition: bmsparsevec.h:199
sparse_vector_type::bvector_type bvector_type
Definition: bmsparsevec.h:169
bool operator!=(const const_iterator &it) const BMNOEXCEPT
Definition: bmsparsevec.h:187
bool operator<(const const_iterator &it) const BMNOEXCEPT
Definition: bmsparsevec.h:189
const_iterator operator++(int)
Advance to the next available value.
Definition: bmsparsevec.h:207
bool operator<=(const const_iterator &it) const BMNOEXCEPT
Definition: bmsparsevec.h:191
bool valid() const BMNOEXCEPT
Returns true if iterator is at a valid position.
Definition: bmsparsevec.h:218
bm::byte_buffer< allocator_type > buffer_type
Definition: bmsparsevec.h:172
const_iterator & operator++() BMNOEXCEPT
Advance to the next available value.
Definition: bmsparsevec.h:203
void invalidate() BMNOEXCEPT
Invalidate current iterator.
Definition: bmsparsevec.h:221
value_type value() const
Get current position (value)
Definition: bmsparsevec.h:2349
void skip_zero_values() BMNOEXCEPT
Definition: bmsparsevec.h:2367
sparse_vector_type::size_type size_type
Definition: bmsparsevec.h:168
size_type pos() const BMNOEXCEPT
Current position (index) in the vector.
Definition: bmsparsevec.h:224
sparse_vector_type * sparse_vector_type_ptr
Definition: bmsparsevec.h:166
sparse_vector_type::value_type value_type
Definition: bmsparsevec.h:167
bvector_type::allocator_type::allocator_pool_type allocator_pool_type
Definition: bmsparsevec.h:171
bool operator>=(const const_iterator &it) const BMNOEXCEPT
Definition: bmsparsevec.h:195
Reference class to access elements via common [] operator.
Definition: bmsparsevec.h:121
reference & operator=(const reference &ref)
Definition: bmsparsevec.h:127
reference & operator=(value_type val)
Definition: bmsparsevec.h:132
bool operator==(const reference &ref) const BMNOEXCEPT
Definition: bmsparsevec.h:137
bool is_null() const BMNOEXCEPT
Definition: bmsparsevec.h:139
reference(sparse_vector< Val, BV > &sv, size_type idx) BMNOEXCEPT
Definition: bmsparsevec.h:123
sparse vector de-serializer
algorithms for sparse_vector scan/search
succinct sparse vector with runtime compression using bit-slicing / transposition method
Definition: bmsparsevec.h:87
unsigned char * init_remap_buffer() BMNOEXCEPT
Definition: bmsparsevec.h:1008
void inc(size_type idx)
increment specified element by one
Definition: bmsparsevec.h:1998
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
Definition: bmsparsevec.h:1941
value_type at(size_type idx) const
access specified element with bounds checking
Definition: bmsparsevec.h:1730
void set_null(size_type idx)
set specified element to unassigned value (NULL)
Definition: bmsparsevec.h:1146
void set_value_no_null(size_type idx, value_type v, bool need_clear)
set value without checking boundaries or support of NULL
Definition: bmsparsevec.h:1952
value_type get(size_type idx) const BMNOEXCEPT
get specified element without bounds checking
Definition: bmsparsevec.h:1741
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
Definition: bmsparsevec.h:1883
static constexpr bool is_str() BMNOEXCEPT
Definition: bmsparsevec.h:587
bool equal(const sparse_vector< Val, BV > &sv, bm::null_support null_able=bm::use_null) const BMNOEXCEPT
check if another sparse vector has the same content and size
Definition: bmsparsevec.h:2246
void sync(bool)
syncronize internal structures, build fast access index
Definition: bmsparsevec.h:884
const value_type & const_reference
Definition: bmsparsevec.h:95
void push_back(value_type v)
push value back into vector
Definition: bmsparsevec.h:1838
remap_matrix_type * get_remap_matrix()
Definition: bmsparsevec.h:1020
void sync_size() BMNOEXCEPT
recalculate size to exclude tail NULL elements After this call size() will return the true size of th...
Definition: bmsparsevec.h:1282
size_type size_internal() const BMNOEXCEPT
Definition: bmsparsevec.h:1003
void push_back_no_null(value_type v)
push value back into vector without NULL semantics
Definition: bmsparsevec.h:1932
void insert_value(size_type idx, value_type v)
insert value without checking boundaries
Definition: bmsparsevec.h:1874
unsigned_value_type get_unsigned(size_type idx) const BMNOEXCEPT
Definition: bmsparsevec.h:1766
void clear_all(bool free_mem) BMNOEXCEPT
resize to zero, free memory
Definition: bmsparsevec.h:2047
bvector_type * bvector_type_ptr
Definition: bmsparsevec.h:91
void set_remap() BMNOEXCEPT
Definition: bmsparsevec.h:1009
size_type size() const BMNOEXCEPT
return size of the vector
Definition: bmsparsevec.h:711
void optimize_gap_size()
Optimize sizes of GAP blocks.
Definition: bmsparsevec.h:2113
sparse_vector(const sparse_vector< Val, BV > &sv)
Definition: bmsparsevec.h:1093
sparse_vector< Val, BV > & operator=(const sparse_vector< Val, BV > &sv)
Definition: bmsparsevec.h:405
sparse_vector(sparse_vector< Val, BV > &&sv) BMNOEXCEPT
Definition: bmsparsevec.h:1101
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
Definition: bmsparsevec.h:1804
void resize(size_type sz)
resize vector
Definition: bmsparsevec.h:721
bool try_get(size_type idx, value_type &v) const BMNOEXCEPT
get specified element with NOT NULL check
Definition: bmsparsevec.h:1791
size_t remap_size() const BMNOEXCEPT
Definition: bmsparsevec.h:1006
void clear(size_type idx, bool set_null)
clear specified element with bounds checking and automatic resize
Definition: bmsparsevec.h:1820
static void throw_range_error(const char *err_msg)
throw range error
Definition: bmsparsevec.h:1126
const_iterator end() const BMNOEXCEPT
Provide const iterator access to the end
Definition: bmsparsevec.h:559
back_insert_iterator get_back_inserter()
Provide back insert iterator Back insert iterator implements buffered insertion, which is faster,...
Definition: bmsparsevec.h:572
void resize_internal(size_type sz, bool set_null=true)
Definition: bmsparsevec.h:1001
static constexpr bool is_compressed() BMNOEXCEPT
various type traits
Definition: bmsparsevec.h:584
constexpr bool is_remap() const BMNOEXCEPT
Definition: bmsparsevec.h:1005
void inc_no_null(size_type idx, value_type v)
increment by v without chnaging NULL vector or size
Definition: bmsparsevec.h:2038
bool resolve_range(size_type from, size_type to, size_type *idx_from, size_type *idx_to) const BMNOEXCEPT
Definition: bmsparsevec.h:1022
friend back_insert_iterator
Definition: bmsparsevec.h:373
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)
Definition: bmsparsevec.h:1205
void inc_no_null(size_type idx)
Increment element by 1 without chnaging NULL vector or size.
Definition: bmsparsevec.h:2015
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.
Definition: bmsparsevec.h:1350
void push_back_null(size_type count)
push back specified amount of NULL values
Definition: bmsparsevec.h:1847
sparse_vector< Val, BV > & merge(sparse_vector< Val, BV > &sv)
merge with another sparse vector using OR operation Merge is different from join(),...
Definition: bmsparsevec.h:2154
void freeze()
Turn sparse vector into immutable mode Read-only (immutable) vector uses less memory and allows faste...
Definition: bmsparsevec.h:807
int compare(size_type idx, const value_type val) const BMNOEXCEPT
Compare vector element with argument.
Definition: bmsparsevec.h:2235
bool empty() const BMNOEXCEPT
return true if vector is empty
Definition: bmsparsevec.h:716
~sparse_vector() BMNOEXCEPT
Definition: bmsparsevec.h:1112
static bool find_rank(size_type rank, size_type &pos) BMNOEXCEPT
find position of compressed element by its rank
Definition: bmsparsevec.h:2055
void swap(sparse_vector< Val, BV > &sv) BMNOEXCEPT
content exchange
Definition: bmsparsevec.h:1118
void set_null(const bvector_type &bv_idx)
Set NULL all elements set as 1 in the argument vector.
Definition: bmsparsevec.h:537
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
Definition: bmsparsevec.h:1017
sparse_vector< Val, BV > & join(const sparse_vector< Val, BV > &sv)
join all with another sparse vector using OR operation
Definition: bmsparsevec.h:2127
static size_type translate_address(size_type i) BMNOEXCEPT
address translation for this type of container
Definition: bmsparsevec.h:931
void insert(size_type idx, value_type v)
insert specified element into container
Definition: bmsparsevec.h:1860
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)
Definition: bmsparsevec.h:1294
base_sparse_vector< Val, BV, 1 > parent_type
Definition: bmsparsevec.h:101
size_type extract_range(value_type *arr, size_type size, size_type offset, bool zero_mem=true) const
extract small window without use of masking vector
Definition: bmsparsevec.h:1516
void calc_stat(struct sparse_vector< Val, BV >::statistics *st) const BMNOEXCEPT
Calculates memory statistics.
Definition: bmsparsevec.h:2078
size_type extract_planes(value_type *arr, size_type size, size_type offset, bool zero_mem=true) const
extract medium window without use of masking vector
Definition: bmsparsevec.h:1601
static void throw_bad_alloc()
throw bad alloc
Definition: bmsparsevec.h:1138
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.
Definition: bmsparsevec.h:2209
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.
Definition: bmsparsevec.h:1187
void join_null_slice(const sparse_vector< Val, BV > &sv)
Definition: bmsparsevec.h:2170
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.
Definition: bmsparsevec.h:1082
void push_back_null()
push back NULL value
Definition: bmsparsevec.h:504
sparse_vector< Val, BV > & clear_range(size_type left, size_type right, bool set_null=false)
clear range (assign bit 0 for all planes)
Definition: bmsparsevec.h:2066
void erase(size_type idx, bool erase_null=true)
erase specified element from container
Definition: bmsparsevec.h:1919
size_type effective_size() const BMNOEXCEPT
size of sparse vector (may be different for RSC)
Definition: bmsparsevec.h:957
void clear() BMNOEXCEPT
resize to zero, free memory
Definition: bmsparsevec.h:690
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.
Definition: bmsparsevec.h:1338
value_type get_no_check(size_type idx) const BMNOEXCEPT
get specified element without checking boundary conditions
Definition: bmsparsevec.h:1752
const remap_matrix_type * get_remap_matrix() const
Definition: bmsparsevec.h:1019
bm::basic_bmatrix< BV > bmatrix_type
Definition: bmsparsevec.h:100
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...
Definition: bmsparsevec.h:545
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.
Definition: bmsparsevec.h:1643
size_type effective_vector_max() const BMNOEXCEPT
Always 1 (non-matrix type)
Definition: bmsparsevec.h:962
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
Definition: bmsparsevec.h:2194
const unsigned char * get_remap_buffer() const BMNOEXCEPT
Definition: bmsparsevec.h:1007
const_iterator get_const_iterator(size_type idx) const BMNOEXCEPT
Get const_itertor re-positioned to specific element.
Definition: bmsparsevec.h:565
parent_type::unsigned_value_type unsigned_value_type
Definition: bmsparsevec.h:102
const_iterator begin() const BMNOEXCEPT
Provide const iterator access to container content
Definition: bmsparsevec.h:2256
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.
Definition: bmsparsevec.h:1154
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)
Definition: bmsparsevec.h:1327
static void u2s_translate(value_type *arr, size_type sz) BMNOEXCEPT
Definition: bmsparsevec.h:1715
void filter(const bvector_type &bv_mask)
Apply value filter, defined by mask vector.
Definition: bmsparsevec.h:2221
const bvector_type * bvector_type_const_ptr
Definition: bmsparsevec.h:94
bool is_ro() const BMNOEXCEPT
Returns true if vector is read-only.
Definition: bmsparsevec.h:810
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.
Definition: bmsparsevec.h:2265
value_type operator[](size_type idx) const BMNOEXCEPT
get specified element without bounds checking
Definition: bmsparsevec.h:443
void optimize(bm::word_t *temp_block=0, typename bvector_type::optmode opt_mode=bvector_type::opt_compress, typename sparse_vector< Val, BV >::statistics *stat=0)
run memory optimization for all vector planes
Definition: bmsparsevec.h:2094
unsigned short bitscan(V w, B *bits) BMNOEXCEPT
Templated Bitscan with dynamic dispatch for best type.
Definition: bmfunc.h:761
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:9364
unsigned bit_scan_reverse(T value) BMNOEXCEPT
Definition: bmutil.h:453
sort_order
Sort order declaration.
Definition: bmconst.h:203
null_support
NULL-able value support.
Definition: bmconst.h:228
@ BM_UNSORTED
input set is NOT sorted
Definition: bmconst.h:204
@ BM_SORTED
input set is sorted (ascending order)
Definition: bmconst.h:205
@ BM_UNKNOWN
sort order unknown
Definition: bmconst.h:207
@ BM_SORTED_UNIFORM
sorted and in one block (internal!)
Definition: bmconst.h:206
@ use_null
support "non-assigned" or "NULL" logic
Definition: bmconst.h:229
@ no_null
do not support NULL values
Definition: bmconst.h:230
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:1784
Definition: bm.h:78
const unsigned set_array_mask
Definition: bmconst.h:97
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.
Definition: bmalgo_impl.h:1925
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:1697
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:9440
unsigned idx_arr_block_lookup_u32(const unsigned *idx, unsigned size, unsigned nb, unsigned start) BMNOEXCEPT
block boundaries look ahead U32
Definition: bmfunc.h:9466
const unsigned set_array_shift
Definition: bmconst.h:96
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
Structure with statistical information about memory allocation footprint, serialization projection,...
Definition: bmfunc.h:56
void reset() BMNOEXCEPT
Reset statisctics.
Definition: bmfunc.h:92
void add(const bv_statistics &st) BMNOEXCEPT
Sum data from another sttructure.
Definition: bmfunc.h:101
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