You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by jm...@apache.org on 2022/04/23 06:38:41 UTC
[datasketches-cpp] branch quantiles updated: finish merge, update types to be able handle const input sketchs instead of just exact matches
This is an automated email from the ASF dual-hosted git repository.
jmalkin pushed a commit to branch quantiles
in repository https://gitbox.apache.org/repos/asf/datasketches-cpp.git
The following commit(s) were added to refs/heads/quantiles by this push:
new bf2a0bc finish merge, update types to be able handle const input sketchs instead of just exact matches
bf2a0bc is described below
commit bf2a0bc0fa31d7bff0e7605b701dc108b97f812b
Author: Jon <jm...@apache.org>
AuthorDate: Fri Apr 22 23:38:27 2022 -0700
finish merge, update types to be able handle const input sketchs instead of just exact matches
---
python/src/quantiles_wrapper.cpp | 4 +-
quantiles/include/quantiles_sketch.hpp | 24 ++-
quantiles/include/quantiles_sketch_impl.hpp | 219 ++++++++++++++++++++--------
quantiles/test/CMakeLists.txt | 1 -
quantiles/test/quantiles_sketch_test.cpp | 56 ++++---
5 files changed, 209 insertions(+), 95 deletions(-)
diff --git a/python/src/quantiles_wrapper.cpp b/python/src/quantiles_wrapper.cpp
index 7cac6d7..ca3b7f0 100644
--- a/python/src/quantiles_wrapper.cpp
+++ b/python/src/quantiles_wrapper.cpp
@@ -150,8 +150,8 @@ void bind_quantiles_sketch(py::module &m, const char* name) {
"Updates the sketch with the given value")
.def("update", &dspy::quantiles_sketch_update<T>, py::arg("array"),
"Updates the sketch with the values in the given array")
- //.def("merge", (void (quantiles_sketch<T>::*)(const quantiles_sketch<T>&)) &quantiles_sketch<T>::merge, py::arg("sketch"),
- // "Merges the provided sketch into the this one")
+ .def("merge", (void (quantiles_sketch<T>::*)(const quantiles_sketch<T>&)) &quantiles_sketch<T>::merge, py::arg("sketch"),
+ "Merges the provided sketch into the this one")
.def("__str__", &quantiles_sketch<T>::to_string, py::arg("print_levels")=false, py::arg("print_items")=false,
"Produces a string summary of the sketch")
.def("to_string", &quantiles_sketch<T>::to_string, py::arg("print_levels")=false, py::arg("print_items")=false,
diff --git a/quantiles/include/quantiles_sketch.hpp b/quantiles/include/quantiles_sketch.hpp
index d033cb9..e078b61 100644
--- a/quantiles/include/quantiles_sketch.hpp
+++ b/quantiles/include/quantiles_sketch.hpp
@@ -490,11 +490,11 @@ private:
bool grow_levels_if_needed();
// buffers should be pre-sized to target capacity as appropriate
- static void in_place_propagate_carry(uint8_t starting_level, Level& buf_size_k,
+ template<typename FwdV>
+ static void in_place_propagate_carry(uint8_t starting_level, FwdV&& buf_size_k,
Level& buf_size_2k, bool apply_as_update,
quantiles_sketch<T,C,A>& sketch);
static void zip_buffer(Level& buf_in, Level& buf_out);
- static void zip_buffer_with_stride(Level& buf_in, Level& buf_out, uint16_t stride);
static void merge_two_size_k_buffers(Level& arr_in_1, Level& arr_in_2, Level& arr_out);
template<typename SerDe>
@@ -514,8 +514,24 @@ private:
static uint32_t compute_valid_levels(uint64_t bit_pattern);
static uint8_t compute_levels_needed(uint16_t k, uint64_t n);
- template<typename FwdT>
- void downsampling_merge(FwdT&& other);
+ /**
+ * Merges the src sketch into the tgt sketch with equal values of K.
+ * src is modified only if elements can be moved out of it.
+ */
+ template<typename FwdSk>
+ static void standard_merge(quantiles_sketch<T,C,A>& tgt, FwdSk&& src);
+
+ /**
+ * Merges the src sketch into the tgt sketch with a smaller value of K.
+ * However, it is required that the ratio of the two K values be a power of 2.
+ * I.e., other.get_k() = this.get_k() * 2^(nonnegative integer).
+ * src is modified only if elements can be moved out of it.
+ */
+ template<typename FwdSk>
+ static void downsampling_merge(quantiles_sketch<T,C,A>& tgt, FwdSk&& src);
+
+ template<typename FwdV>
+ static void zip_buffer_with_stride(FwdV&& buf_in, Level& buf_out, uint16_t stride);
/**
* Returns the zero-based bit position of the lowest zero bit of <i>bits</i> starting at
diff --git a/quantiles/include/quantiles_sketch_impl.hpp b/quantiles/include/quantiles_sketch_impl.hpp
index 1119829..2da61f6 100644
--- a/quantiles/include/quantiles_sketch_impl.hpp
+++ b/quantiles/include/quantiles_sketch_impl.hpp
@@ -64,6 +64,11 @@ is_sorted_(other.is_sorted_)
{
if (other.min_value_ != nullptr) min_value_ = new (allocator_.allocate(1)) T(*other.min_value_);
if (other.max_value_ != nullptr) max_value_ = new (allocator_.allocate(1)) T(*other.max_value_);
+ for (size_t i = 0; i < levels_.size(); ++i) {
+ if (levels_[i].capacity() != other.levels_[i].capacity()) {
+ levels_[i].reserve(other.levels_[i].capacity());
+ }
+ }
}
template<typename T, typename C, typename A>
@@ -166,37 +171,62 @@ void quantiles_sketch<T, C, A>::update(FwdT&& item) {
}
template<typename T, typename C, typename A>
-template<typename FwdT>
-void quantiles_sketch<T, C, A>::merge(FwdT&& other) {
+template<typename FwdSk>
+void quantiles_sketch<T, C, A>::merge(FwdSk&& other) {
if (other.is_empty()) {
return; // nothing to do
} else if (!other.is_estimation_mode()) {
// other is exact, stream in regardless of k
for (auto item : other.base_buffer_) {
- update(conditional_forward<FwdT>(item));
+ update(conditional_forward<FwdSk>(item));
}
return; // we're done
}
- if (is_empty()) {
- std::cerr << "Copy, possibly downsampling" << std::endl;
- if (k_ >= other.get_k()) {
- std::cerr << "Copy other into self" << std::endl;
- // empty, so copy other (since we can't change it) and replace self with copy
- quantiles_sketch<T, C, A> sk_copy(k_, allocator_);
- //sk_copy.merge(std::forward<FwdT>(other));
- sk_copy.merge(other);
- *this = std::move(sk_copy);
+ // we know other has data and is in estimation mode
+ if (is_estimation_mode()) {
+ if (k_ == other.get_k()) {
+ standard_merge(*this, other);
+ } else if (k_ > other.get_k()) {
+ quantiles_sketch<T, C, A> sk_copy(other);
+ downsampling_merge(sk_copy, *this);
+ *this = sk_copy;
} else { // k_ < other.get_k()
- std::cerr << "Downsampling merge other into self" << std::endl;
- // copy, maybe with downsampling
- downsampling_merge(std::forward<FwdT>(other));
-
+ downsampling_merge(*this, other);
+ }
+ } else {
+ // exact or empty
+ quantiles_sketch<T, C, A> sk_copy(other);
+ if (k_ <= other.get_k()) {
+ if (!is_empty()) {
+ for (uint16_t i = 0; i < base_buffer_.size(); ++i) {
+ sk_copy.update(std::move(base_buffer_[i]));
+ }
+ }
+ } else { // k_ > other.get_k()
+ downsampling_merge(sk_copy, *this);
}
+ *this = sk_copy;
+ }
+
+/*
+ // update min/max values
+ // can't just check is_empty() since min/max might not have been set if
+ // there were no base buffer items added via update()
+ if (min_value_ == nullptr) {
+ min_value_ = new (allocator_.allocate(1)) T(*other.min_value_);
} else {
- // merge, maybe with downsampling
- std::cerr << "Merge, possibly downsampling" << std::endl;
+ if (C()(*other.min_value_, *min_value_))
+ *min_value_ = conditional_forward<FwdSk>(*other.min_value_);
+ }
+
+ if (max_value_ == nullptr) {
+ max_value_ = new (allocator_.allocate(1)) T(*other.max_value_);
+ } else {
+ if (C()(*max_value_, *other.max_value_))
+ *max_value_ = conditional_forward<FwdSk>(*other.max_value_);
}
+ */
}
template<typename T, typename C, typename A>
@@ -913,8 +943,9 @@ bool quantiles_sketch<T, C, A>::grow_levels_if_needed() {
}
template<typename T, typename C, typename A>
+template<typename FwdV>
void quantiles_sketch<T, C, A>::in_place_propagate_carry(uint8_t starting_level,
- Level& buf_size_k, Level& buf_size_2k,
+ FwdV&& buf_size_k, Level& buf_size_2k,
bool apply_as_update,
quantiles_sketch<T,C,A>& sketch) {
const uint64_t bit_pattern = sketch.bit_pattern_;
@@ -929,7 +960,7 @@ void quantiles_sketch<T, C, A>::in_place_propagate_carry(uint8_t starting_level,
} else {
// merge_into version of computation
for (uint16_t i = 0; i < k; ++i) {
- sketch.levels_[ending_level].push_back(std::move(buf_size_k[i]));
+ sketch.levels_[ending_level].push_back(conditional_forward<FwdV>(buf_size_k[i]));
}
}
@@ -967,16 +998,17 @@ void quantiles_sketch<T, C, A>::zip_buffer(Level& buf_in, Level& buf_out) {
}
template<typename T, typename C, typename A>
-void quantiles_sketch<T, C, A>::zip_buffer_with_stride(Level& buf_in, Level& buf_out, uint16_t stride) {
+template<typename FwdV>
+void quantiles_sketch<T, C, A>::zip_buffer_with_stride(FwdV&& buf_in, Level& buf_out, uint16_t stride) {
// Random offset in range [0, stride)
std::uniform_int_distribution<uint16_t> dist(0, stride - 1);
uint16_t rand_offset = dist(random_utils::rand);
- assert(buf_in.size() == (1 << stride) * buf_out.capacity());
+ assert(buf_in.size() == stride * buf_out.capacity());
assert(buf_out.size() == 0);
size_t k = buf_out.capacity();
- for (uint16_t i = rand_offset, o = 0; o < k; i += 2, ++o) {
- buf_out.push_back(buf_in[i]);
+ for (uint16_t i = rand_offset, o = 0; o < k; i += stride, ++o) {
+ buf_out.push_back(conditional_forward<FwdV>(buf_in[i]));
}
// do not clear input buffer
}
@@ -1008,84 +1040,143 @@ void quantiles_sketch<T, C, A>::merge_two_size_k_buffers(Level& src_1, Level& sr
}
}
-/**
- * Merges the other sketch into the current sketch with a smaller value of K.
- * However, it is required that the ratio of the two K values be a power of 2.
- * I.e., other.get_k() = this.get_k() * 2^(nonnegative integer).
- * other is modified only if elements can be moved out of it
- */
+
template<typename T, typename C, typename A>
-template<typename FwdT>
-void quantiles_sketch<T, C, A>::downsampling_merge(FwdT&& other) {
- if (other.get_k() % k_ != 0) {
- throw std::invalid_argument("other.get_k() is not a multiple of k_");
+template<typename FwdSk>
+void quantiles_sketch<T, C, A>::standard_merge(quantiles_sketch<T,C,A>& tgt, FwdSk&& src) {
+ if (src.get_k() != tgt.get_k()) {
+ throw std::invalid_argument("src.get_k() != tgt.get_k()");
+ }
+ assert(!src.is_empty());
+
+ uint64_t new_n = src.get_n() + tgt.get_n();
+
+ // move items from src's base buffer
+ for (uint16_t i = 0; i < src.base_buffer_.size(); ++i) {
+ tgt.update(conditional_forward<FwdSk>(src.base_buffer_[i]));
+ }
+
+ // check (after moving raw items) if we need to extetend levels array
+ uint8_t levels_needed = compute_levels_needed(tgt.get_k(), new_n);
+ if (levels_needed > tgt.levels_.size()) {
+ tgt.levels_.reserve(levels_needed);
+ while (tgt.levels_.size() < levels_needed) {
+ Level empty_level(tgt.allocator_);
+ empty_level.reserve(tgt.get_k());
+ tgt.levels_.push_back(std::move(empty_level));
+ }
+ }
+
+ Level scratch_buf(tgt.allocator_);
+ scratch_buf.reserve(2 * tgt.get_k());
+
+ uint64_t src_pattern = src.bit_pattern_;
+ for (uint8_t src_lvl = 0; src_pattern != 0; ++src_lvl, src_pattern >>= 1) {
+ if ((src_pattern & 1) > 0) {
+ scratch_buf.clear();
+
+ // propagate-carry
+ in_place_propagate_carry(src_lvl,
+ src.levels_[src_lvl], scratch_buf,
+ false, tgt);
+ // update n_ at the end
+ }
+ }
+ tgt.n_ = new_n;
+ assert((tgt.get_n() / (2 * tgt.get_k())) == tgt.bit_pattern_); // internal consistency check
+
+ // update min/max values
+ // can't just check is_empty() since min/max might not have been set if
+ // there were no base buffer items added via update()
+ if (tgt.min_value_ == nullptr) {
+ tgt.min_value_ = new (tgt.allocator_.allocate(1)) T(*src.min_value_);
+ } else {
+ if (C()(*src.min_value_, *tgt.min_value_))
+ *tgt.min_value_ = conditional_forward<FwdSk>(*src.min_value_);
+ }
+
+ if (tgt.max_value_ == nullptr) {
+ tgt.max_value_ = new (tgt.allocator_.allocate(1)) T(*src.max_value_);
+ } else {
+ if (C()(*tgt.max_value_, *src.max_value_))
+ *tgt.max_value_ = conditional_forward<FwdSk>(*src.max_value_);
+ }
+}
+
+
+template<typename T, typename C, typename A>
+template<typename FwdSk>
+void quantiles_sketch<T, C, A>::downsampling_merge(quantiles_sketch<T,C,A>& tgt, FwdSk&& src) {
+ if (src.get_k() % tgt.get_k() != 0) {
+ throw std::invalid_argument("src.get_k() is not a multiple of tgt.get_k()");
}
- assert(!other.is_empty());
+ assert(!src.is_empty());
- const uint32_t downsample_factor = other.get_k() / k_;
+ const uint32_t downsample_factor = src.get_k() / tgt.get_k();
const uint32_t lg_sample_factor = count_trailing_zeros_in_u32(downsample_factor);
- uint64_t new_n = n_ + other.get_n();
+ uint64_t new_n = src.get_n() + tgt.get_n();
- // move items from other's base buffer
- for (uint16_t i = 0; i < other.base_buffer_.size(); ++i) {
- update(conditional_forward<FwdT>(other.base_buffer_[i]));
+ // move items from src's base buffer
+ for (uint16_t i = 0; i < src.base_buffer_.size(); ++i) {
+ tgt.update(conditional_forward<FwdSk>(src.base_buffer_[i]));
}
// check (after moving raw items) if we need to extetend levels array
- uint8_t levels_needed = compute_levels_needed(k_, new_n);
- if (levels_needed > levels_.size()) {
- levels_.reserve(levels_needed);
- while (levels_.size() < levels_needed) {
- Level empty_level(allocator_);
- empty_level.reserve(k_);
- levels_.push_back(std::move(empty_level));
+ uint8_t levels_needed = compute_levels_needed(tgt.get_k(), new_n);
+ if (levels_needed > tgt.levels_.size()) {
+ tgt.levels_.reserve(levels_needed);
+ while (tgt.levels_.size() < levels_needed) {
+ Level empty_level(tgt.allocator_);
+ empty_level.reserve(tgt.get_k());
+ tgt.levels_.push_back(std::move(empty_level));
}
}
- Level down_buf(allocator_);
- down_buf.reserve(k_);
+ Level down_buf(tgt.allocator_);
+ down_buf.reserve(tgt.get_k());
- Level scratch_buf(allocator_);
- scratch_buf.reserve(2 * k_);
+ Level scratch_buf(tgt.allocator_);
+ scratch_buf.reserve(2 * tgt.get_k());
- uint64_t src_pattern = other.bit_pattern_;
+ uint64_t src_pattern = src.bit_pattern_;
for (uint8_t src_lvl = 0; src_pattern != 0; ++src_lvl, src_pattern >>= 1) {
if ((src_pattern & 1) > 0) {
down_buf.clear();
scratch_buf.clear();
// zip with stride, leaving input buffer intact
- zip_buffer_with_stride(other.levels_[src_lvl], down_buf, lg_sample_factor);
+ zip_buffer_with_stride(src.levels_[src_lvl], down_buf, downsample_factor);
// propagate-carry
in_place_propagate_carry(src_lvl + lg_sample_factor,
down_buf, scratch_buf,
- false, *this);
+ false, tgt);
// update n_ at the end
}
}
- n_ = new_n;
- assert((n_ / (2 * k_)) == bit_pattern_); // internal consistency check
+ tgt.n_ = new_n;
+ assert((tgt.get_n() / (2 * tgt.get_k())) == tgt.bit_pattern_); // internal consistency check
// update min/max values
// can't just check is_empty() since min/max might not have been set if
// there were no base buffer items added via update()
- if (min_value_ == nullptr) {
- min_value_ = new (allocator_.allocate(1)) T(*other.min_value_);
+ if (tgt.min_value_ == nullptr) {
+ tgt.min_value_ = new (tgt.allocator_.allocate(1)) T(*src.min_value_);
} else {
- if (C()(*other.min_value_, *min_value_))
- *min_value_ = conditional_forward<FwdT>(*other.min_value_);
+ if (C()(*src.min_value_, *tgt.min_value_))
+ *tgt.min_value_ = conditional_forward<FwdSk>(*src.min_value_);
}
- if (max_value_ == nullptr) {
- max_value_ = new (allocator_.allocate(1)) T(*other.max_value_);
+ if (tgt.max_value_ == nullptr) {
+ tgt.max_value_ = new (tgt.allocator_.allocate(1)) T(*src.max_value_);
} else {
- if (C()(*max_value_, *other.max_value_))
- *max_value_ = conditional_forward<FwdT>(*other.max_value_);
+ if (C()(*tgt.max_value_, *src.max_value_))
+ *tgt.max_value_ = conditional_forward<FwdSk>(*src.max_value_);
}
}
+
template<typename T, typename C, typename A>
uint8_t quantiles_sketch<T, C, A>::lowest_zero_bit_starting_at(uint64_t bits, uint8_t starting_bit) {
uint8_t pos = starting_bit & 0X3F;
diff --git a/quantiles/test/CMakeLists.txt b/quantiles/test/CMakeLists.txt
index 74ef73f..2adbcda 100644
--- a/quantiles/test/CMakeLists.txt
+++ b/quantiles/test/CMakeLists.txt
@@ -41,5 +41,4 @@ target_sources(quantiles_test
PRIVATE
quantiles_sketch_test.cpp
quantiles_compatibility_test.cpp
- #simple_test.cpp
)
diff --git a/quantiles/test/quantiles_sketch_test.cpp b/quantiles/test/quantiles_sketch_test.cpp
index 2b6dc4c..130f9f9 100644
--- a/quantiles/test/quantiles_sketch_test.cpp
+++ b/quantiles/test/quantiles_sketch_test.cpp
@@ -475,36 +475,44 @@ TEST_CASE("quantiles sketch", "[quantiles_sketch]") {
REQUIRE_THROWS_AS(sketch.get_CDF(split_points, 1), std::invalid_argument);
}
- SECTION("merge, manual testing") {
- quantiles_float_sketch sk1(32, 0);
- quantiles_float_sketch sk2(256, 0);
+ SECTION("merge") {
+ quantiles_float_sketch sketch1(128, 0);
+ quantiles_float_sketch sketch2(128, 0);
const int n = 10000;
for (int i = 0; i < n; i++) {
- //sk1.update(static_cast<float>(i));
- sk2.update(static_cast<float>((2 * n) - i - 1));
+ sketch1.update(static_cast<float>(i));
+ sketch2.update(static_cast<float>((2 * n) - i - 1));
}
- //std::cout << "Min: " << sk1.get_min_value() << std::endl;
- //std::cout << "Max: " << sk1.get_max_value() << std::endl;
- std::cout << "Merging..." << std::endl;
- sk1.merge(sk2);
- std::cout << "Min: " << sk1.get_min_value() << std::endl;
- std::cout << "Max: " << sk1.get_max_value() << std::endl;
+ REQUIRE(sketch1.get_min_value() == 0.0f);
+ REQUIRE(sketch1.get_max_value() == n - 1);
+ REQUIRE(sketch2.get_min_value() == n);
+ REQUIRE(sketch2.get_max_value() == 2.0f * n - 1);
- std::cout << "n: " << sk1.get_n() << std::endl;
+ sketch1.merge(sketch2);
+
+ REQUIRE_FALSE(sketch1.is_empty());
+ REQUIRE(sketch1.get_n() == 2 * n);
+ REQUIRE(sketch1.get_min_value() == 0.0f);
+ REQUIRE(sketch1.get_max_value() == 2.0f * n - 1);
+ REQUIRE(sketch1.get_quantile(0.5) == Approx(n).margin(n * RANK_EPS_FOR_K_128));
}
-/*
- SECTION("merge") {
+ SECTION("merge from const") {
quantiles_float_sketch sketch1(128, 0);
quantiles_float_sketch sketch2(128, 0);
+ const int n = 10000;
+ for (int i = 0; i < n; i++) {
+ sketch1.update(static_cast<float>(i));
+ sketch2.update(static_cast<float>((2 * n) - i - 1));
+ }
REQUIRE(sketch1.get_min_value() == 0.0f);
REQUIRE(sketch1.get_max_value() == n - 1);
REQUIRE(sketch2.get_min_value() == n);
REQUIRE(sketch2.get_max_value() == 2.0f * n - 1);
- sketch1.merge(sketch2);
+ sketch1.merge(const_cast<const quantiles_float_sketch&>(sketch2));
REQUIRE_FALSE(sketch1.is_empty());
REQUIRE(sketch1.get_n() == 2 * n);
@@ -513,6 +521,7 @@ TEST_CASE("quantiles sketch", "[quantiles_sketch]") {
REQUIRE(sketch1.get_quantile(0.5) == Approx(n).margin(n * RANK_EPS_FOR_K_128));
}
+
SECTION("merge lower k") {
quantiles_float_sketch sketch1(256, 0);
quantiles_float_sketch sketch2(128, 0);
@@ -543,12 +552,12 @@ TEST_CASE("quantiles sketch", "[quantiles_sketch]") {
REQUIRE(sketch1.get_n() == 2 * n);
REQUIRE(sketch1.get_min_value() == 0.0f);
REQUIRE(sketch1.get_max_value() == 2.0f * n - 1);
- REQUIRE(sketch1.get_quantile(0.5) == Approx(n).margin(n * RANK_EPS_FOR_K_200));
+ REQUIRE(sketch1.get_quantile(0.5) == Approx(n).margin(n * RANK_EPS_FOR_K_128));
}
SECTION("merge exact mode, lower k") {
- kll_float_sketch sketch1(256, 0);
- kll_float_sketch sketch2(128, 0);
+ quantiles_float_sketch sketch1(256, 0);
+ quantiles_float_sketch sketch2(128, 0);
const int n = 10000;
for (int i = 0; i < n; i++) {
sketch1.update(static_cast<float>(i));
@@ -563,7 +572,7 @@ TEST_CASE("quantiles sketch", "[quantiles_sketch]") {
REQUIRE(sketch1.get_n() == n);
REQUIRE(sketch1.get_min_value() == 0.0f);
REQUIRE(sketch1.get_max_value() == n - 1);
- REQUIRE(sketch1.get_quantile(0.5) == Approx(n / 2).margin(n / 2 * RANK_EPS_FOR_K_200));
+ REQUIRE(sketch1.get_quantile(0.5) == Approx(n / 2).margin(n / 2 * RANK_EPS_FOR_K_128));
sketch2.update(0);
sketch1.merge(sketch2);
@@ -572,8 +581,8 @@ TEST_CASE("quantiles sketch", "[quantiles_sketch]") {
}
SECTION("merge min value from other") {
- kll_float_sketch sketch1(200, 0);
- kll_float_sketch sketch2(200, 0);
+ quantiles_float_sketch sketch1(128, 0);
+ quantiles_float_sketch sketch2(128, 0);
sketch1.update(1.0f);
sketch2.update(2.0f);
sketch2.merge(sketch1);
@@ -582,14 +591,13 @@ TEST_CASE("quantiles sketch", "[quantiles_sketch]") {
}
SECTION("merge min and max values from other") {
- kll_float_sketch sketch1(200, 0);
+ quantiles_float_sketch sketch1(128, 0);
for (int i = 0; i < 1000000; i++) sketch1.update(static_cast<float>(i));
- kll_float_sketch sketch2(200, 0);
+ quantiles_float_sketch sketch2(128, 0);
sketch2.merge(sketch1);
REQUIRE(sketch2.get_min_value() == 0.0f);
REQUIRE(sketch2.get_max_value() == 999999.0f);
}
-*/
SECTION("sketch of ints") {
quantiles_sketch<int> sketch;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org