Package com.facebook.presto.operator.aggregation

Source Code of com.facebook.presto.operator.aggregation.DoubleApproximatePercentileWeightedAggregation$DigestAndPercentile

/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.facebook.presto.operator.aggregation;

import com.facebook.presto.block.Block;
import com.facebook.presto.block.BlockBuilder;
import com.facebook.presto.block.BlockCursor;
import com.facebook.presto.tuple.TupleInfo;
import com.google.common.base.Preconditions;
import io.airlift.slice.DynamicSliceOutput;
import io.airlift.slice.SliceInput;
import io.airlift.stats.QuantileDigest;

public class DoubleApproximatePercentileWeightedAggregation
        implements VariableWidthAggregationFunction<DoubleApproximatePercentileWeightedAggregation.DigestAndPercentile>
{
    public static final DoubleApproximatePercentileWeightedAggregation INSTANCE = new DoubleApproximatePercentileWeightedAggregation();

    private static final int VALUE_INDEX = 0;
    private static final int WEIGHT_INDEX = 1;
    private static final int PERCENTILE_INDEX = 2;

    @Override
    public DigestAndPercentile initialize()
    {
        return new DigestAndPercentile(new QuantileDigest(0.01));
    }

    @Override
    public DigestAndPercentile addInput(int positionCount, Block[] blocks, int[] fields, DigestAndPercentile currentValue)
    {
        BlockCursor valueCursor = blocks[VALUE_INDEX].cursor();
        BlockCursor weightCursor = blocks[WEIGHT_INDEX].cursor();
        int valueField = fields[VALUE_INDEX];
        int weightField = fields[WEIGHT_INDEX];

        while (valueCursor.advanceNextPosition() && weightCursor.advanceNextPosition()) {
            if (!valueCursor.isNull(valueField) && !weightCursor.isNull(weightField)) {
                double value = valueCursor.getDouble(valueField);
                long weight = weightCursor.getLong(weightField);
                currentValue.digest.add(doubleToSortableLong(value), weight);
            }
        }

        BlockCursor percentileCursor = blocks[PERCENTILE_INDEX].cursor();
        int percentileField = fields[PERCENTILE_INDEX];
        if (percentileCursor.advanceNextPosition()) {
            if (!percentileCursor.isNull(percentileField)) {
                currentValue.percentile = percentileCursor.getDouble(percentileField);
            }
        }

        return currentValue;
    }

    @Override
    public DigestAndPercentile addInput(BlockCursor[] cursors, int[] fields, DigestAndPercentile currentValue)
    {
        if (!cursors[VALUE_INDEX].isNull(fields[VALUE_INDEX]) && !cursors[WEIGHT_INDEX].isNull(fields[WEIGHT_INDEX])) {
            double value = cursors[0].getDouble(fields[0]);
            long weight = cursors[WEIGHT_INDEX].getLong(fields[WEIGHT_INDEX]);
            currentValue.digest.add(doubleToSortableLong(value), weight);
        }

        if (!cursors[PERCENTILE_INDEX].isNull(fields[PERCENTILE_INDEX])) {
            currentValue.percentile = cursors[PERCENTILE_INDEX].getDouble(fields[PERCENTILE_INDEX]);
        }

        return currentValue;
    }

    @Override
    public DigestAndPercentile addIntermediate(BlockCursor[] cursors, int[] fields, DigestAndPercentile currentValue)
    {
        if (!cursors[0].isNull(fields[0])) {
            SliceInput input = cursors[0].getSlice(fields[0]).getInput();

            currentValue.digest.merge(QuantileDigest.deserialize(input));
            currentValue.percentile = input.readDouble();
        }

        return currentValue;
    }

    @Override
    public void evaluateIntermediate(DigestAndPercentile currentValue, BlockBuilder output)
    {
        if (currentValue.digest.getCount() == 0.0) {
            output.appendNull();
        }
        else {
            DynamicSliceOutput sliceOutput = new DynamicSliceOutput(currentValue.digest.estimatedSerializedSizeInBytes());
            currentValue.digest.serialize(sliceOutput);
            sliceOutput.appendDouble(currentValue.percentile);

            output.append(sliceOutput.slice());
        }
    }

    @Override
    public void evaluateFinal(DigestAndPercentile currentValue, BlockBuilder output)
    {
        if (currentValue.digest.getCount() == 0.0) {
            output.appendNull();
        }
        else {
            Preconditions.checkState(currentValue.percentile != -1, "Percentile is missing");
            output.append(longToDouble(currentValue.digest.getQuantile(currentValue.percentile)));
        }
    }

    @Override
    public long estimateSizeInBytes(DigestAndPercentile value)
    {
        // TODO: account for DigestAndPercentile object
        return value.digest.estimatedInMemorySizeInBytes();
    }

    @Override
    public TupleInfo getFinalTupleInfo()
    {
        return TupleInfo.SINGLE_DOUBLE;
    }

    @Override
    public TupleInfo getIntermediateTupleInfo()
    {
        return TupleInfo.SINGLE_VARBINARY;
    }

    private static double longToDouble(long value)
    {
        if (value < 0) {
            value ^= 0x7fffffffffffffffL;
        }

        return Double.longBitsToDouble(value);
    }

    private static long doubleToSortableLong(double value)
    {
        long result = Double.doubleToRawLongBits(value);

        if (result < 0) {
            result ^= 0x7fffffffffffffffL;
        }

        return result;
    }

    public final static class DigestAndPercentile
    {
        private QuantileDigest digest;
        private double percentile = -1;

        public DigestAndPercentile(QuantileDigest digest)
        {
            this.digest = digest;
        }
    }
}
TOP

Related Classes of com.facebook.presto.operator.aggregation.DoubleApproximatePercentileWeightedAggregation$DigestAndPercentile

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.