| /* |
| * 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 <ebpps_sample.hpp> |
| |
| #include <catch2/catch.hpp> |
| |
| #include <vector> |
| #include <string> |
| #include <sstream> |
| #include <fstream> |
| #include <cmath> |
| #include <random> |
| #include <stdexcept> |
| |
| namespace datasketches { |
| |
| static constexpr double EPS = 1e-15; |
| |
| TEST_CASE("ebpps sample: basic initialization", "[ebpps_sketch]") { |
| ebpps_sample<int> sample = ebpps_sample<int>(0); |
| REQUIRE(sample.get_c() == 0.0); |
| REQUIRE(sample.get_num_retained_items() == 0); |
| REQUIRE(sample.get_sample().size() == 0); |
| } |
| |
| TEST_CASE("ebpps sample: pre-initialized", "[ebpps_sketch]") { |
| double theta = 1.0; |
| ebpps_sample<int> sample(1); |
| sample.replace_content(-1, theta); |
| REQUIRE(sample.get_c() == theta); |
| REQUIRE(sample.get_num_retained_items() == 1); |
| REQUIRE(sample.get_sample().size() == 1); |
| REQUIRE(sample.has_partial_item() == false); |
| |
| theta = 1e-300; |
| sample.replace_content(-1, theta); |
| REQUIRE(sample.get_c() == theta); |
| REQUIRE(sample.get_num_retained_items() == 1); |
| REQUIRE(sample.get_sample().size() == 0); // assuming the random number is > 1e-300 |
| REQUIRE(sample.has_partial_item()); |
| } |
| |
| TEST_CASE("ebpps sample: downsampling", "[ebpps_sketch]") { |
| ebpps_sample<char> sample(1); |
| sample.replace_content('a', 1.0); |
| |
| sample.downsample(2.0); // no-op |
| REQUIRE(sample.get_c() == 1.0); |
| REQUIRE(sample.get_num_retained_items() == 1); |
| REQUIRE(sample.has_partial_item() == false); |
| |
| // downsample and result in an empty sample |
| random_utils::override_seed(12); |
| std::vector<char> items = {'a', 'b'}; |
| optional<char> opt; // empty |
| sample = ebpps_sample<char>(std::move(items), std::move(opt), 1.8); |
| sample.downsample(0.5); |
| REQUIRE(sample.get_c() == 0.9); |
| REQUIRE(sample.get_num_retained_items() == 0); |
| REQUIRE(sample.has_partial_item() == false); |
| |
| // downsample and result in a sample with a partial item |
| items = {'a', 'b'}; |
| opt.reset(); |
| sample = ebpps_sample<char>(std::move(items), std::move(opt), 1.5); |
| sample.downsample(0.5); |
| REQUIRE(sample.get_c() == 0.75); |
| REQUIRE(sample.get_num_retained_items() == 1); |
| REQUIRE(sample.has_partial_item() == true); |
| for (char c : sample) { |
| REQUIRE((c == 'a' || c == 'b')); |
| } |
| |
| // downsample to an exact integer c (7.5 * 0.8 = 6.0) |
| items = {'a', 'b', 'c', 'd', 'e', 'f', 'g'}; |
| opt.emplace('h'); |
| auto ref_items = items; // copy to check contents |
| ref_items.emplace_back('h'); // include partial item |
| sample = ebpps_sample<char>(std::move(items), std::move(opt), 7.5); |
| sample.downsample(0.8); |
| REQUIRE(sample.get_c() == 6.0); |
| REQUIRE(sample.get_num_retained_items() == 6); |
| REQUIRE(sample.has_partial_item() == false); |
| for (char c : sample) { |
| REQUIRE(std::find(ref_items.begin(), ref_items.end(), c) != ref_items.end()); |
| } |
| |
| // downsample to c > 1 with partial item |
| items = ref_items; // includes previous optional item |
| opt.emplace('i'); |
| sample = ebpps_sample<char>(std::move(items), std::move(opt), 8.5); |
| REQUIRE(sample.get_partial_item() == 'i'); |
| sample.downsample(0.8); |
| REQUIRE(sample.get_c() == Approx(6.8).margin(EPS)); |
| REQUIRE(sample.get_num_retained_items() == 7); |
| REQUIRE(sample.has_partial_item() == true); |
| ref_items.emplace_back('i'); |
| for (char c : sample) { |
| REQUIRE(std::find(ref_items.begin(), ref_items.end(), c) != ref_items.end()); |
| } |
| |
| random_utils::override_seed(random_utils::rd()); |
| } |
| |
| TEST_CASE("ebpps sample: merge unit samples", "[ebpps_sketch]") { |
| uint32_t k = 8; |
| ebpps_sample<int> sample = ebpps_sample<int>(k); |
| |
| ebpps_sample<int> s(1); |
| for (uint32_t i = 1; i <= k; ++i) { |
| s.replace_content(i, 1.0); |
| sample.merge(s); |
| REQUIRE(sample.get_c() == static_cast<double>(i)); |
| REQUIRE(sample.get_num_retained_items() == i); |
| } |
| |
| sample.reset(); |
| REQUIRE(sample.get_c() == 0); |
| REQUIRE(sample.get_num_retained_items() == 0); |
| REQUIRE(sample.has_partial_item() == false); |
| } |
| |
| } // namespace datasketches |