* Perform compaction of the t-digest, i.e. merge the centroids as required * by the compression parameter. * * We always keep the data sorted in ascending order. This way we can reuse * the sort between compactions, and also when computing the quantiles. * * XXX Switch the direction regularly, to eliminate possible bias and improve * accuracy, as mentioned in the paper. * * XXX This initi
| 314 | * [1] https://github.com/ajwerner/tdigestc/blob/master/go/tdigest.c |
| 315 | */ |
| 316 | static void |
| 317 | tdigest_compact(tdigest_aggstate_t *state) |
| 318 | { |
| 319 | int i; |
| 320 | |
| 321 | int cur; /* current centroid */ |
| 322 | int64 count_so_far; |
| 323 | int64 total_count; |
| 324 | double denom; |
| 325 | double normalizer; |
| 326 | int start; |
| 327 | int step; |
| 328 | int n; |
| 329 | |
| 330 | /* if the digest is fully compacted, it's been already compacted */ |
| 331 | if (state->ncompacted == state->ncentroids) |
| 332 | { |
| 333 | return; |
| 334 | } |
| 335 | |
| 336 | tdigest_sort(state); |
| 337 | |
| 338 | state->ncompactions++; |
| 339 | |
| 340 | if (state->ncompactions % 2 == 0) |
| 341 | { |
| 342 | start = 0; |
| 343 | step = 1; |
| 344 | } |
| 345 | else |
| 346 | { |
| 347 | start = state->ncentroids - 1; |
| 348 | step = -1; |
| 349 | } |
| 350 | |
| 351 | total_count = state->count; |
| 352 | denom = 2 * M_PI * total_count * log(total_count); |
| 353 | normalizer = state->compression / denom; |
| 354 | |
| 355 | cur = start; |
| 356 | count_so_far = 0; |
| 357 | n = 1; |
| 358 | |
| 359 | for (i = start + step; (i >= 0) && (i < state->ncentroids); i += step) |
| 360 | { |
| 361 | int64 proposed_count; |
| 362 | double q0; |
| 363 | double q2; |
| 364 | double z; |
| 365 | bool should_add; |
| 366 | |
| 367 | proposed_count = state->centroids[cur].count + state->centroids[i].count; |
| 368 | |
| 369 | z = proposed_count * normalizer; |
| 370 | q0 = count_so_far / (double) total_count; |
| 371 | q2 = (count_so_far + proposed_count) / (double) total_count; |
| 372 | |
| 373 | should_add = (z <= (q0 * (1 - q0))) && (z <= (q2 * (1 - q2))); |
no test coverage detected