Esempio n. 1
0
        public static FseDecompressState Initialize(ref FseBitReader reader, FseDecompressTableHeader header, ReadOnlySpan <FseDecompressTable> dt)
        {
            FseDecompressState fse = default;

            fse.Table = dt;
            fse.State = (int)reader.ReadBits(header.TableLog);
            return(fse);
        }
        public static bool BuildDecodeTable(ReadOnlySpan <short> normalizedCounter, int maxSymbolValue, int tableLog, Span <FseDecompressTable> decodeTable, out FseDecompressTableHeader header)
        {
            //Span<short> symbolNext = stackalloc short[FSE_MAX_SYMBOL_VALUE + 1];
            byte[] stackBuffer = ArrayPool <byte> .Shared.Rent(2 *(FSE_MAX_SYMBOL_VALUE + 1));

            try
            {
                Span <short> symbolNext = MemoryMarshal.Cast <byte, short>(stackBuffer.AsSpan()).Slice(0, FSE_MAX_SYMBOL_VALUE + 1);

                int maxSV1        = maxSymbolValue + 1;
                int tableSize     = 1 << tableLog;
                int highThreshold = tableSize - 1;

                if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE)
                {
                    throw new ArgumentOutOfRangeException(nameof(maxSymbolValue));
                }
                if (tableLog > FSE_MAX_TABLELOG)
                {
                    throw new ArgumentOutOfRangeException(nameof(tableLog));
                }

                // Init, lay down lowprob symbols
                {
                    header          = default;
                    header.TableLog = (short)tableLog;
                    //header.FastMode = 1;

                    short largeLimit = (short)(1 << (tableLog - 1));
                    for (int s = 0; s < maxSV1; s++)
                    {
                        if (normalizedCounter[s] == -1)
                        {
                            decodeTable[highThreshold--].Symbol = (byte)s;
                            symbolNext[s] = 1;
                        }
                        else
                        {
                            if (normalizedCounter[s] >= largeLimit)
                            {
                                //header.FastMode = 0;
                            }
                            symbolNext[s] = normalizedCounter[s];
                        }
                    }
                }

                /* Spread symbols */
                {
                    int tableMask = tableSize - 1;
                    int step      = GetTableStep(tableSize);
                    int position  = 0;
                    for (int s = 0; s < maxSV1; s++)
                    {
                        for (int i = 0; i < normalizedCounter[s]; i++)
                        {
                            decodeTable[position].Symbol = (byte)s;
                            position = (position + step) & tableMask;
                            while (position > highThreshold)
                            {
                                position = (position + step) & tableMask;   // lowprob area
                            }
                        }
                    }
                    if (position != 0)
                    {
                        return(false);
                    }
                }

                /* Build Decoding table */
                {
                    for (int u = 0; u < tableSize; u++)
                    {
                        byte symbol    = decodeTable[u].Symbol;
                        int  nextState = symbolNext[symbol]++;
                        decodeTable[u].NumberOfBits = (byte)(tableLog - MathHelper.Log2((uint)nextState));
                        decodeTable[u].NewState     = (ushort)((nextState << decodeTable[u].NumberOfBits) - tableSize);
                    }
                }

                return(true);
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(stackBuffer);
            }
        }
        public static int DecompressUsingTable(ReadOnlySpan <byte> source, Span <byte> destination, FseDecompressTableHeader header, ReadOnlySpan <FseDecompressTable> decodeTable)
        {
            int destinationLength = destination.Length;
            var reader            = new FseBitReader(source);

            var state1 = FseDecompressState.Initialize(ref reader, header, decodeTable);
            var state2 = FseDecompressState.Initialize(ref reader, header, decodeTable);

            while (destination.Length >= 16)
            {
                ref byte destinationRef = ref MemoryMarshal.GetReference(destination);

                destinationRef = state1.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 1)  = state2.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 2)  = state1.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 3)  = state2.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 4)  = state1.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 5)  = state2.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 6)  = state1.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 7)  = state2.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 8)  = state1.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 9)  = state2.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 10) = state1.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 11) = state2.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 12) = state1.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 13) = state2.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 14) = state1.DecodeSymbol(ref reader);
                Unsafe.Add(ref destinationRef, 15) = state2.DecodeSymbol(ref reader);

                destination = destination.Slice(16);
            }