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); }