示例#1
0
        private void WriteBlock(int[] array, int index, int endIndex)
        {
            int length = endIndex - index;

            if (length == 0)
            {
                return;
            }

            // Choose how to encode
            IntBlock block = IntBlock.Plan(array, index, endIndex);

            Stats?.Add(block);

            // Write the block markers
            block.Write(_writer);
            _writer.EnsureSpace(block.TotalBytes);

            // Write adjustment bits
            if (block.BitsPerAdjustment > 0)
            {
                int   bitsLeftToWrite = 0;
                ulong toWrite         = 0;

                for (int i = 0; i < block.AdjustmentCount; ++i)
                {
                    // Calculate adjustment (zero once out of real values)
                    ulong adjustment = unchecked ((uint)(i >= block.Count ? 0 : array[index + i] - (block.Base + block.Slope * i)));

                    // Add new value to bits left to write at top of long
                    toWrite += adjustment << (64 - block.BitsPerAdjustment - bitsLeftToWrite);

                    // Write all whole bytes built
                    bitsLeftToWrite += block.BitsPerAdjustment;
                    while (bitsLeftToWrite >= 8)
                    {
                        // Write top byte
                        byte nextByte = (byte)(toWrite >> 56);
                        _writer.Buffer[_writer.Index++] = nextByte;

                        // Shift to next byte
                        toWrite          = toWrite << 8;
                        bitsLeftToWrite -= 8;
                    }
                }
            }

            // Clear buffer; it's been written
            _bufferCount = 0;
        }
示例#2
0
        private void WriteComponent(BufferedWriter writer, int component, byte componentMarkerBase)
        {
            if (component == 0)
            {
                return;
            }
            byte byteLength = IntBlock.ByteLength(component);

            writer.Buffer[writer.Index++] = (byte)(componentMarkerBase + byteLength - 1);

            for (byte i = 0; i < byteLength; ++i)
            {
                writer.Buffer[writer.Index++] = (byte)(component & 0xFF);
                component = component >> 8;
            }
        }
示例#3
0
        public int Next(out int[] buffer)
        {
            buffer = _buffer;
            if (_reader.EndOfStream)
            {
                return(0);
            }

            // Read markers
            IntBlock block = IntBlock.Read(_reader);

            // Read adjustments
            //ReadScalar(block);
            IntBlockVectorReader.ReadVector(block, _reader, _buffer);

            return(block.Count);
        }
示例#4
0
        private void ReadScalar(IntBlock block)
        {
            if (block.BitsPerAdjustment == 0)
            {
                // If no adjustments, calculate each value
                int unadjusted = block.Base;
                for (int i = 0; i < block.Count; ++i)
                {
                    _buffer[i]  = unadjusted;
                    unadjusted += block.Slope;
                }
            }
            else
            {
                // Build a mask to get the low adjustmentBitLength bits
                byte  bitsPerAdjustment = block.BitsPerAdjustment;
                ulong mask = ulong.MaxValue >> (64 - bitsPerAdjustment);

                byte  bitsLeftToRead = 0;
                ulong pending        = 0;

                int countWritten = IntBlock.RequiredCount(block.Count);
                int unadjusted   = block.Base;

                for (int i = 0; i < countWritten; ++i)
                {
                    // Read enough bits to get value
                    while (bitsLeftToRead < bitsPerAdjustment)
                    {
                        pending         = pending << 8;
                        pending        += _reader.Buffer[_reader.Index++];
                        bitsLeftToRead += 8;
                    }

                    // Extract correct bits and build value
                    int adjustment = unchecked ((int)(((pending >> (bitsLeftToRead - bitsPerAdjustment)) & mask)));
                    _buffer[i] = unadjusted + adjustment;

                    bitsLeftToRead -= bitsPerAdjustment;
                    unadjusted     += block.Slope;
                }
            }
        }
示例#5
0
        public void Add(IntBlock block)
        {
            TotalBlockCount++;

            if (block.Slope != 0)
            {
                BaseAndSlopeCount++;
            }
            else if (block.Base != 0)
            {
                BaseCount++;
            }
            else
            {
                AdjustmentOnlyCount++;
            }

            CountPerLength[block.BitsPerAdjustment]++;
        }
示例#6
0
        public static unsafe void ReadVector(IntBlock block, BufferedReader reader, int[] buffer)
        {
            // Build first unadjusted vector and per-vector increment
            Vector128 <int> unadjusted = SetIncrement(block.Base, block.Slope);
            Vector128 <int> increment  = Set1(block.Slope * 4);

            if (block.BitsPerAdjustment == 0)
            {
                // If no adjustments, calculate in blocks and return
                fixed(int *resultPtr = buffer)
                {
                    for (int i = 0; i < block.Count; i += 4)
                    {
                        Unsafe.WriteUnaligned(&resultPtr[i], unadjusted);
                        unadjusted = Sse2.Add(unadjusted, increment);
                    }
                }

                return;
            }

            fixed(byte *bufferPtr = reader.Buffer)
            fixed(int *resultPtr        = buffer)
            fixed(sbyte *shuffleMaskPtr = ShuffleMasks)
            fixed(int *multiplyMaskPtr  = MultiplyMasks)
            {
                byte bitsPerAdjustment = block.BitsPerAdjustment;
                int  index             = reader.Index;
                int  count             = block.Count;

                // Calculate bytes consumed for the first and second four ints decoded (different for odd bit lengths)
                byte bytesPerEight = bitsPerAdjustment;
                byte bytes1        = (byte)(bytesPerEight / 2);

                // Calculate how much to shift values (from top of each int to bottom)
                byte shiftRightBits = (byte)(32 - bitsPerAdjustment);

                // Get shuffle mask (to get correct bits) and multiply value (to shift to top of each int) for halves
                Vector128 <sbyte> shuffle1  = Unsafe.ReadUnaligned <Vector128 <sbyte> >(&shuffleMaskPtr[32 * bitsPerAdjustment]);
                Vector128 <int>   multiply1 = Unsafe.ReadUnaligned <Vector128 <int> >(&multiplyMaskPtr[8 * bitsPerAdjustment]);

                Vector128 <sbyte> shuffle2  = Unsafe.ReadUnaligned <Vector128 <sbyte> >(&shuffleMaskPtr[32 * bitsPerAdjustment + 16]);
                Vector128 <int>   multiply2 = Unsafe.ReadUnaligned <Vector128 <int> >(&multiplyMaskPtr[8 * bitsPerAdjustment + 4]);

                for (int i = 0; i < count; i += 8, index += bytesPerEight)
                {
                    // Read source bytes
                    Vector128 <int> vector1 = Unsafe.ReadUnaligned <Vector128 <int> >(&bufferPtr[index]);
                    Vector128 <int> vector2 = Unsafe.ReadUnaligned <Vector128 <int> >(&bufferPtr[index + bytes1]);

                    // Shuffle to get the right bytes in each integer
                    vector1 = Sse.StaticCast <sbyte, int>(Ssse3.Shuffle(Sse.StaticCast <int, sbyte>(vector1), shuffle1));
                    vector2 = Sse.StaticCast <sbyte, int>(Ssse3.Shuffle(Sse.StaticCast <int, sbyte>(vector2), shuffle2));

                    // Multiply to shift each int so the desired bits are at the top
                    vector1 = Sse41.MultiplyLow(vector1, multiply1);
                    vector2 = Sse41.MultiplyLow(vector2, multiply2);

                    // Shift the desired bits to the bottom and zero the top
                    vector1 = Sse2.ShiftRightLogical(vector1, shiftRightBits);
                    vector2 = Sse2.ShiftRightLogical(vector2, shiftRightBits);

                    // Add the delta base value
                    vector1    = Sse2.Add(vector1, unadjusted);
                    unadjusted = Sse2.Add(unadjusted, increment);

                    vector2    = Sse2.Add(vector2, unadjusted);
                    unadjusted = Sse2.Add(unadjusted, increment);

                    // Write the decoded integers
                    Unsafe.WriteUnaligned(&resultPtr[i], vector1);
                    Unsafe.WriteUnaligned(&resultPtr[i + 4], vector2);
                }

                reader.Index = index;
            }
        }
示例#7
0
        public static IntBlock Plan(int[] values, int index, int endIndex)
        {
            byte count = (byte)(endIndex - index);

            // If only one value, write base only
            if (count == 1)
            {
                return(new IntBlock(count, values[index], 0, 0));
            }

            int first = values[index];

            // Compute overall slope and consider values around exact (non-int) slope
            int slopeL = (values[index + count - 1] - first) / (count - 1);
            int slopeH = slopeL + 1;

            int min  = first;
            int max  = first;
            int minL = first;
            int maxL = first;
            int minH = first;
            int maxH = first;

            // Find absolute and slope-relative min and max
            int line = 0;

            for (int i = 1; i < count; ++i)
            {
                int value = values[index + i];

                if (value < min)
                {
                    min = value;
                }
                if (value > max)
                {
                    max = value;
                }

                line += slopeL;
                int adjustment = value - line;
                if (adjustment < minL)
                {
                    minL = adjustment;
                }
                if (adjustment > maxL)
                {
                    maxL = adjustment;
                }

                adjustment = value - (line + i);
                if (adjustment < minH)
                {
                    minH = adjustment;
                }
                if (adjustment > maxH)
                {
                    maxH = adjustment;
                }
            }

            // Measure adjustments from slope and identify ideal base
            IntBlock adjustmentOnly = new IntBlock(count, 0, 0, (min < 0 ? (byte)32 : BitLength(max)));
            IntBlock withBase       = new IntBlock(count, min, 0, BitLength(max - min));
            IntBlock baseAndSlopeL  = new IntBlock(count, minL, slopeL, BitLength(maxL - minL));
            IntBlock baseAndSlopeH  = new IntBlock(count, minH, slopeH, BitLength(maxH - minH));

            IntBlock plan = adjustmentOnly;

            if (withBase.TotalBytes < plan.TotalBytes)
            {
                plan = withBase;
            }
            if (baseAndSlopeL.TotalBytes < plan.TotalBytes)
            {
                plan = baseAndSlopeL;
            }
            if (baseAndSlopeH.TotalBytes < plan.TotalBytes)
            {
                plan = baseAndSlopeH;
            }

            return(plan);
        }