209 size_t nCentroids = 0;
210 for (
auto it = digests.begin(); it != digests.end(); it++) {
211 nCentroids += it->centroids_.size();
214 if (nCentroids == 0) {
218 std::vector<Centroid> centroids;
219 centroids.reserve(nCentroids);
221 std::vector<std::vector<Centroid>::iterator> starts;
222 starts.reserve(digests.size());
228 double min = std::numeric_limits<double>::infinity();
229 double max = -std::numeric_limits<double>::infinity();
231 for (
auto it = digests.begin(); it != digests.end(); it++) {
232 starts.push_back(centroids.end());
233 double curCount = it->count();
235 DCHECK(!std::isnan(it->min_));
236 DCHECK(!std::isnan(it->max_));
240 for (
const auto& centroid : it->centroids_) {
241 centroids.push_back(centroid);
246 for (
size_t digestsPerBlock = 1; digestsPerBlock < starts.size();
247 digestsPerBlock *= 2) {
250 for (
size_t i = 0;
i < starts.size();
i += (digestsPerBlock * 2)) {
253 if (
i + digestsPerBlock < starts.size()) {
255 auto middle = starts[
i + digestsPerBlock];
260 std::vector<Centroid>::iterator last =
261 (
i + (digestsPerBlock * 2) < starts.size())
262 ? *(starts.begin() +
i + 2 * digestsPerBlock)
264 std::inplace_merge(
first, middle, last);
269 DCHECK(std::is_sorted(centroids.begin(), centroids.end()));
271 size_t maxSize = digests.begin()->maxSize_;
274 std::vector<Centroid> compressed;
275 compressed.reserve(maxSize);
278 double q_limit_times_count =
k_to_q(k_limit, maxSize) *
count;
280 Centroid cur = centroids.front();
281 double weightSoFar = cur.weight();
282 double sumsToMerge = 0;
283 double weightsToMerge = 0;
284 for (
auto it = centroids.begin() + 1; it != centroids.end(); ++it) {
285 weightSoFar += it->weight();
286 if (weightSoFar <= q_limit_times_count) {
287 sumsToMerge += it->mean() * it->weight();
288 weightsToMerge += it->weight();
290 result.sum_ += cur.add(sumsToMerge, weightsToMerge);
293 compressed.push_back(cur);
294 q_limit_times_count =
k_to_q(k_limit++, maxSize) *
count;
298 result.sum_ += cur.add(sumsToMerge, weightsToMerge);
299 compressed.push_back(cur);
300 compressed.shrink_to_fit();
303 std::sort(compressed.begin(), compressed.end());
305 result.count_ =
count;
308 result.centroids_ =
std::move(compressed);
static double k_to_q(double k, double d)
constexpr detail::Map< Move > move
TDigest(size_t maxSize=100)
constexpr detail::First first