MCPcopy Create free account
hub / github.com/documentdb/documentdb / tdigest_sort

Function tdigest_sort

pg_documentdb/src/aggregation/bson_tdigest.c:229–295  ·  view source on GitHub ↗

* Sort centroids in the digest. * * We have to sort the whole array, because we don't just simply sort the * centroids - we do the rebalancing of items with the same mean too. */

Source from the content-addressed store, hash-verified

227 * centroids - we do the rebalancing of items with the same mean too.
228 */
229static void
230tdigest_sort(tdigest_aggstate_t *state)
231{
232 int i;
233 int64 count_so_far;
234 int64 next_group;
235 int64 median_count;
236
237 /* do qsort on the non-sorted part */
238 pg_qsort(state->centroids,
239 state->ncentroids,
240 sizeof(centroid_t), centroid_cmp);
241
242 /*
243 * The centroids are sorted by (mean,count). That's fine for centroids up
244 * to median, but above median this ordering is incorrect for centroids
245 * with the same mean (or for groups crossing the median boundary). To fix
246 * this we 'rebalance' those groups. Those entirely above median can be
247 * simply sorted in the opposite order, while those crossing the median
248 * need to be rebalanced depending on what part is below/above median.
249 */
250 count_so_far = 0;
251 next_group = 0; /* includes count_so_far */
252 median_count = (state->count / 2);
253
254 /*
255 * Split the centroids into groups with the same mean, process each group
256 * depending on whether it falls before/after median.
257 */
258 i = 0;
259 while (i < state->ncentroids)
260 {
261 int j = i;
262 int group_size = 0;
263
264 /* determine the end of the group */
265 while ((j < state->ncentroids) &&
266 (state->centroids[i].mean == state->centroids[j].mean))
267 {
268 next_group += state->centroids[j].count;
269 group_size++;
270 j++;
271 }
272
273 /*
274 * We can ignore groups of size 1 (Total count of centroids, not counts), as
275 * those are trivially sorted.
276 */
277 if (group_size > 1)
278 {
279 if (count_so_far >= median_count)
280 {
281 /* group fully above median - reverse the order */
282 reverse_centroids(&state->centroids[i], group_size);
283 }
284 else if (next_group >= median_count) /* group split by median */
285 {
286 rebalance_centroids(&state->centroids[i], group_size,

Callers 1

tdigest_compactFunction · 0.85

Calls 2

reverse_centroidsFunction · 0.85
rebalance_centroidsFunction · 0.85

Tested by

no test coverage detected