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); }
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); }