2626#include < stdexcept>
2727
2828#include " conditional_forward.hpp"
29+ #include " count_zeros.hpp"
2930#include " memory_operations.hpp"
3031#include " kll_helper.hpp"
3132
@@ -69,7 +70,7 @@ max_value_(nullptr),
6970is_level_zero_sorted_(other.is_level_zero_sorted_)
7071{
7172 items_ = allocator_.allocate (items_size_);
72- std::copy (other. items_ + levels_[0 ], other. items_ + levels_[num_levels_], items_ + levels_[ 0 ]);
73+ for ( auto i = levels_[0 ]; i < levels_[num_levels_]; ++i) new (&items_[i]) T (other. items_ [i ]);
7374 if (other.min_value_ != nullptr ) min_value_ = new (allocator_.allocate (1 )) T (*other.min_value_ );
7475 if (other.max_value_ != nullptr ) max_value_ = new (allocator_.allocate (1 )) T (*other.max_value_ );
7576}
@@ -147,6 +148,52 @@ kll_sketch<T, C, S, A>::~kll_sketch() {
147148 }
148149}
149150
151+ template <typename T, typename C, typename S, typename A>
152+ template <typename TT , typename CC , typename AA >
153+ kll_sketch<T, C, S, A>::kll_sketch(const kll_sketch<TT , CC , AA >& other, const A& allocator):
154+ allocator_ (allocator),
155+ k_(other.get_k()),
156+ m_(DEFAULT_M ),
157+ min_k_(other.get_min_k()),
158+ n_(other.get_n()),
159+ num_levels_(1 ),
160+ levels_(2 , 0 , allocator),
161+ items_(nullptr ),
162+ items_size_(other.get_capacity()),
163+ min_value_(nullptr ),
164+ max_value_(nullptr ),
165+ is_level_zero_sorted_(false )
166+ {
167+ static_assert (
168+ std::is_constructible<T, TT >::value,
169+ " Type converting constructor requires new type to be constructible from existing type"
170+ );
171+ items_ = allocator_.allocate (items_size_);
172+ levels_[0 ] = items_size_ - other.get_num_retained ();
173+ levels_[1 ] = items_size_;
174+
175+ if (!other.is_empty ()) {
176+ min_value_ = new (allocator_.allocate (1 )) T (other.get_min_value ());
177+ max_value_ = new (allocator_.allocate (1 )) T (other.get_max_value ());
178+ size_t index = levels_[0 ];
179+ for (auto pair: other) {
180+ new (&items_[index]) T (pair.first );
181+ const uint8_t level = count_trailing_zeros_in_u64 (pair.second );
182+ if (level == num_levels_) {
183+ ++num_levels_;
184+ levels_.resize (num_levels_ + 1 );
185+ levels_[level] = index;
186+ levels_[num_levels_] = items_size_;
187+ } else if (level < num_levels_ - 1 || level > num_levels_) {
188+ throw std::invalid_argument (" corrupt source sketch" );
189+ }
190+ ++index;
191+ }
192+ }
193+ check_sorting ();
194+ assert_correct_total_weight ();
195+ }
196+
150197template <typename T, typename C, typename S, typename A>
151198template <typename FwdT>
152199void kll_sketch<T, C, S, A>::update(FwdT&& value) {
@@ -210,6 +257,11 @@ uint16_t kll_sketch<T, C, S, A>::get_k() const {
210257 return k_;
211258}
212259
260+ template <typename T, typename C, typename S, typename A>
261+ uint16_t kll_sketch<T, C, S, A>::get_min_k() const {
262+ return min_k_;
263+ }
264+
213265template <typename T, typename C, typename S, typename A>
214266uint64_t kll_sketch<T, C, S, A>::get_n() const {
215267 return n_;
@@ -220,6 +272,11 @@ uint32_t kll_sketch<T, C, S, A>::get_num_retained() const {
220272 return levels_[num_levels_] - levels_[0 ];
221273}
222274
275+ template <typename T, typename C, typename S, typename A>
276+ uint32_t kll_sketch<T, C, S, A>::get_capacity() const {
277+ return items_size_;
278+ }
279+
223280template <typename T, typename C, typename S, typename A>
224281bool kll_sketch<T, C, S, A>::is_estimation_mode() const {
225282 return num_levels_ > 1 ;
@@ -780,17 +837,27 @@ void kll_sketch<T, C, S, A>::sort_level_zero() {
780837 }
781838}
782839
840+ template <typename T, typename C, typename S, typename A>
841+ void kll_sketch<T, C, S, A>::check_sorting() const {
842+ // not checking level 0
843+ for (uint8_t level = 1 ; level < num_levels_; ++level) {
844+ const auto from = items_ + levels_[level];
845+ const auto to = items_ + levels_[level + 1 ];
846+ if (!std::is_sorted (from, to, C ())) {
847+ throw std::logic_error (" levels must be sorted" );
848+ }
849+ }
850+ }
851+
783852template <typename T, typename C, typename S, typename A>
784853template <bool inclusive>
785854quantile_sketch_sorted_view<T, C, A> kll_sketch<T, C, S, A>::get_sorted_view(bool cumulative) const {
786855 const_cast <kll_sketch*>(this )->sort_level_zero (); // allow this side effect
787856 quantile_sketch_sorted_view<T, C, A> view (get_num_retained (), allocator_);
788- uint8_t level = 0 ;
789- while (level < num_levels_) {
857+ for (uint8_t level = 0 ; level < num_levels_; ++level) {
790858 const auto from = items_ + levels_[level];
791859 const auto to = items_ + levels_[level + 1 ]; // exclusive
792860 view.add (from, to, 1 << level);
793- ++level;
794861 }
795862 if (cumulative) view.template convert_to_cummulative <inclusive>();
796863 return view;
0 commit comments