You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by al...@apache.org on 2020/11/19 00:05:54 UTC
[incubator-datasketches-cpp] 02/02: fixed quantile calculator
This is an automated email from the ASF dual-hosted git repository.
alsay pushed a commit to branch req_sketch
in repository https://gitbox.apache.org/repos/asf/incubator-datasketches-cpp.git
commit 255c2d0abba97282057012ffe3a469e2e0840b4a
Author: AlexanderSaydakov <Al...@users.noreply.github.com>
AuthorDate: Wed Nov 18 16:05:39 2020 -0800
fixed quantile calculator
---
req/include/req_quantile_calculator.hpp | 8 ++++++++
req/include/req_quantile_calculator_impl.hpp | 18 +++++++++---------
req/include/req_sketch_impl.hpp | 2 +-
req/test/req_sketch_test.cpp | 5 +++--
4 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/req/include/req_quantile_calculator.hpp b/req/include/req_quantile_calculator.hpp
index ccf901c..f6cc13e 100755
--- a/req/include/req_quantile_calculator.hpp
+++ b/req/include/req_quantile_calculator.hpp
@@ -26,6 +26,7 @@ namespace datasketches {
template<
typename T,
+ typename Comparator,
typename Allocator
>
class req_quantile_calculator {
@@ -44,6 +45,13 @@ private:
using AllocEntry = typename std::allocator_traits<Allocator>::template rebind_alloc<Entry>;
using Container = std::vector<Entry, AllocEntry>;
+ template<typename C>
+ struct compare_pairs_by_first_ptr {
+ bool operator()(const Entry& a, const Entry& b) {
+ return C()(*a.first, *b.first);
+ }
+ };
+
struct compare_pairs_by_second {
bool operator()(const Entry& a, const Entry& b) {
return a.second < b.second;
diff --git a/req/include/req_quantile_calculator_impl.hpp b/req/include/req_quantile_calculator_impl.hpp
index fe6fcc9..8441c02 100755
--- a/req/include/req_quantile_calculator_impl.hpp
+++ b/req/include/req_quantile_calculator_impl.hpp
@@ -22,23 +22,23 @@
namespace datasketches {
-template<typename T, typename A>
-req_quantile_calculator<T, A>::req_quantile_calculator(uint64_t n, const A& allocator):
+template<typename T, typename C, typename A>
+req_quantile_calculator<T, C, A>::req_quantile_calculator(uint64_t n, const A& allocator):
n_(n),
entries_(allocator)
{}
-template<typename T, typename A>
-void req_quantile_calculator<T, A>::add(const std::vector<T, A>& items, uint8_t lg_weight) {
+template<typename T, typename C, typename A>
+void req_quantile_calculator<T, C, A>::add(const std::vector<T, A>& items, uint8_t lg_weight) {
if (entries_.capacity() < entries_.size() + items.size()) entries_.reserve(entries_.size() + items.size());
auto middle = entries_.end();
for (const auto& item: items) entries_.push_back(Entry(&item, 1 << lg_weight));
- std::inplace_merge(entries_.begin(), middle, entries_.end(), compare_pairs_by_second());
+ std::inplace_merge(entries_.begin(), middle, entries_.end(), compare_pairs_by_first_ptr<C>());
}
-template<typename T, typename A>
+template<typename T, typename C, typename A>
template<bool inclusive>
-void req_quantile_calculator<T, A>::convert_to_cummulative() {
+void req_quantile_calculator<T, C, A>::convert_to_cummulative() {
uint64_t subtotal = 0;
for (auto& entry: entries_) {
const uint64_t new_subtotal = subtotal + entry.second;
@@ -47,8 +47,8 @@ void req_quantile_calculator<T, A>::convert_to_cummulative() {
}
}
-template<typename T, typename A>
-const T& req_quantile_calculator<T, A>::get_quantile(double rank) const {
+template<typename T, typename C, typename A>
+const T& req_quantile_calculator<T, C, A>::get_quantile(double rank) const {
uint64_t weight = static_cast<uint64_t>(rank * n_);
auto it = std::lower_bound(entries_.begin(), entries_.end(), Entry(nullptr, weight), compare_pairs_by_second());
if (it == entries_.end()) return *(entries_[entries_.size() - 1].first);
diff --git a/req/include/req_sketch_impl.hpp b/req/include/req_sketch_impl.hpp
index 96e10c2..fd4b445 100755
--- a/req/include/req_sketch_impl.hpp
+++ b/req/include/req_sketch_impl.hpp
@@ -204,7 +204,7 @@ const T& req_sketch<T, H, C, S, A>::get_quantile(double rank) const {
if (!compactors_[0].is_sorted()) {
const_cast<Compactor&>(compactors_[0]).sort(); // allow this side effect
}
- req_quantile_calculator<T, A> quantile_calculator(n_, allocator_);
+ req_quantile_calculator<T, C, A> quantile_calculator(n_, allocator_);
for (auto& compactor: compactors_) {
quantile_calculator.add(compactor.get_items(), compactor.get_lg_weight());
}
diff --git a/req/test/req_sketch_test.cpp b/req/test/req_sketch_test.cpp
index e0e6c9a..49cd776 100755
--- a/req/test/req_sketch_test.cpp
+++ b/req/test/req_sketch_test.cpp
@@ -374,10 +374,11 @@ TEST_CASE("req sketch: merge", "[req_sketch]") {
for (size_t i = 1000; i < 2000; ++i) sketch2.update(i);
sketch1.merge(sketch2);
- //std::cout << sketch1.to_string(true, true);
REQUIRE(sketch1.get_min_value() == 0);
REQUIRE(sketch1.get_max_value() == 1999);
- //REQUIRE(sketch1.get_quantile(0.5) == 1000);
+ REQUIRE(sketch1.get_quantile(0.25) == Approx(500).margin(3));
+ REQUIRE(sketch1.get_quantile(0.5) == Approx(1000).margin(1));
+ REQUIRE(sketch1.get_quantile(0.75) == Approx(1500).margin(1));
REQUIRE(sketch1.get_rank(1000) == Approx(0.5).margin(0.01));
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org