presto-main/src/main/java/io/prestosql/operator/aggregation/NumericHistogram.java/NumericHistogram/mergeBuckets
class NumericHistogram:    private static PriorityQueue<Entry> mergeBuckets(double[] values, double[] weights, int count, int targetCount)
    {
        checkArgument(targetCount > 0, "targetCount must be > 0");

        PriorityQueue<Entry> queue = initializeQueue(values, weights, count);

        while (count > targetCount) {
            Entry current = queue.poll();
            if (!current.isValid()) {
                // ignore entries that have already been replaced
                continue;
            }

            count--;

            Entry right = current.getRight();

            // right is guaranteed to exist because we set the penalty of the last bucket to infinity
            // so the first current in the queue can never be the last bucket
            checkState(right != null, "Expected right to be != null");
            checkState(right.isValid(), "Expected right to be valid");

            // merge "current" with "right"
            double newWeight = current.getWeight() + right.getWeight();
            double newValue = (current.getValue() * current.getWeight() + right.getValue() * right.getWeight()) / newWeight;

            // mark "right" as invalid so we can skip it if it shows up as we poll from the head of the queue
            right.invalidate();

            // compute the merged entry linked to right of right
            Entry merged = new Entry(current.getId(), newValue, newWeight, right.getRight());
            queue.add(merged);

            Entry left = current.getLeft();
            if (left != null) {
                checkState(left.isValid(), "Expected left to be valid");

                // replace "left" with a new entry with a penalty adjusted to account for (newValue, newWeight)
                left.invalidate();

                // create a new left entry linked to the merged entry
                queue.add(new Entry(left.getId(), left.getValue(), left.getWeight(), left.getLeft(), merged));
            }
        }

        return queue;
    }