private (ByteWriter, string error) encodePacked() { if (len == 0) { return(null, null); } // Encode all but the first value. Fist value is written unencoded // using 8 bytes. ByteWriter b = new ByteWriter(1 + 8 * len); // 4 high bits of first byte store the encoding type for the block b.Write((byte)(intCompressedSimple << 4)); // Write the first value since it's not part of the encoded values b.Write(values[0]); var error = Simple8bEncoder.EncodeAll(values, 1, len, b); if (error != null) { b.Release(); return(null, error); } return(b, null); }
public (ByteWriter, string) EncodingAll(Span <ulong> src) { int srclen = src.Length; if (srclen == 0) { return(null, null); // Nothing to do } ulong max = 0, div = (ulong)1e12; ulong[] deltaarray = ArrayPool <ulong> .Shared.Rent(srclen); Span <ulong> deltas = new Span <ulong>(deltaarray); deltas[0] = src[0]; ByteWriter result; if (srclen > 1) { for (int i = srclen - 1; i > 0; i--) { deltas[i] = src[i] - src[i - 1]; if (deltas[i] > max) { max = deltas[i]; } } bool rle = true; var delta1 = deltas[1]; for (int i = 2; i < srclen; i++) { if (delta1 != deltas[i]) { rle = false; break; } } // Deltas are the same - encode with RLE if (rle) { // Large varints can take up to 10 bytes. We're storing 3 + 1 // type byte. result = new ByteWriter(31); // 4 high bits used for the encoding type result.Write((byte)(timeCompressedRLE << 4)); // The first value result.Write(deltas[0]); // The first delta, checking the divisor // given all deltas are the same, we can do a single check for the divisor ulong v = deltas[1]; while (div > 1 && v % div != 0) { div /= 10; } if (div > 1) { // 4 low bits are the log10 divisor result.EndWrite()[0] |= (byte)Math.Log10(div); result.Write(Varint.GetBytes(deltas[1] / div)); } else { result.Write(Varint.GetBytes(deltas[1])); } // The number of times the delta is repeated result.Write(Varint.GetBytes(srclen)); ArrayPool <ulong> .Shared.Return(deltaarray); return(result, null); } } // We can't compress this time-range, the deltas exceed 1 << 60 if (max > Simple8bEncoder.MaxValue) { // Encode uncompressed. int sz = 1 + srclen * 8; result = new ByteWriter(sz); result.Write((byte)(timeUncompressed << 4)); for (int i = 0; i < srclen; i++) { result.Write(deltas[i]); } ArrayPool <ulong> .Shared.Return(deltaarray); return(result, null); } // find divisor only if we're compressing with simple8b for (int i = 1; i < srclen && div > 1; i++) { // If our value is divisible by 10, break. Otherwise, try the next smallest divisor. var v = deltaarray[i]; while (div > 1 && v % div != 0) { div /= 10; } } // Only apply the divisor if it's greater than 1 since division is expensive. if (div > 1) { for (int i = 1; i < srclen; i++) { deltas[i] /= div; } } result = new ByteWriter(1 + srclen * 8); result.Write((byte)((timeCompressedPackedSimple << 4) | (byte)Math.Log10(div))); // Write the first value since it's not part of the encoded values result.Write(deltas[0]); // Encode with simple8b - fist value is written unencoded using 8 bytes. var error = Simple8bEncoder.EncodeAll(deltaarray, 1, srclen, result); if (error != null) { result.Release(); return(null, error); } return(result, null); }
public TimeEncoder(int sz) { ts = new ulong[Constants.DefaultMaxPointsPerBlock]; enc = new Simple8bEncoder(); }
public (ByteWriter, string) EncodingAll(Span <long> src) { int srclen = src.Length; ulong max = 0; ulong[] deltasarray = ArrayPool <ulong> .Shared.Rent(srclen); Span <ulong> deltas = new Span <ulong>(deltasarray); for (int i = srclen - 1; i > 0; i--) { long l = src[i] - src[i - 1]; ulong delta = Encoding.ZigZagEncode(l); deltas[i] = delta; if (delta > max) { max = delta; } } deltas[0] = Encoding.ZigZagEncode(src[0]); ByteWriter result; if (srclen > 2) { var rle = true; for (int i = 2; i < srclen; i++) { if (deltas[1] != deltas[i]) { rle = false; break; } } if (rle) { // Large varints can take up to 10 bytes. We're storing 3 + 1 // type byte. result = new ByteWriter(31); // 4 high bits used for the encoding type result.Write((byte)(intCompressedRLE << 4)); // The first value result.Write(deltas[0]); // The first delta result.Write(Varint.GetBytes(deltas[1])); // The number of times the delta is repeated result.Write(Varint.GetBytes(srclen - 1)); ArrayPool <ulong> .Shared.Return(deltasarray); return(result, null); } } if (max > Simple8bEncoder.MaxValue)// There is an encoded value that's too big to simple8b encode. { // Encode uncompressed. int sz = 1 + srclen * 8; result = new ByteWriter(sz); result.Write((byte)(intUncompressed << 4)); for (int i = 0; i < srclen; i++) { result.Write(deltas[i]); } ArrayPool <ulong> .Shared.Return(deltasarray); return(result, null); } result = new ByteWriter(1 + srclen * 8); result.Write((byte)(intCompressedSimple << 4)); // Write the first value since it's not part of the encoded values result.Write(deltas[0]); var error = Simple8bEncoder.EncodeAll(deltasarray, 1, srclen, result); ArrayPool <ulong> .Shared.Return(deltasarray); if (error != null) { result.Release(); return(null, error); } return(result, null); }