in cpc/include/cpc_union_impl.hpp [104:171]
void cpc_union_alloc<A>::internal_update(S&& sketch) {
const uint16_t seed_hash_union = compute_seed_hash(seed);
const uint16_t seed_hash_sketch = compute_seed_hash(sketch.seed);
if (seed_hash_union != seed_hash_sketch) {
throw std::invalid_argument("Incompatible seed hashes: " + std::to_string(seed_hash_union) + ", "
+ std::to_string(seed_hash_sketch));
}
const auto src_flavor = sketch.determine_flavor();
if (cpc_sketch_alloc<A>::flavor::EMPTY == src_flavor) return;
if (sketch.get_lg_k() < lg_k) reduce_k(sketch.get_lg_k());
if (sketch.get_lg_k() < lg_k) throw std::logic_error("sketch lg_k < union lg_k");
if (accumulator == nullptr && bit_matrix.size() == 0) throw std::logic_error("both accumulator and bit matrix are absent");
if (cpc_sketch_alloc<A>::flavor::SPARSE == src_flavor && accumulator != nullptr) { // Case A
if (bit_matrix.size() > 0) throw std::logic_error("union bit_matrix is not expected");
const auto initial_dest_flavor = accumulator->determine_flavor();
if (cpc_sketch_alloc<A>::flavor::EMPTY != initial_dest_flavor &&
cpc_sketch_alloc<A>::flavor::SPARSE != initial_dest_flavor) throw std::logic_error("wrong flavor");
// The following partially fixes the snowplow problem provided that the K's are equal.
if (cpc_sketch_alloc<A>::flavor::EMPTY == initial_dest_flavor && lg_k == sketch.get_lg_k()) {
*accumulator = std::forward<S>(sketch);
return;
}
walk_table_updating_sketch(sketch.surprising_value_table);
const auto final_dst_flavor = accumulator->determine_flavor();
// if the accumulator has graduated beyond sparse, switch to a bit matrix representation
if (final_dst_flavor != cpc_sketch_alloc<A>::flavor::EMPTY && final_dst_flavor != cpc_sketch_alloc<A>::flavor::SPARSE) {
switch_to_bit_matrix();
}
return;
}
if (cpc_sketch_alloc<A>::flavor::SPARSE == src_flavor && bit_matrix.size() > 0) { // Case B
if (accumulator != nullptr) throw std::logic_error("union accumulator != null");
or_table_into_matrix(sketch.surprising_value_table);
return;
}
if (cpc_sketch_alloc<A>::flavor::HYBRID != src_flavor && cpc_sketch_alloc<A>::flavor::PINNED != src_flavor
&& cpc_sketch_alloc<A>::flavor::SLIDING != src_flavor) throw std::logic_error("wrong flavor");
// source is past SPARSE mode, so make sure that dest is a bit matrix
if (accumulator != nullptr) {
if (bit_matrix.size() > 0) throw std::logic_error("union bit matrix is not expected");
const auto dst_flavor = accumulator->determine_flavor();
if (cpc_sketch_alloc<A>::flavor::EMPTY != dst_flavor && cpc_sketch_alloc<A>::flavor::SPARSE != dst_flavor) {
throw std::logic_error("wrong flavor");
}
switch_to_bit_matrix();
}
if (bit_matrix.size() == 0) throw std::logic_error("union bit_matrix is expected");
if (cpc_sketch_alloc<A>::flavor::HYBRID == src_flavor || cpc_sketch_alloc<A>::flavor::PINNED == src_flavor) { // Case C
or_window_into_matrix(sketch.sliding_window, sketch.window_offset, sketch.get_lg_k());
or_table_into_matrix(sketch.surprising_value_table);
return;
}
// SLIDING mode involves inverted logic, so we can't just walk the source sketch.
// Instead, we convert it to a bitMatrix that can be OR'ed into the destination.
if (cpc_sketch_alloc<A>::flavor::SLIDING != src_flavor) throw std::logic_error("wrong flavor"); // Case D
vector_u64<A> src_matrix = sketch.build_bit_matrix();
or_matrix_into_matrix(src_matrix, sketch.get_lg_k());
}