/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include #include #include #include #include namespace datasketches { TEST_CASE("tuple_union float: empty", "[tuple union]") { auto update_sketch = update_tuple_sketch::builder().build(); auto u = tuple_union::builder().build(); u.update(update_sketch); auto result = u.get_result(); // std::cout << result.to_string(true); REQUIRE(result.is_empty()); REQUIRE(result.get_num_retained() == 0); REQUIRE(!result.is_estimation_mode()); REQUIRE(result.get_estimate() == 0); } TEST_CASE("tupe_union float: empty theta sketch", "[tuple union]") { auto update_sketch = update_theta_sketch::builder().build(); auto u = tuple_union::builder().build(); u.update(compact_tuple_sketch(update_sketch, 0)); auto result = u.get_result(); // std::cout << result.to_string(true); REQUIRE(result.is_empty()); REQUIRE(result.get_num_retained() == 0); REQUIRE(!result.is_estimation_mode()); REQUIRE(result.get_estimate() == 0); } TEST_CASE("tuple_union float: non-empty no retained entries", "[tuple union]") { auto update_sketch = update_tuple_sketch::builder().set_p(0.001f).build(); // std::cout << update_sketch.to_string(); update_sketch.update(1, 1.0f); REQUIRE(!update_sketch.is_empty()); REQUIRE(update_sketch.get_num_retained() == 0); auto u = tuple_union::builder().build(); u.update(update_sketch); auto result = u.get_result(); // std::cout << result.to_string(true); REQUIRE(!result.is_empty()); REQUIRE(result.get_num_retained() == 0); REQUIRE(result.is_estimation_mode()); REQUIRE(result.get_estimate() == 0); REQUIRE(result.get_theta() == Approx(0.001).margin(1e-10)); } TEST_CASE("tuple_union float: simple case", "[tuple union]") { auto update_sketch1 = update_tuple_sketch::builder().build(); update_sketch1.update(1, 1.0f); update_sketch1.update(2, 1.0f); auto update_sketch2 = update_tuple_sketch::builder().build(); update_sketch2.update(1, 1.0f); update_sketch2.update(3, 1.0f); auto u = tuple_union::builder().build(); u.update(update_sketch1); u.update(update_sketch2); auto result = u.get_result(); REQUIRE(result.get_num_retained() == 3); u.reset(); result = u.get_result(); REQUIRE(result.is_empty()); REQUIRE(result.get_num_retained() == 0); REQUIRE(!result.is_estimation_mode()); REQUIRE(result.get_estimate() == 0); } TEST_CASE("tuple_union float: exact mode half overlap", "[tuple union]") { auto update_sketch1 = update_tuple_sketch::builder().build(); int value = 0; for (int i = 0; i < 1000; ++i) update_sketch1.update(value++, 1.0f); auto update_sketch2 = update_tuple_sketch::builder().build(); value = 500; for (int i = 0; i < 1000; ++i) update_sketch2.update(value++, 1.0f); { // unordered auto u = tuple_union::builder().build(); u.update(update_sketch1); u.update(update_sketch2); auto result = u.get_result(); REQUIRE(!result.is_empty()); REQUIRE(!result.is_estimation_mode()); REQUIRE(result.get_estimate() == Approx(1500).margin(1500 * 0.01)); } { // ordered auto u = tuple_union::builder().build(); u.update(update_sketch1.compact()); u.update(update_sketch2.compact()); auto result = u.get_result(); REQUIRE(!result.is_empty()); REQUIRE(!result.is_estimation_mode()); REQUIRE(result.get_estimate() == Approx(1500).margin(1500 * 0.01)); } } TEST_CASE("tuple_union float: estimation mode half overlap", "[tuple union]") { auto update_sketch1 = update_tuple_sketch::builder().build(); int value = 0; for (int i = 0; i < 10000; ++i) update_sketch1.update(value++, 1.0f); auto update_sketch2 = update_tuple_sketch::builder().build(); value = 5000; for (int i = 0; i < 10000; ++i) update_sketch2.update(value++, 1.0f); { // unordered auto u = tuple_union::builder().build(); u.update(update_sketch1); u.update(update_sketch2); auto result = u.get_result(); REQUIRE(!result.is_empty()); REQUIRE(result.is_estimation_mode()); REQUIRE(result.get_estimate() == Approx(15000).margin(15000 * 0.01)); } { // ordered auto u = tuple_union::builder().build(); u.update(update_sketch1.compact()); u.update(update_sketch2.compact()); auto result = u.get_result(); REQUIRE(!result.is_empty()); REQUIRE(result.is_estimation_mode()); REQUIRE(result.get_estimate() == Approx(15000).margin(15000 * 0.01)); } } TEST_CASE("tuple_union float: seed mismatch", "[tuple union]") { auto update_sketch = update_tuple_sketch::builder().build(); update_sketch.update(1, 1.0f); // non-empty should not be ignored auto u = tuple_union::builder().set_seed(123).build(); REQUIRE_THROWS_AS(u.update(update_sketch), std::invalid_argument); } TEST_CASE("tuple_union float: full overlap with theta sketch", "[tuple union]") { auto u = tuple_union::builder().build(); // tuple update auto update_tuple = update_tuple_sketch::builder().build(); for (unsigned i = 0; i < 10; ++i) update_tuple.update(i, 1.0f); u.update(update_tuple); // tuple compact auto compact_tuple = update_tuple.compact(); u.update(compact_tuple); // theta update auto update_theta = update_theta_sketch::builder().build(); for (unsigned i = 0; i < 10; ++i) update_theta.update(i); u.update(compact_tuple_sketch(update_theta, 1)); // theta compact auto compact_theta = update_theta.compact(); u.update(compact_tuple_sketch(compact_theta, 1)); auto result = u.get_result(); // std::cout << result.to_string(true); REQUIRE_FALSE(result.is_empty()); REQUIRE(result.get_num_retained() == 10); REQUIRE(!result.is_estimation_mode()); REQUIRE(result.get_estimate() == 10); for (const auto& entry: result) { REQUIRE(entry.second == 4); } } } /* namespace datasketches */