#include <catch2/catch.hpp>
#include <cstdio>
#include "hll.hpp"
#include "HllUtil.hpp"
namespace datasketches {
static int get_n(int lg_k, hll_mode mode) {
if (mode == LIST) return 4;
if (mode == SET) return 1 << (lg_k - 4);
return ((lg_k < 8) && (mode == HLL)) ? (1 << lg_k) : 1 << (lg_k - 3);
}
static long v = 0;
static hll_sketch build_sketch(uint8_t lg_k, target_hll_type hll_type, hll_mode mode) {
hll_sketch sk(lg_k, hll_type);
int n = get_n(lg_k, mode);
for (int i = 0; i < n; i++) sk.update(static_cast<uint64_t>(i + v));
v += n;
return sk;
}
static void union_one_update(bool compact) {
for (uint8_t lg_k = 4; lg_k <= 21; lg_k++) { for (int mode = 0; mode <= 2; mode++) { if ((lg_k < 8) && (mode == 1)) continue; for (int t = 0; t <= 2; t++) { target_hll_type hll_type = (target_hll_type) t;
hll_sketch sk1 = build_sketch(lg_k, hll_type, (hll_mode) mode);
hll_union u(lg_k);
u.update(sk1);
hll_sketch sk2 = u.get_result(hll_type);
auto bytes1 = compact ? sk1.serialize_compact() : sk1.serialize_updatable();
auto bytes2 = compact ? sk2.serialize_compact() : sk2.serialize_updatable();
auto msg = "LgK=" + std::to_string(lg_k)
+ ", Mode=" + std::to_string(mode)
+ ", Type=" + std::to_string(hll_type)
+ "\n" + sk1.to_string(true, true, true, true)
+ "\n" + sk2.to_string(true, true, true, true);
if (bytes1 != bytes2) {
std::cerr << msg << std::endl;
REQUIRE(bytes1 == bytes2);
}
}
}
}
}
TEST_CASE("hll isomorphic: union one update serialize updatable", "[hll_isomorphic]") {
union_one_update(false);
}
TEST_CASE("hll isomorphic: union one update serialize compact", "[hll_isomorphic]") {
union_one_update(true);
}
static void convert_back_and_forth(bool compact) {
for (uint8_t lg_k = 4; lg_k <= 21; lg_k++) { for (int mode = 0; mode <= 2; mode++) { if ((lg_k < 8) && (mode == 1)) continue; for (int t1 = 0; t1 <= 2; t1++) { target_hll_type hll_type1 = (target_hll_type) t1;
hll_sketch sk1 = build_sketch(lg_k, hll_type1, (hll_mode) mode);
auto bytes1 = compact ? sk1.serialize_compact() : sk1.serialize_updatable();
for (int t2 = 0; t2 <= 2; t2++) { if (t2 == t1) continue;
target_hll_type hll_type2 = (target_hll_type) t2;
hll_sketch sk2(hll_sketch(sk1, hll_type2), hll_type1);
auto bytes2 = compact ? sk2.serialize_compact() : sk2.serialize_updatable();
auto msg = "LgK=" + std::to_string(lg_k)
+ ", Mode=" + std::to_string(mode)
+ ", Type1=" + std::to_string(hll_type1)
+ ", Type2=" + std::to_string(hll_type2)
+ "\n" + sk1.to_string(true, true, true, true)
+ "\n" + sk2.to_string(true, true, true, true);
if (bytes1 != bytes2) {
std::cerr << msg << std::endl;
REQUIRE(bytes1 == bytes2);
}
}
}
}
}
}
TEST_CASE("hll isomorphic: convert back and forth serialize updatable", "[hll_isomorphic]") {
convert_back_and_forth(false);
}
TEST_CASE("hll isomorphic: convert back and forth serialize compact", "[hll_isomorphic]") {
convert_back_and_forth(true);
}
}