in csharp/src/ZStdDecompress.cs [958:1034]
static void BuildFSETable(SeqSymbol* dt,
short[] normalizedCounter, uint maxSymbolValue,
U32[] baseValue, U32[] nbAdditionalBits,
uint tableLog)
{
{
SeqSymbol* tableDecode = dt + 1;
U16[] symbolNext = new U16[MaxSeq + 1];
U32 maxSV1 = maxSymbolValue + 1;
U32 tableSize = (U32)1 << (int)tableLog;
U32 highThreshold = tableSize - 1;
/* Sanity Checks */
Debug.Assert(maxSymbolValue <= MaxSeq);
Debug.Assert(tableLog <= MaxFSELog);
/* Init, lay down lowprob symbols */
{
ZSTD_seqSymbol_header DTableH;
DTableH.tableLog = tableLog;
DTableH.fastMode = 1;
{
S16 largeLimit = (S16)(1 << (int)(tableLog - 1));
U32 s;
for (s = 0; s < maxSV1; s++)
{
if (normalizedCounter[s] == -1)
{
tableDecode[highThreshold--].baseValue = s;
symbolNext[s] = 1;
}
else
{
if (normalizedCounter[s] >= largeLimit) DTableH.fastMode = 0;
symbolNext[s] = (U16)normalizedCounter[s];
}
}
}
*(ZSTD_seqSymbol_header*)dt = DTableH; //memcpy(dt, &DTableH, sizeof(ZSTD_seqSymbol_header /*DTableH*/));
}
/* Spread symbols */
{
U32 tableMask = tableSize - 1;
U32 step = Fse.FSE_TABLESTEP(tableSize);
U32 s, position = 0;
for (s = 0; s < maxSV1; s++)
{
int i;
for (i = 0; i < normalizedCounter[s]; i++)
{
tableDecode[position].baseValue = s;
position = (position + step) & tableMask;
while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
}
}
Debug.Assert(position == 0); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
}
/* Build Decoding table */
{
U32 u;
for (u = 0; u < tableSize; u++)
{
U32 symbol = tableDecode[u].baseValue;
U32 nextState = symbolNext[symbol]++;
tableDecode[u].nbBits = (BYTE)(tableLog - BIT_highbit32(nextState));
tableDecode[u].nextState = (U16)((nextState << tableDecode[u].nbBits) - tableSize);
Debug.Assert(nbAdditionalBits[symbol] < 255);
tableDecode[u].nbAdditionalBits = (BYTE)nbAdditionalBits[symbol];
tableDecode[u].baseValue = baseValue[symbol];
}
}
}
}