private void DirectEncode(IEnumerable <long> values, int numValues, bool aligned,
                                  int?precalculatedFixedBitWidth)
        {
            int fixedBitWidth;

            if (precalculatedFixedBitWidth.HasValue)
            {
                fixedBitWidth = precalculatedFixedBitWidth.Value;
            }
            else
            {
                var histogram = values.GenerateHistogramOfBitWidths();
                fixedBitWidth = BitManipulation.GetBitsRequiredForPercentile(histogram, 1.0);
            }

            fixedBitWidth = aligned
                ? BitManipulation.FindNearestAlignedDirectWidth(fixedBitWidth)
                : BitManipulation.FindNearestDirectWidth(fixedBitWidth);
            var encodedFixedBitWidth = fixedBitWidth.EncodeDirectWidth();

            var byte1 = 0;

            byte1 |= 0x1 << 6;                           //7..6 Encoding Type
            byte1 |= (encodedFixedBitWidth & 0x1f) << 1; //5..1 Fixed Width
            byte1 |= (numValues - 1) >> 8;               //0    MSB of length
            var byte2 = (numValues - 1) & 0xff;          //7..0 LSBs of length

            _outputStream.WriteByte((byte)byte1);
            _outputStream.WriteByte((byte)byte2);
            _outputStream.WriteBitpackedIntegers(values, fixedBitWidth);
        }
        private DeltaEncodingResult TryDeltaEncoding(IList <long> values, bool areSigned, bool aligned, out int length,
                                                     out long minValue)
        {
            var deltas       = new long[values.Count - 1];
            var initialValue = values[0];

            minValue = initialValue; //This gets saved for the patch base if things don't work out here
            var maxValue     = initialValue;
            var initialDelta = values[1] - initialValue;
            var curDelta     = initialDelta;
            long
                deltaMax =
                0;     //This is different from the java implementation.  I believe their implementation may be a bug.
            //The first delta value is not considered for the delta bit width, so don't include it in the max value calculation
            var isIncreasing    = initialDelta > 0;
            var isDecreasing    = initialDelta < 0;
            var isConstantDelta = true;

            deltas[0] = initialDelta;

            var previousValue = initialValue;
            var i             = 1;

            foreach (var value in values.Skip(1))
            {
                curDelta = value - previousValue;
                if (value < minValue)
                {
                    minValue = value;
                }
                if (value > maxValue)
                {
                    maxValue = value;
                }

                if (value < previousValue)
                {
                    isIncreasing = false;
                }
                if (previousValue > value)
                {
                    isDecreasing = false;
                }

                if (curDelta != initialDelta)
                {
                    isConstantDelta = false;
                }

                if (i > 1) //Don't rewrite the first value because it holds the sign of the remaining values
                {
                    var absCurrDelta = Math.Abs(curDelta);
                    deltas[i - 1] = absCurrDelta;
                    if (absCurrDelta > deltaMax)
                    {
                        deltaMax = absCurrDelta;
                    }
                }

                i++;
                previousValue = value;
            }

            if (BitManipulation.SubtractionWouldOverflow(maxValue, minValue))
            {
                length = 0;
                return(DeltaEncodingResult.Overflow);
            }

            if (maxValue == minValue) //All values were identical
            {
                DeltaEncode(minValue, areSigned, values.Count);
                length = values.Count;
                return(DeltaEncodingResult.Success);
            }

            if (isConstantDelta) //All values changed by set amount
            {
                DeltaEncode(initialValue, areSigned, curDelta, values.Count);
                length = values.Count;
                return(DeltaEncodingResult.Success);
            }

            if (isIncreasing || isDecreasing)
            {
                var deltaBits = BitManipulation.NumBits((ulong)deltaMax);
                deltaBits = aligned
                    ? BitManipulation.FindNearestAlignedDirectWidth(deltaBits)
                    : BitManipulation.FindNearestDirectWidth(deltaBits);

                DeltaEncode(initialValue, areSigned, values.Count, deltas, deltaBits);
                length = values.Count;
                return(DeltaEncodingResult.Success);
            }

            length = 0;
            return(DeltaEncodingResult.NonMonotonic);
        }
Пример #3
0
        DeltaEncodingResult TryDeltaEncoding(IList <long> values, bool areSigned, bool aligned, out int length, out long minValue)
        {
            var  deltas       = new long[values.Count - 1];
            long initialValue = values[0];

            minValue = initialValue;                                                            //This gets saved for the patch base if things don't work out here
            long maxValue     = initialValue;
            long initialDelta = values[1] - initialValue;
            long curDelta     = initialDelta;
            long deltaMax     = 0;              //This is different from the java implementation.  I believe their implementation may be a bug.
            //The first delta value is not considered for the delta bit width, so don't include it in the max value calculation
            bool isIncreasing    = initialDelta > 0;
            bool isDecreasing    = initialDelta < 0;
            bool isConstantDelta = true;

            long previousValue = values[1];

            if (values[1] < minValue)
            {
                minValue = values[1];
            }
            if (values[1] > maxValue)
            {
                maxValue = values[1];
            }

            deltas[0] = initialDelta;

            int i = 2;

            foreach (var value in values.Skip(2))               //The first value is initialValue. The second value is initialDelta, already loaded. Start with the third value
            {
                curDelta = value - previousValue;
                if (value < minValue)
                {
                    minValue = value;
                }
                if (value > maxValue)
                {
                    maxValue = value;
                }

                if (value < previousValue)
                {
                    isIncreasing = false;
                }
                if (value > previousValue)
                {
                    isDecreasing = false;
                }

                if (curDelta != initialDelta)
                {
                    isConstantDelta = false;
                }

                var absCurrDelta = Math.Abs(curDelta);
                deltas[i - 1] = absCurrDelta;
                if (absCurrDelta > deltaMax)
                {
                    deltaMax = absCurrDelta;
                }

                i++;
                previousValue = value;
            }

            if (BitManipulation.SubtractionWouldOverflow(maxValue, minValue))
            {
                length = 0;
                return(DeltaEncodingResult.Overflow);
            }

            if (maxValue == minValue)               //All values after the first were identical
            {
                DeltaEncode(minValue, areSigned, values.Count);
                length = values.Count;
                return(DeltaEncodingResult.Success);
            }

            if (isConstantDelta)            //All values changed by set amount
            {
                DeltaEncode(initialValue, areSigned, curDelta, values.Count);
                length = values.Count;
                return(DeltaEncodingResult.Success);
            }

            if (isIncreasing || isDecreasing)
            {
                var deltaBits = BitManipulation.NumBits((ulong)deltaMax);
                if (aligned)
                {
                    deltaBits = BitManipulation.FindNearestAlignedDirectWidth(deltaBits);
                }
                else
                {
                    deltaBits = BitManipulation.FindNearestDirectWidth(deltaBits);
                }

                DeltaEncode(initialValue, areSigned, values.Count, deltas, deltaBits);
                length = values.Count;
                return(DeltaEncodingResult.Success);
            }

            length = 0;
            return(DeltaEncodingResult.NonMonotonic);
        }