fixed merge
diff --git a/req/include/req_compactor_impl.hpp b/req/include/req_compactor_impl.hpp
index 067196c..841066c 100755
--- a/req/include/req_compactor_impl.hpp
+++ b/req/include/req_compactor_impl.hpp
@@ -219,7 +219,7 @@
auto other_it = other.begin();
for (auto it = from; it != to; ++it, ++other_it) new (it) T(conditional_forward<FwdC>(*other_it));
if (!other.sorted_) std::sort(from, to, C());
- std::inplace_merge(H ? from : begin(), middle, H ? end() : to);
+ if (num_items_ > 0) std::inplace_merge(H ? from : begin(), middle, H ? end() : to);
num_items_ += other.get_num_items();
}
diff --git a/req/include/req_sketch_impl.hpp b/req/include/req_sketch_impl.hpp
index d6d873f..8ee16b4 100755
--- a/req/include/req_sketch_impl.hpp
+++ b/req/include/req_sketch_impl.hpp
@@ -149,7 +149,6 @@
template<typename FwdSk>
void req_sketch<T, H, C, S, A>::merge(FwdSk&& other) {
if (other.is_empty()) return;
- n_ += other.n_;
if (is_empty()) {
min_value_ = new (allocator_.allocate(1)) T(conditional_forward<FwdSk>(*other.min_value_));
max_value_ = new (allocator_.allocate(1)) T(conditional_forward<FwdSk>(*other.max_value_));
@@ -160,9 +159,10 @@
// grow until this has at least as many compactors as other
while (get_num_levels() < other.get_num_levels()) grow();
// merge the items in all height compactors
- for (size_t i = 0; i < get_num_levels(); ++i) {
+ for (size_t i = 0; i < other.get_num_levels(); ++i) {
compactors_[i].merge(conditional_forward<FwdSk>(other.compactors_[i]));
}
+ n_ += other.n_;
update_max_nom_size();
update_num_retained();
if (num_retained_ >= max_nom_size_) compress();
diff --git a/req/test/req_sketch_test.cpp b/req/test/req_sketch_test.cpp
index 72a0e5d..e7d1fca 100755
--- a/req/test/req_sketch_test.cpp
+++ b/req/test/req_sketch_test.cpp
@@ -366,6 +366,21 @@
REQUIRE(sketch.get_rank(5000) == 0.5);
}
+TEST_CASE("req sketch: merge into empty", "[req_sketch]") {
+ req_sketch<float, true> sketch1(40);
+
+ req_sketch<float, true> sketch2(40);
+ for (size_t i = 0; i < 1000; ++i) sketch2.update(i);
+
+ sketch1.merge(sketch2);
+ REQUIRE(sketch1.get_min_value() == 0);
+ REQUIRE(sketch1.get_max_value() == 999);
+ REQUIRE(sketch1.get_quantile(0.25) == Approx(250).margin(3));
+ REQUIRE(sketch1.get_quantile(0.5) == Approx(500).margin(3));
+ REQUIRE(sketch1.get_quantile(0.75) == Approx(750).margin(3));
+ REQUIRE(sketch1.get_rank(500) == Approx(0.5).margin(0.01));
+}
+
TEST_CASE("req sketch: merge", "[req_sketch]") {
req_sketch<float, true> sketch1(100);
for (size_t i = 0; i < 1000; ++i) sketch1.update(i);
@@ -382,15 +397,35 @@
REQUIRE(sketch1.get_rank(1000) == Approx(0.5).margin(0.01));
}
-TEST_CASE("for manual comparison with Java") {
+TEST_CASE("req sketch: merge multiple", "[req_sketch]") {
+ req_sketch<float, true> sketch1(12);
+ for (size_t i = 0; i < 40; ++i) sketch1.update(i);
+
+ req_sketch<float, true> sketch2(12);
+ for (size_t i = 40; i < 80; ++i) sketch2.update(i);
+
+ req_sketch<float, true> sketch3(12);
+ for (size_t i = 80; i < 120; ++i) sketch3.update(i);
+
req_sketch<float, true> sketch(12);
- for (size_t i = 0; i < 100000; ++i) sketch.update(i);
- sketch.merge(sketch);
- std::ofstream os;
- os.exceptions(std::ios::failbit | std::ios::badbit);
- os.open("req_float_hra_12_100000_merged.sk", std::ios::binary);
- sketch.get_quantile(0.5); // force sorting level 0
- sketch.serialize(os);
+ sketch.merge(sketch1);
+ sketch.merge(sketch2);
+ sketch.merge(sketch3);
+ REQUIRE(sketch.get_min_value() == 0);
+ REQUIRE(sketch.get_max_value() == 119);
+ REQUIRE(sketch.get_quantile(0.5) == Approx(60).margin(3));
+ REQUIRE(sketch.get_rank(60) == Approx(0.5).margin(0.01));
}
+//TEST_CASE("for manual comparison with Java") {
+// req_sketch<float, true> sketch(12);
+// for (size_t i = 0; i < 100000; ++i) sketch.update(i);
+// sketch.merge(sketch);
+// std::ofstream os;
+// os.exceptions(std::ios::failbit | std::ios::badbit);
+// os.open("req_float_hra_12_100000_merged.sk", std::ios::binary);
+// sketch.get_quantile(0.5); // force sorting level 0
+// sketch.serialize(os);
+//}
+
} /* namespace datasketches */