/// <summary> /// Deserializes to an array of nullable <see lang="double"/> from the specified reader. /// </summary> /// <param name="reader">The reader.</param> /// <returns>An array of nullable <see lang="double"/>.</returns> public static double?[] DeserializeToNullableDoubles(BinaryReader reader) { // version not in use yet. reader.ReadByte(); var numOfItems = (int)SerializationUtils.ReadUInt32FromBase128(reader); if (numOfItems == 0) { return(EmptyNullableDoubleArray); } var result = new double?[numOfItems]; var bitBinaryReader = new BitBinaryReader(reader); var previousState = new DoubleValueState(0, -1, -1); for (int i = 0; i < numOfItems; ++i) { var newState = ReadDouble(bitBinaryReader, previousState); result[i] = double.IsNaN(newState.Value) ? (double?)null : newState.Value; previousState = newState; } return(result); }
private static bool WriteDouble(BitBinaryWriter writer, double value, DoubleValueState previousValue, out DoubleValueState newValue) { newValue = previousValue; newValue.Value = value; var xor = BitConverter.DoubleToInt64Bits(value) ^ BitConverter.DoubleToInt64Bits(previousValue.Value); if (xor == 0) { writer.WriteBit(false); } else { writer.WriteBit(true); var leadingZeros = (sbyte)BitAggregateMagic.CountLeadingZeros(xor); var trailingZeros = (sbyte)BitAggregateMagic.CountTrailingZeros(xor); if (leadingZeros > MaxLeadingZerosLength) { leadingZeros = MaxLeadingZerosLength; } int blockSize = 64 - leadingZeros - trailingZeros; int expectedSize = NumBitsToEncodeNumLeadingZeros + NumBitsToEncodeNumMeaningfulBits + blockSize; int previousBlockInformationSize = 64 - previousValue.TrailingZeros - previousValue.LeadingZeros; // The block position is set by the first non-zero XOR value. previousValue.LeadingZeros was initialized to -1s to start with. if (previousValue.LeadingZeros > 0 && leadingZeros >= previousValue.LeadingZeros && trailingZeros >= previousValue.TrailingZeros && previousBlockInformationSize < expectedSize) { writer.WriteBit(false); // there are at least as many leading zeros and as many trailing zeros as with the previous value, reuse the block position. var numMeaningfulBits = BitAggregateMagic.NumBitsInLongInteger - previousValue.LeadingZeros - previousValue.TrailingZeros; writer.WriteBits(xor, numMeaningfulBits, previousValue.TrailingZeros); } else { // start a new block position writer.WriteBit(true); writer.WriteBits(leadingZeros, NumBitsToEncodeNumLeadingZeros, 0); newValue.LeadingZeros = leadingZeros; var numMeaningfulBits = BitAggregateMagic.NumBitsInLongInteger - leadingZeros - trailingZeros; writer.WriteBits(numMeaningfulBits, NumBitsToEncodeNumMeaningfulBits, 0); newValue.TrailingZeros = trailingZeros; writer.WriteBits(xor, numMeaningfulBits, trailingZeros); } } return(true); }
private static unsafe void DeserializeValues(BinaryReader reader, double *values, int count) { var bitBinaryReader = new BitBinaryReader(reader); var previousState = new DoubleValueState(0, -1, -1); for (int i = 0; i < count; ++i) { var newState = ReadDouble(bitBinaryReader, previousState); values[i] = newState.Value; previousState = newState; } }
public static unsafe void Serialize(BinaryWriter writer, double *values, int count) { // Reserve one byte for future versioning. writer.Write((byte)1); SerializationUtils.WriteUInt32AsBase128(writer, (uint)count); if (count > 0) { BitBinaryWriter bitWriter = new BitBinaryWriter(writer); var previousState = new DoubleValueState(0, -1, -1); for (int i = 0; i < count; ++i) { DoubleValueState newState; WriteDouble(bitWriter, values[i], previousState, out newState); previousState = newState; } bitWriter.Flush(); } }
private static DoubleValueState ReadDouble(BitBinaryReader reader, DoubleValueState state) { var firstBit = reader.ReadBit(); if (!firstBit) { return(state); } var secondBit = reader.ReadBit(); long meaningFulBits; if (!secondBit) { var numBitsToRead = BitAggregateMagic.NumBitsInLongInteger - state.LeadingZeros - state.TrailingZeros; meaningFulBits = reader.ReadBits(numBitsToRead); } else { // a new block position was started since the number starts with "11". state.LeadingZeros = (sbyte)reader.ReadBits(NumBitsToEncodeNumLeadingZeros); var numBitsToRead = (sbyte)reader.ReadBits(NumBitsToEncodeNumMeaningfulBits); if (numBitsToRead == 0) { // The block size is 64 bits which becomes 0 in writing into 6 bits - overflow. // If the block size were indeed 0 bits, the xor value would be 0, and the actual value would be identical to the prior value, // so we would have bailed out early on since firstBit would be 0. numBitsToRead = (sbyte)BitAggregateMagic.NumBitsInLongInteger; } state.TrailingZeros = (sbyte)(BitAggregateMagic.NumBitsInLongInteger - state.LeadingZeros - numBitsToRead); meaningFulBits = reader.ReadBits(numBitsToRead); } var xor = meaningFulBits << state.TrailingZeros; state.Value = BitConverter.Int64BitsToDouble(xor ^ BitConverter.DoubleToInt64Bits(state.Value)); return(state); }