in csharp/src/FseDecompress.cs [111:181]
public static size_t BuildDTable(FSE_DTable* dt, short[] normalizedCounter, uint maxSymbolValue, uint tableLog)
{
void* tdPtr = dt + 1; /* because *dt is unsigned, 32-bits aligned on 32-bits */
FSE_DECODE_TYPE* tableDecode = (FSE_DECODE_TYPE*)(tdPtr);
U16[] symbolNext = new U16[Fse.FSE_MAX_SYMBOL_VALUE + 1];
U32 maxSV1 = maxSymbolValue + 1;
U32 tableSize = (U32)1 << (int)tableLog;
U32 highThreshold = tableSize - 1;
/* Sanity Checks */
if (maxSymbolValue > FSE_MAX_SYMBOL_VALUE) return ERROR(Error.maxSymbolValue_tooLarge);
if (tableLog > FSE_MAX_TABLELOG) return ERROR(Error.tableLog_tooLarge);
/* Init, lay down lowprob symbols */
{
FSE_DTableHeader DTableH;
DTableH.tableLog = (U16)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--].symbol = (FSE_FUNCTION_TYPE)s;
symbolNext[s] = 1;
}
else
{
if (normalizedCounter[s] >= largeLimit) DTableH.fastMode = 0;
symbolNext[s] = (U16)normalizedCounter[s];
}
}
}
*(FSE_DTableHeader*)dt = DTableH; // memcpy(dt, &DTableH, sizeof(DTableH));
}
/* Spread symbols */
{
U32 tableMask = tableSize - 1;
U32 step = FSE_TABLESTEP(tableSize);
U32 s, position = 0;
for (s = 0; s < maxSV1; s++)
{
int i;
for (i = 0; i < normalizedCounter[s]; i++)
{
tableDecode[position].symbol = (FSE_FUNCTION_TYPE)s;
position = (position + step) & tableMask;
while (position > highThreshold) position = (position + step) & tableMask; /* lowprob area */
}
}
if (position != 0) return ERROR(Error.GENERIC); /* position must reach all cells once, otherwise normalizedCounter is incorrect */
}
/* Build Decoding table */
{
U32 u;
for (u = 0; u < tableSize; u++)
{
FSE_FUNCTION_TYPE symbol = (FSE_FUNCTION_TYPE)(tableDecode[u].symbol);
U32 nextState = symbolNext[symbol]++;
tableDecode[u].nbBits = (BYTE)(tableLog - BIT_highbit32(nextState));
tableDecode[u].newState = (U16)((nextState << tableDecode[u].nbBits) - tableSize);
}
}
return 0;
}