20#ifndef REQ_SKETCH_IMPL_HPP_
21#define REQ_SKETCH_IMPL_HPP_
29template<
typename T,
typename C,
typename A>
30req_sketch<T, C, A>::req_sketch(uint16_t k,
bool hra,
const C& comparator,
const A& allocator):
31comparator_(comparator),
33k_(std::max<uint16_t>(static_cast<int>(k) & -2, static_cast<int>(
req_constants::
MIN_K))),
38compactors_(allocator),
43 if (k > req_constants::MAX_K) {
44 throw std::invalid_argument(
"K must be <= " + std::to_string(req_constants::MAX_K) +
": " + std::to_string(k));
49template<
typename T,
typename C,
typename A>
50req_sketch<T, C, A>::~req_sketch() {
54template<
typename T,
typename C,
typename A>
55req_sketch<T, C, A>::req_sketch(
const req_sketch& other):
56comparator_(other.comparator_),
57allocator_(other.allocator_),
60max_nom_size_(other.max_nom_size_),
61num_retained_(other.num_retained_),
63compactors_(other.compactors_),
64min_item_(other.min_item_),
65max_item_(other.max_item_),
69template<
typename T,
typename C,
typename A>
70req_sketch<T, C, A>::req_sketch(req_sketch&& other) noexcept :
71comparator_(std::move(other.comparator_)),
72allocator_(std::move(other.allocator_)),
75max_nom_size_(other.max_nom_size_),
76num_retained_(other.num_retained_),
78compactors_(std::move(other.compactors_)),
79min_item_(std::move(other.min_item_)),
80max_item_(std::move(other.max_item_)),
84template<
typename T,
typename C,
typename A>
86 req_sketch copy(other);
87 std::swap(comparator_, copy.comparator_);
88 std::swap(allocator_, copy.allocator_);
89 std::swap(k_, copy.k_);
90 std::swap(hra_, copy.hra_);
91 std::swap(max_nom_size_, copy.max_nom_size_);
92 std::swap(num_retained_, copy.num_retained_);
93 std::swap(n_, copy.n_);
94 std::swap(compactors_, copy.compactors_);
95 std::swap(min_item_, copy.min_item_);
96 std::swap(max_item_, copy.max_item_);
101template<
typename T,
typename C,
typename A>
103 std::swap(comparator_, other.comparator_);
104 std::swap(allocator_, other.allocator_);
105 std::swap(k_, other.k_);
106 std::swap(hra_, other.hra_);
107 std::swap(max_nom_size_, other.max_nom_size_);
108 std::swap(num_retained_, other.num_retained_);
109 std::swap(n_, other.n_);
110 std::swap(compactors_, other.compactors_);
111 std::swap(min_item_, other.min_item_);
112 std::swap(max_item_, other.max_item_);
117template<
typename T,
typename C,
typename A>
118template<
typename TT,
typename CC,
typename AA>
119req_sketch<T, C, A>::req_sketch(
const req_sketch<TT, CC, AA>& other,
const C& comparator,
const A& allocator):
120comparator_(comparator),
121allocator_(allocator),
124max_nom_size_(other.max_nom_size_),
125num_retained_(other.num_retained_),
127compactors_(allocator),
128min_item_(other.min_item_),
129max_item_(other.max_item_),
133 std::is_constructible<T, TT>::value,
134 "Type converting constructor requires new type to be constructible from existing type"
136 compactors_.reserve(other.compactors_.size());
137 for (
const auto& compactor: other.compactors_) {
138 compactors_.push_back(req_compactor<T, C, A>(compactor, comparator_, allocator_));
142template<
typename T,
typename C,
typename A>
147template<
typename T,
typename C,
typename A>
152template<
typename T,
typename C,
typename A>
157template<
typename T,
typename C,
typename A>
162template<
typename T,
typename C,
typename A>
164 return num_retained_;
167template<
typename T,
typename C,
typename A>
169 return compactors_.size() > 1;
172template<
typename T,
typename C,
typename A>
173template<
typename FwdT>
175 if (!check_update_item(item)) {
return; }
177 min_item_.emplace(item);
178 max_item_.emplace(item);
180 if (comparator_(item, *min_item_)) *min_item_ = item;
181 if (comparator_(*max_item_, item)) *max_item_ = item;
183 compactors_[0].append(std::forward<FwdT>(item));
186 if (num_retained_ == max_nom_size_) compress();
190template<
typename T,
typename C,
typename A>
191template<
typename FwdSk>
193 if (
is_HRA() != other.
is_HRA())
throw std::invalid_argument(
"merging HRA and LRA is not valid");
196 min_item_.emplace(conditional_forward<FwdSk>(*other.min_item_));
197 max_item_.emplace(conditional_forward<FwdSk>(*other.max_item_));
199 if (comparator_(*other.min_item_, *min_item_)) *min_item_ = conditional_forward<FwdSk>(*other.min_item_);
200 if (comparator_(*max_item_, *other.max_item_)) *max_item_ = conditional_forward<FwdSk>(*other.max_item_);
203 while (get_num_levels() < other.get_num_levels()) grow();
205 for (
size_t i = 0; i < other.get_num_levels(); ++i) {
206 compactors_[i].merge(conditional_forward<FwdSk>(other.compactors_[i]));
209 update_max_nom_size();
210 update_num_retained();
211 if (num_retained_ >= max_nom_size_) compress();
215template<
typename T,
typename C,
typename A>
217 if (
is_empty())
throw std::runtime_error(
"operation is undefined for an empty sketch");
221template<
typename T,
typename C,
typename A>
223 if (
is_empty())
throw std::runtime_error(
"operation is undefined for an empty sketch");
227template<
typename T,
typename C,
typename A>
232template<
typename T,
typename C,
typename A>
237template<
typename T,
typename C,
typename A>
239 if (
is_empty())
throw std::runtime_error(
"operation is undefined for an empty sketch");
241 for (
const auto& compactor: compactors_) {
242 weight += compactor.compute_weight(item, inclusive);
244 return static_cast<double>(weight) / n_;
247template<
typename T,
typename C,
typename A>
249 if (
is_empty())
throw std::runtime_error(
"operation is undefined for an empty sketch");
251 return sorted_view_->get_PMF(split_points, size, inclusive);
254template<
typename T,
typename C,
typename A>
256 if (
is_empty())
throw std::runtime_error(
"operation is undefined for an empty sketch");
258 return sorted_view_->get_CDF(split_points, size, inclusive);
261template<
typename T,
typename C,
typename A>
263 if (
is_empty())
throw std::runtime_error(
"operation is undefined for an empty sketch");
264 if ((rank < 0.0) || (rank > 1.0)) {
265 throw std::invalid_argument(
"Normalized rank cannot be less than 0 or greater than 1");
269 return sorted_view_->get_quantile(rank, inclusive);
272template<
typename T,
typename C,
typename A>
274 if (!compactors_[0].is_sorted()) {
275 const_cast<Compactor&
>(compactors_[0]).sort();
279 for (
auto& compactor: compactors_) {
280 view.add(compactor.begin(), compactor.end(), 1ULL << compactor.get_lg_weight());
283 view.convert_to_cummulative();
287template<
typename T,
typename C,
typename A>
289 return get_rank_lb(
get_k(), get_num_levels(), rank, num_std_dev,
get_n(), hra_);
292template<
typename T,
typename C,
typename A>
294 return get_rank_ub(
get_k(), get_num_levels(), rank, num_std_dev,
get_n(), hra_);
297template<
typename T,
typename C,
typename A>
299 return get_rank_ub(k, 2, rank, 1, n, hra) - rank;
302template<
typename T,
typename C,
typename A>
303double req_sketch<T, C, A>::get_rank_lb(uint16_t k, uint8_t num_levels,
double rank, uint8_t num_std_dev, uint64_t n,
bool hra) {
304 if (is_exact_rank(k, num_levels, rank, n, hra))
return rank;
305 const double relative = relative_rse_factor() / k * (hra ? 1.0 - rank : rank);
306 const double fixed = FIXED_RSE_FACTOR / k;
307 const double lb_rel = rank - num_std_dev * relative;
308 const double lb_fix = rank - num_std_dev * fixed;
309 return std::max(lb_rel, lb_fix);
312template<
typename T,
typename C,
typename A>
313double req_sketch<T, C, A>::get_rank_ub(uint16_t k, uint8_t num_levels,
double rank, uint8_t num_std_dev, uint64_t n,
bool hra) {
314 if (is_exact_rank(k, num_levels, rank, n, hra))
return rank;
315 const double relative = relative_rse_factor() / k * (hra ? 1.0 - rank : rank);
316 const double fixed = FIXED_RSE_FACTOR / k;
317 const double ub_rel = rank + num_std_dev * relative;
318 const double ub_fix = rank + num_std_dev * fixed;
319 return std::min(ub_rel, ub_fix);
322template<
typename T,
typename C,
typename A>
323bool req_sketch<T, C, A>::is_exact_rank(uint16_t k, uint8_t num_levels,
double rank, uint64_t n,
bool hra) {
325 if (num_levels == 1 || n <= base_cap)
return true;
326 const double exact_rank_thresh =
static_cast<double>(base_cap) / n;
327 return (hra && rank >= 1.0 - exact_rank_thresh) || (!hra && rank <= exact_rank_thresh);
330template<
typename T,
typename C,
typename A>
331double req_sketch<T, C, A>::relative_rse_factor() {
336template<
typename T,
typename C,
typename A>
337template<typename TT, typename SerDe, typename std::enable_if<std::is_arithmetic<TT>::value,
int>::type>
339 size_t size = PREAMBLE_SIZE_BYTES;
342 size +=
sizeof(n_) +
sizeof(TT) * 2;
347 for (
const auto& compactor: compactors_) size += compactor.get_serialized_size_bytes(sd);
353template<
typename T,
typename C,
typename A>
354template<typename TT, typename SerDe, typename std::enable_if<!std::is_arithmetic<TT>::value,
int>::type>
356 size_t size = PREAMBLE_SIZE_BYTES;
357 if (is_empty())
return size;
358 if (is_estimation_mode()) {
360 size += sd.size_of_item(*min_item_);
361 size += sd.size_of_item(*max_item_);
364 size += sd.size_of_item(*compactors_[0].begin());
366 for (
const auto& compactor: compactors_) size += compactor.get_serialized_size_bytes(sd);
371template<
typename T,
typename C,
typename A>
372template<
typename SerDe>
375 write(os, preamble_ints);
376 const uint8_t serial_version = SERIAL_VERSION;
377 write(os, serial_version);
378 const uint8_t family = FAMILY;
381 const uint8_t flags_byte(
382 (
is_empty() ? 1 << flags::IS_EMPTY : 0)
383 | (hra_ ? 1 << flags::IS_HIGH_RANK : 0)
384 | (raw_items ? 1 << flags::RAW_ITEMS : 0)
385 | (compactors_[0].is_sorted() ? 1 << flags::IS_LEVEL_ZERO_SORTED : 0)
387 write(os, flags_byte);
389 const uint8_t num_levels =
is_empty() ? 0 : get_num_levels();
390 write(os, num_levels);
391 const uint8_t num_raw_items = raw_items ?
static_cast<uint8_t
>(n_) : 0;
392 write(os, num_raw_items);
396 sd.serialize(os, &*min_item_, 1);
397 sd.serialize(os, &*max_item_, 1);
400 sd.serialize(os, compactors_[0].
begin(), num_raw_items);
402 for (
const auto& compactor: compactors_) compactor.serialize(os, sd);
406template<
typename T,
typename C,
typename A>
407template<
typename SerDe>
409 const size_t size = header_size_bytes + get_serialized_size_bytes(sd);
410 vector_bytes bytes(size, 0, allocator_);
411 uint8_t* ptr = bytes.data() + header_size_bytes;
412 const uint8_t* end_ptr = ptr + size;
414 const uint8_t preamble_ints = is_estimation_mode() ? 4 : 2;
415 ptr += copy_to_mem(preamble_ints, ptr);
416 const uint8_t serial_version = SERIAL_VERSION;
417 ptr += copy_to_mem(serial_version, ptr);
418 const uint8_t family = FAMILY;
419 ptr += copy_to_mem(family, ptr);
421 const uint8_t flags_byte(
422 (is_empty() ? 1 << flags::IS_EMPTY : 0)
423 | (hra_ ? 1 << flags::IS_HIGH_RANK : 0)
424 | (raw_items ? 1 << flags::RAW_ITEMS : 0)
425 | (compactors_[0].is_sorted() ? 1 << flags::IS_LEVEL_ZERO_SORTED : 0)
427 ptr += copy_to_mem(flags_byte, ptr);
428 ptr += copy_to_mem(k_, ptr);
429 const uint8_t num_levels = is_empty() ? 0 : get_num_levels();
430 ptr += copy_to_mem(num_levels, ptr);
431 const uint8_t num_raw_items = raw_items ?
static_cast<uint8_t
>(n_) : 0;
432 ptr += copy_to_mem(num_raw_items, ptr);
434 if (is_estimation_mode()) {
435 ptr += copy_to_mem(n_, ptr);
436 ptr += sd.serialize(ptr, end_ptr - ptr, &*min_item_, 1);
437 ptr += sd.serialize(ptr, end_ptr - ptr, &*max_item_, 1);
440 ptr += sd.serialize(ptr, end_ptr - ptr, compactors_[0].begin(), num_raw_items);
442 for (
const auto& compactor: compactors_) ptr += compactor.serialize(ptr, end_ptr - ptr, sd);
448template<
typename T,
typename C,
typename A>
449template<
typename SerDe>
451 const auto preamble_ints = read<uint8_t>(is);
452 const auto serial_version = read<uint8_t>(is);
453 const auto family_id = read<uint8_t>(is);
454 const auto flags_byte = read<uint8_t>(is);
455 const auto k = read<uint16_t>(is);
456 const auto num_levels = read<uint8_t>(is);
457 const auto num_raw_items = read<uint8_t>(is);
460 check_preamble_ints(preamble_ints, num_levels);
461 check_serial_version(serial_version);
462 check_family_id(family_id);
464 if (!is.good())
throw std::runtime_error(
"error reading from std::istream");
465 const bool is_empty = flags_byte & (1 << flags::IS_EMPTY);
466 const bool hra = flags_byte & (1 << flags::IS_HIGH_RANK);
467 if (is_empty)
return req_sketch(k, hra, comparator, allocator);
469 optional<T> min_item;
470 optional<T> max_item;
472 const bool raw_items = flags_byte & (1 << flags::RAW_ITEMS);
473 check_num_levels(num_levels, raw_items);
474 const bool is_level_0_sorted = flags_byte & (1 << flags::IS_LEVEL_ZERO_SORTED);
475 std::vector<Compactor, AllocCompactor> compactors(allocator);
478 if (num_levels > 1) {
479 n = read<uint64_t>(is);
482 typename std::aligned_storage<
sizeof(T),
alignof(T)>::type tmp_storage;
483 T* tmp =
reinterpret_cast<T*
>(&tmp_storage);
485 sd.deserialize(is, tmp, 1);
487 min_item.emplace(std::move(*tmp));
489 sd.deserialize(is, tmp, 1);
491 max_item.emplace(std::move(*tmp));
496 compactors.push_back(Compactor::deserialize(is, sd, comparator, allocator, is_level_0_sorted, k, num_raw_items, hra));
498 for (
size_t i = 0; i < num_levels; ++i) {
499 compactors.push_back(Compactor::deserialize(is, sd, comparator, allocator, i == 0 ? is_level_0_sorted :
true, hra,
500 k,
static_cast<uint8_t
>(i)));
503 if (num_levels == 1) {
504 if (compactors[0].get_num_items() == 0)
throw std::invalid_argument(
"Possible corruption: non-empty sketch with no items");
505 const auto begin = compactors[0].begin();
506 const auto end = compactors[0].end();
507 n = compactors[0].get_num_items();
510 for (
auto it = begin; it != end; ++it) {
511 if (comparator(*it, *min_it)) min_it = it;
512 if (comparator(*max_it, *it)) max_it = it;
514 min_item.emplace(*min_it);
515 max_item.emplace(*max_it);
518 if (!is.good())
throw std::runtime_error(
"error reading from std::istream");
519 return req_sketch(k, hra, n, std::move(min_item), std::move(max_item), std::move(compactors), comparator);
522template<
typename T,
typename C,
typename A>
523template<
typename SerDe>
525 ensure_minimum_memory(size, 8);
526 const char* ptr =
static_cast<const char*
>(bytes);
527 const char* end_ptr =
static_cast<const char*
>(bytes) + size;
529 uint8_t preamble_ints;
530 ptr += copy_from_mem(ptr, preamble_ints);
531 uint8_t serial_version;
532 ptr += copy_from_mem(ptr, serial_version);
534 ptr += copy_from_mem(ptr, family_id);
536 ptr += copy_from_mem(ptr, flags_byte);
538 ptr += copy_from_mem(ptr, k);
540 ptr += copy_from_mem(ptr, num_levels);
541 uint8_t num_raw_items;
542 ptr += copy_from_mem(ptr, num_raw_items);
545 check_preamble_ints(preamble_ints, num_levels);
546 check_serial_version(serial_version);
547 check_family_id(family_id);
549 const bool is_empty = flags_byte & (1 << flags::IS_EMPTY);
550 const bool hra = flags_byte & (1 << flags::IS_HIGH_RANK);
551 if (is_empty)
return req_sketch(k, hra, comparator, allocator);
553 optional<T> min_item;
554 optional<T> max_item;
556 const bool raw_items = flags_byte & (1 << flags::RAW_ITEMS);
557 check_num_levels(num_levels, raw_items);
558 const bool is_level_0_sorted = flags_byte & (1 << flags::IS_LEVEL_ZERO_SORTED);
559 std::vector<Compactor, AllocCompactor> compactors(allocator);
562 if (num_levels > 1) {
563 ensure_minimum_memory(end_ptr - ptr,
sizeof(n));
564 ptr += copy_from_mem(ptr, n);
567 typename std::aligned_storage<
sizeof(T),
alignof(T)>::type tmp_storage;
568 T* tmp =
reinterpret_cast<T*
>(&tmp_storage);
570 ptr += sd.deserialize(ptr, end_ptr - ptr, tmp, 1);
572 min_item.emplace(std::move(*tmp));
574 ptr += sd.deserialize(ptr, end_ptr - ptr, tmp, 1);
576 max_item.emplace(std::move(*tmp));
581 auto pair = Compactor::deserialize(ptr, end_ptr - ptr, sd, comparator, allocator, is_level_0_sorted, k, num_raw_items, hra);
582 compactors.push_back(std::move(pair.first));
585 for (
size_t i = 0; i < num_levels; ++i) {
586 auto pair = Compactor::deserialize(ptr, end_ptr - ptr, sd, comparator, allocator, i == 0 ? is_level_0_sorted :
true, hra,
587 k,
static_cast<uint8_t
>(i));
588 compactors.push_back(std::move(pair.first));
592 if (num_levels == 1) {
593 if (compactors[0].get_num_items() == 0)
throw std::invalid_argument(
"Possible corruption: non-empty sketch with no items");
594 const auto begin = compactors[0].begin();
595 const auto end = compactors[0].end();
596 n = compactors[0].get_num_items();
599 for (
auto it = begin; it != end; ++it) {
600 if (comparator(*it, *min_it)) min_it = it;
601 if (comparator(*max_it, *it)) max_it = it;
603 min_item.emplace(*min_it);
604 max_item.emplace(*max_it);
607 return req_sketch(k, hra, n, std::move(min_item), std::move(max_item), std::move(compactors), comparator);
610template<
typename T,
typename C,
typename A>
611void req_sketch<T, C, A>::grow() {
612 const uint8_t lg_weight = get_num_levels();
613 compactors_.push_back(Compactor(hra_, lg_weight, k_, comparator_, allocator_));
614 update_max_nom_size();
617template<
typename T,
typename C,
typename A>
618uint8_t req_sketch<T, C, A>::get_num_levels()
const {
619 return static_cast<uint8_t
>(compactors_.size());
622template<
typename T,
typename C,
typename A>
623void req_sketch<T, C, A>::update_max_nom_size() {
625 for (
const auto& compactor: compactors_) max_nom_size_ += compactor.get_nom_capacity();
628template<
typename T,
typename C,
typename A>
629void req_sketch<T, C, A>::update_num_retained() {
631 for (
const auto& compactor: compactors_) num_retained_ += compactor.get_num_items();
634template<
typename T,
typename C,
typename A>
635void req_sketch<T, C, A>::compress() {
636 for (
size_t h = 0; h < compactors_.size(); ++h) {
637 if (compactors_[h].get_num_items() >= compactors_[h].get_nom_capacity()) {
638 if (h == 0) compactors_[0].sort();
639 if (h + 1 >= get_num_levels()) {
642 auto pair = compactors_[h].compact(compactors_[h + 1]);
643 num_retained_ -= pair.first;
644 max_nom_size_ += pair.second;
645 if (LAZY_COMPRESSION && num_retained_ < max_nom_size_)
break;
650template<
typename T,
typename C,
typename A>
654 std::ostringstream os;
655 os <<
"### REQ sketch summary:" << std::endl;
656 os <<
" K : " << k_ << std::endl;
657 os <<
" High Rank Acc : " << (hra_ ?
"true" :
"false") << std::endl;
658 os <<
" Empty : " << (
is_empty() ?
"true" :
"false") << std::endl;
660 os <<
" Sorted : " << (compactors_[0].is_sorted() ?
"true" :
"false") << std::endl;
661 os <<
" N : " << n_ << std::endl;
662 os <<
" Levels : " << compactors_.size() << std::endl;
663 os <<
" Retained items : " << num_retained_ << std::endl;
664 os <<
" Capacity items : " << max_nom_size_ << std::endl;
666 os <<
" Min item : " << *min_item_ << std::endl;
667 os <<
" Max item : " << *max_item_ << std::endl;
669 os <<
"### End sketch summary" << std::endl;
672 os <<
"### REQ sketch levels:" << std::endl;
673 os <<
" index: nominal capacity, actual size" << std::endl;
674 for (uint8_t i = 0; i < compactors_.size(); i++) {
675 os <<
" " << (
unsigned int) i <<
": "
676 << compactors_[i].get_nom_capacity() <<
", "
677 << compactors_[i].get_num_items() << std::endl;
679 os <<
"### End sketch levels" << std::endl;
683 os <<
"### REQ sketch data:" << std::endl;
685 for (
const auto& compactor: compactors_) {
686 os <<
" level " << level <<
": " << std::endl;
687 for (
auto it = compactor.begin(); it != compactor.end(); ++it) {
688 os <<
" " << *it << std::endl;
692 os <<
"### End sketch data" << std::endl;
694 return string<A>(os.str().c_str(), allocator_);
697template<
typename T,
typename C,
typename A>
698req_sketch<T, C, A>::req_sketch(uint16_t k,
bool hra, uint64_t n,
699 optional<T>&& min_item, optional<T>&& max_item,
700 std::vector<Compactor, AllocCompactor>&& compactors,
const C& comparator):
701comparator_(comparator),
702allocator_(compactors.get_allocator()),
708compactors_(std::move(compactors)),
709min_item_(std::move(min_item)),
710max_item_(std::move(max_item)),
713 update_max_nom_size();
714 update_num_retained();
717template<
typename T,
typename C,
typename A>
718void req_sketch<T, C, A>::check_k(uint16_t k) {
720 throw std::invalid_argument(
"Possible corruption: k must be even and in the range ["
725template<
typename T,
typename C,
typename A>
726void req_sketch<T, C, A>::check_num_levels(uint8_t num_levels,
bool raw_items) {
728 if (num_levels == 0 || (raw_items && num_levels != 1)) {
729 throw std::invalid_argument(
"Possible corruption: number of levels " + std::to_string(num_levels)
730 + (raw_items ?
" with raw items" :
""));
734template<
typename T,
typename C,
typename A>
735void req_sketch<T, C, A>::check_preamble_ints(uint8_t preamble_ints, uint8_t num_levels) {
736 const uint8_t expected_preamble_ints = num_levels > 1 ? 4 : 2;
737 if (preamble_ints != expected_preamble_ints) {
738 throw std::invalid_argument(
"Possible corruption: preamble ints must be "
739 + std::to_string(expected_preamble_ints) +
", got " + std::to_string(preamble_ints));
743template<
typename T,
typename C,
typename A>
744void req_sketch<T, C, A>::check_serial_version(uint8_t serial_version) {
745 if (serial_version != SERIAL_VERSION) {
746 throw std::invalid_argument(
"Possible corruption: serial version mismatch: expected "
747 + std::to_string(SERIAL_VERSION)
748 +
", got " + std::to_string(serial_version));
752template<
typename T,
typename C,
typename A>
753void req_sketch<T, C, A>::check_family_id(uint8_t family_id) {
754 if (family_id != FAMILY) {
755 throw std::invalid_argument(
"Possible corruption: family mismatch: expected "
756 + std::to_string(FAMILY) +
", got " + std::to_string(family_id));
760template<
typename T,
typename C,
typename A>
762 return const_iterator(compactors_.begin(), compactors_.end());
765template<
typename T,
typename C,
typename A>
767 return const_iterator(compactors_.end(), compactors_.end());
770template<
typename T,
typename C,
typename A>
771void req_sketch<T, C, A>::setup_sorted_view()
const {
772 if (sorted_view_ ==
nullptr) {
773 using AllocSortedView =
typename std::allocator_traits<A>::template rebind_alloc<quantiles_sorted_view<T, C, A>>;
778template<
typename T,
typename C,
typename A>
779void req_sketch<T, C, A>::reset_sorted_view() {
780 if (sorted_view_ !=
nullptr) {
781 sorted_view_->~quantiles_sorted_view();
782 using AllocSortedView =
typename std::allocator_traits<A>::template rebind_alloc<quantiles_sorted_view<T, C, A>>;
783 AllocSortedView(allocator_).deallocate(sorted_view_, 1);
784 sorted_view_ =
nullptr;
790template<
typename T,
typename C,
typename A>
791req_sketch<T, C, A>::const_iterator::const_iterator(LevelsIterator begin, LevelsIterator end):
794 compactor_it_(begin == end ? nullptr : (*levels_it_).begin())
797template<
typename T,
typename C,
typename A>
798auto req_sketch<T, C, A>::const_iterator::operator++() -> const_iterator& {
800 if (compactor_it_ == (*levels_it_).end()) {
802 if (levels_it_ != levels_end_) compactor_it_ = (*levels_it_).begin();
807template<
typename T,
typename C,
typename A>
808auto req_sketch<T, C, A>::const_iterator::operator++(
int) -> const_iterator& {
809 const_iterator tmp(*
this);
814template<
typename T,
typename C,
typename A>
815bool req_sketch<T, C, A>::const_iterator::operator==(
const const_iterator& other)
const {
816 if (levels_it_ != other.levels_it_)
return false;
817 if (levels_it_ == levels_end_)
return true;
818 return compactor_it_ == other.compactor_it_;
821template<
typename T,
typename C,
typename A>
822bool req_sketch<T, C, A>::const_iterator::operator!=(
const const_iterator& other)
const {
823 return !operator==(other);
826template<
typename T,
typename C,
typename A>
827auto req_sketch<T, C, A>::const_iterator::operator*() const -> reference {
828 return value_type(*compactor_it_, 1ULL << (*levels_it_).get_lg_weight());
831template<
typename T,
typename C,
typename A>
832auto req_sketch<T, C, A>::const_iterator::operator->() const -> pointer {
Sorted view for quantiles sketches (REQ, KLL and Quantiles).
Definition quantiles_sorted_view.hpp:38
Relative Error Quantiles Sketch.
Definition req_sketch.hpp:84
Comparator get_comparator() const
Returns an instance of the comparator for this sketch.
Definition req_sketch_impl.hpp:228
quantiles_sorted_view< T, Comparator, Allocator > get_sorted_view() const
Gets the sorted view of this sketch.
Definition req_sketch_impl.hpp:273
static req_sketch deserialize(std::istream &is, const SerDe &sd=SerDe(), const Comparator &comparator=Comparator(), const Allocator &allocator=Allocator())
This method deserializes a sketch from a given stream.
vector_double get_CDF(const T *split_points, uint32_t size, bool inclusive=true) const
Returns an approximation to the Cumulative Distribution Function (CDF), which is the cumulative analo...
Definition req_sketch_impl.hpp:255
uint32_t get_num_retained() const
Returns the number of retained items in the sketch.
Definition req_sketch_impl.hpp:163
vector_double get_PMF(const T *split_points, uint32_t size, bool inclusive=true) const
Returns an approximation to the Probability Mass Function (PMF) of the input stream given a set of sp...
Definition req_sketch_impl.hpp:248
void merge(FwdSk &&other)
Merges another sketch into this one.
Definition req_sketch_impl.hpp:192
typename quantiles_sorted_view< T, Comparator, Allocator >::quantile_return_type quantile_return_type
Quantile return type.
Definition req_sketch.hpp:97
void update(FwdT &&item)
Updates this sketch with the given data item.
Definition req_sketch_impl.hpp:174
void serialize(std::ostream &os, const SerDe &sd=SerDe()) const
This method serializes the sketch into a given stream in a binary form.
Definition req_sketch_impl.hpp:373
string< Allocator > to_string(bool print_levels=false, bool print_items=false) const
Prints a summary of the sketch.
Definition req_sketch_impl.hpp:651
uint16_t get_k() const
Returns configured parameter K.
Definition req_sketch_impl.hpp:143
bool is_empty() const
Returns true if this sketch is empty.
Definition req_sketch_impl.hpp:153
const T & get_max_item() const
Returns the max item of the stream.
Definition req_sketch_impl.hpp:222
double get_rank_upper_bound(double rank, uint8_t num_std_dev) const
Returns an approximate upper bound of the given normalized rank.
Definition req_sketch_impl.hpp:293
double get_rank(const T &item, bool inclusive=true) const
Returns an approximation to the normalized rank of the given item from 0 to 1 inclusive.
Definition req_sketch_impl.hpp:238
static double get_RSE(uint16_t k, double rank, bool hra, uint64_t n)
Returns an a priori estimate of relative standard error (RSE, expressed as a number in [0,...
Definition req_sketch_impl.hpp:298
double get_rank_lower_bound(double rank, uint8_t num_std_dev) const
Returns an approximate lower bound of the given normalized rank.
Definition req_sketch_impl.hpp:288
Allocator get_allocator() const
Returns an instance of the allocator for this sketch.
Definition req_sketch_impl.hpp:233
req_sketch & operator=(const req_sketch &other)
Copy assignment.
Definition req_sketch_impl.hpp:85
quantile_return_type get_quantile(double rank, bool inclusive=true) const
Returns an approximate quantile of the given normalized rank.
Definition req_sketch_impl.hpp:262
const_iterator begin() const
Iterator pointing to the first item in the sketch.
Definition req_sketch_impl.hpp:761
size_t get_serialized_size_bytes(const SerDe &sd=SerDe()) const
Computes size needed to serialize the current state of the sketch.
Definition req_sketch_impl.hpp:338
const_iterator end() const
Iterator pointing to the past-the-end item in the sketch.
Definition req_sketch_impl.hpp:766
bool is_estimation_mode() const
Returns true if this sketch is in estimation mode.
Definition req_sketch_impl.hpp:168
const T & get_min_item() const
Returns the min item of the stream.
Definition req_sketch_impl.hpp:216
bool is_HRA() const
Returns configured parameter High Rank Accuracy.
Definition req_sketch_impl.hpp:148
uint64_t get_n() const
Returns the length of the input stream.
Definition req_sketch_impl.hpp:158
const uint16_t MIN_K
min value of parameter K
Definition kll_sketch.hpp:39
REQ sketch constants.
Definition req_common.hpp:31
const uint8_t INIT_NUM_SECTIONS
initial number of sections
Definition req_common.hpp:37
const uint16_t MAX_K
maximum value of parameter K
Definition req_common.hpp:35
const uint16_t MIN_K
minimum value of parameter K
Definition req_common.hpp:33
DataSketches namespace.
Definition binomial_bounds.hpp:38