in tdigest/include/tdigest_impl.hpp [377:418]
tdigest<T, A> tdigest<T, A>::deserialize(std::istream& is, const A& allocator) {
const auto preamble_longs = read<uint8_t>(is);
const auto serial_version = read<uint8_t>(is);
const auto sketch_type = read<uint8_t>(is);
if (sketch_type != SKETCH_TYPE) {
if (preamble_longs == 0 && serial_version == 0 && sketch_type == 0) return deserialize_compat(is, allocator);
throw std::invalid_argument("sketch type mismatch: expected " + std::to_string(SKETCH_TYPE) + ", actual " + std::to_string(sketch_type));
}
if (serial_version != SERIAL_VERSION) {
throw std::invalid_argument("serial version mismatch: expected " + std::to_string(SERIAL_VERSION) + ", actual " + std::to_string(serial_version));
}
const auto k = read<uint16_t>(is);
const auto flags_byte = read<uint8_t>(is);
const bool is_empty = flags_byte & (1 << flags::IS_EMPTY);
const bool is_single_value = flags_byte & (1 << flags::IS_SINGLE_VALUE);
const uint8_t expected_preamble_longs = is_empty || is_single_value ? PREAMBLE_LONGS_EMPTY_OR_SINGLE : PREAMBLE_LONGS_MULTIPLE;
if (preamble_longs != expected_preamble_longs) {
throw std::invalid_argument("preamble longs mismatch: expected " + std::to_string(expected_preamble_longs) + ", actual " + std::to_string(preamble_longs));
}
read<uint16_t>(is); // unused
if (is_empty) return tdigest(k, allocator);
const bool reverse_merge = flags_byte & (1 << flags::REVERSE_MERGE);
if (is_single_value) {
const T value = read<T>(is);
return tdigest(reverse_merge, k, value, value, vector_centroid(1, centroid(value, 1), allocator), 1, vector_t(allocator));
}
const auto num_centroids = read<uint32_t>(is);
const auto num_buffered = read<uint32_t>(is);
const T min = read<T>(is);
const T max = read<T>(is);
vector_centroid centroids(num_centroids, centroid(0, 0), allocator);
if (num_centroids > 0) read(is, centroids.data(), num_centroids * sizeof(centroid));
vector_t buffer(num_buffered, 0, allocator);
if (num_buffered > 0) read(is, buffer.data(), num_buffered * sizeof(T));
uint64_t weight = 0;
for (const auto& c: centroids) weight += c.get_weight();
return tdigest(reverse_merge, k, min, max, std::move(centroids), weight, std::move(buffer));
}