void cpc_union_alloc::internal_update()

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 src_matrix = sketch.build_bit_matrix();
  or_matrix_into_matrix(src_matrix, sketch.get_lg_k());
}