예제 #1
0
        public static void FseBuildCTableRaw(ref FseCompressTable ct, int nbBits)
        {
            int tableSize      = 1 << nbBits;
            int tableMask      = tableSize - 1;
            int maxSymbolValue = tableMask;

            Span <FseSymbolCompressionTransform> symbolTT = ct.symbolTT;

            /* Sanity checks */
            if (nbBits < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(nbBits));
            }

            /* header */
            ct.tableLog       = (ushort)nbBits;
            ct.maxSymbolValue = (ushort)maxSymbolValue;

            /* Build table */
            Span <ushort> nextStateNumber = ct.nextStateNumber;

            for (int s = 0; s < tableSize; s++)
            {
                nextStateNumber[s] = (ushort)(tableSize + s);
            }

            /* Build Symbol Transformation Table */
            int deltaNbBits = (nbBits << 16) - (1 << nbBits);

            for (int s = 0; s <= maxSymbolValue; s++)
            {
                symbolTT[s].deltaNbBits    = (uint)deltaNbBits;
                symbolTT[s].deltaFindState = s - 1;
            }
        }
예제 #2
0
        public static void FseBuildCTable(ref FseCompressTable ct, ReadOnlySpan <short> normalizedCounter, int maxSymbolValue, int tableLog)
        {
            byte[] buffer = ArrayPool <byte> .Shared.Rent(FSE_MAX_TABLESIZE);

            try
            {
                FseBuildCTableWksp(ref ct, normalizedCounter, maxSymbolValue, tableLog, buffer.AsSpan(0, FSE_MAX_TABLESIZE));
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(buffer);
            }
        }
예제 #3
0
        public static void FseBuildCTableRle(ref FseCompressTable ct, byte symbolValue)
        {
            /* header */
            ct.tableLog       = 0;
            ct.maxSymbolValue = symbolValue;

            /* Build table */
            Span <ushort> nextStateNumber = ct.nextStateNumber;

            nextStateNumber[0] = 0;
            nextStateNumber[1] = 0;  /* just in case */

            /* Build Symbol Transformation Table */
            Span <FseSymbolCompressionTransform> symbolTT = ct.symbolTT;

            symbolTT[symbolValue].deltaFindState = 0;
            symbolTT[symbolValue].deltaFindState = 0;
        }
예제 #4
0
        public static void FseBuildCTableWksp(ref FseCompressTable ct, ReadOnlySpan <short> normalizedCounter, int maxSymbolValue, int tableLog, Span <byte> workSpace)
        {
            int tableSize = 1 << tableLog;
            int tableMask = tableSize - 1;
            int step      = FseTableStep(tableSize);

            byte[] buffer = ArrayPool <byte> .Shared.Rent(4 *(FSE_MAX_SYMBOL_VALUE + 2));

            try
            {
                Span <int> cumul = MemoryMarshal.Cast <byte, int>(buffer.AsSpan()).Slice(0, FSE_MAX_SYMBOL_VALUE + 2);

                Span <byte> tableSymbol   = workSpace;
                int         highThreshold = tableSize - 1;

                if ((1 << tableLog) > workSpace.Length)
                {
                    throw new ArgumentException("Workspace is too small.", nameof(workSpace));
                }
                ct.tableLog       = (ushort)tableLog;
                ct.maxSymbolValue = (ushort)maxSymbolValue;
                Debug.Assert(tableLog < 16);

                /* symbol start positions */
                {
                    cumul[0] = 0;
                    for (int u = 1; u <= maxSymbolValue + 1; u++)
                    {
                        if (normalizedCounter[u - 1] == -1) /* Low proba symbol */
                        {
                            cumul[u] = cumul[u - 1] + 1;
                            tableSymbol[highThreshold--] = (byte)(u - 1);
                        }
                        else
                        {
                            cumul[u] = cumul[u - 1] + normalizedCounter[u - 1];
                        }
                    }
                    cumul[maxSymbolValue + 1] = tableSize + 1;
                }

                /* Spread symbols */
                {
                    int position = 0;
                    for (int symbol = 0; symbol <= maxSymbolValue; symbol++)
                    {
                        for (int nbOccurences = 0; nbOccurences < normalizedCounter[symbol]; nbOccurences++)
                        {
                            tableSymbol[position] = (byte)symbol;
                            position = (position + step) & tableMask;
                            while (position > highThreshold) /* Low proba area */
                            {
                                position = (position + step) & tableMask;
                            }
                        }
                    }

                    if (position != 0) /* Must have gone through all positions */
                    {
                        throw new InvalidDataException();
                    }
                }

                /* Build table */
                var nextStateNumber = ct.nextStateNumber;
                {
                    for (int u = 0; u < tableSize; u++)
                    {
                        byte s = tableSymbol[u];
                        nextStateNumber[cumul[s]++] = (ushort)(tableSize + u);
                    }
                }

                /* Build Symbol Transformation Table */
                var symbolTT = ct.symbolTT;
                {
                    int total = 0;
                    for (int s = 0; s <= maxSymbolValue; s++)
                    {
                        switch (normalizedCounter[s])
                        {
                        case 0:
                            /* filling nonetheless, for compatibility with FSE_getMaxNbBits() */
                            symbolTT[s].deltaNbBits = (uint)(((tableLog + 1) << 16) - (1 << tableLog));
                            break;

                        case -1:
                        case 1:
                            symbolTT[s].deltaNbBits    = (uint)((tableLog << 16) - (1 << tableLog));
                            symbolTT[s].deltaFindState = total - 1;
                            total++;
                            break;

                        default:
                            uint maxBitsOut   = (uint)tableLog - (uint)MathHelper.Log2((uint)(normalizedCounter[s] - 1));
                            uint minStatePlus = (uint)normalizedCounter[s] << (int)maxBitsOut;
                            symbolTT[s].deltaNbBits    = (maxBitsOut << 16) - minStatePlus;
                            symbolTT[s].deltaFindState = total - normalizedCounter[s];
                            total += normalizedCounter[s];
                            break;
                        }
                    }
                }
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(buffer);
            }
        }