// File: /workspace/github_c_makefile_star2_O2/Cyan4973[P]FiniteStateEntropy/programs/../lib/fse_compress.c
// Function: FSE_buildCTable_wksp
size_t FSE_buildCTable_wksp(FSE_CTable* ct,
                      const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog,
                            void* workSpace, size_t wkspSize)
{
    U32 const tableSize = 1 << tableLog;
    U32 const tableMask = tableSize - 1;
    void* const ptr = ct;
    U16* const tableU16 = ( (U16*) ptr) + 2;
    void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ;
    FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT);
    U32 const step = FSE_TABLESTEP(tableSize);
    U32 cumul[FSE_MAX_SYMBOL_VALUE+2];

    FSE_FUNCTION_TYPE* const tableSymbol = (FSE_FUNCTION_TYPE*)workSpace;
    U32 highThreshold = tableSize-1;

    /* CTable header */
    if (((size_t)1 << tableLog) * sizeof(FSE_FUNCTION_TYPE) > wkspSize) return ERROR(tableLog_tooLarge);
    tableU16[-2] = (U16) tableLog;
    tableU16[-1] = (U16) maxSymbolValue;
    assert(tableLog < 16);   /* required for threshold strategy to work */

    /* For explanations on how to distribute symbol values over the table :
     * http://fastcompression.blogspot.fr/2014/02/fse-distributing-symbol-values.html */

     #ifdef __clang_analyzer__
     memset(tableSymbol, 0, sizeof(*tableSymbol) * tableSize);   /* useless initialization, just to keep scan-build happy */
     #endif

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

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

        assert(position==0);  /* Must have initialized all positions */
    }

    /* Build table */
    {   U32 u; for (u=0; u<tableSize; u++) {
        FSE_FUNCTION_TYPE s = tableSymbol[u];   /* note : static analyzer may not understand tableSymbol is properly initialized */
        tableU16[cumul[s]++] = (U16) (tableSize+u);   /* TableU16 : sorted by symbol order; gives next state value */
    }   }

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

            case -1:
            case  1:
                symbolTT[s].deltaNbBits = (tableLog << 16) - (1<<tableLog);
                symbolTT[s].deltaFindState = total - 1;
                total ++;
                break;
            default :
                {
                    U32 const maxBitsOut = tableLog - BIT_highbit32 (normalizedCounter[s]-1);
                    U32 const minStatePlus = normalizedCounter[s] << maxBitsOut;
                    symbolTT[s].deltaNbBits = (maxBitsOut << 16) - minStatePlus;
                    symbolTT[s].deltaFindState = total - normalizedCounter[s];
                    total +=  normalizedCounter[s];
    }   }   }   }

#if 0  /* debug : symbol costs */
    DEBUGLOG(5, "\n --- table statistics : ");
    {   U32 symbol;
        for (symbol=0; symbol<=maxSymbolValue; symbol++) {
            DEBUGLOG(5, "%3u: w=%3i,   maxBits=%u, fracBits=%.2f",
                symbol, normalizedCounter[symbol],
                FSE_getMaxNbBits(symbolTT, symbol),
                (double)FSE_bitCost(symbolTT, tableLog, symbol, 8) / 256);
        }
    }
#endif

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x388, %rsp            # imm = 0x388
movl $0x1, %eax
movl %eax, %r11d
shll %cl, %r11d
movl %r11d, %ebx
shrl %ebx
testl %ecx, %ecx
cmovnel %ebx, %eax
shrq %cl, %r9
testq %r9, %r9
je 0x783a
movl %ecx, %r10d
leal -0x1(%r11), %ecx
movl %r11d, %r14d
shrl $0x3, %r14d
movw %r10w, (%rdi)
movw %dx, 0x2(%rdi)
andl $0x0, -0x80(%rsp)
incl %edx
xorl %r15d, %r15d
xorl %ebp, %ebp
movl %ecx, %r9d
leaq 0x1(%r15), %r12
cmpq %rdx, %r12
ja 0x7742
movswl (%rsi,%r15,2), %r13d
cmpl $-0x1, %r13d
je 0x772c
addl %r13d, %ebp
jmp 0x7738
incl %ebp
movl %r9d, %r13d
decl %r9d
movb %r15b, (%r8,%r13)
movl %ebp, -0x7c(%rsp,%r15,4)
movq %r12, %r15
jmp 0x7713
leal 0x1(%r11), %ebp
movl %ebp, -0x80(%rsp,%rdx,4)
addl %r14d, %ebx
addl $0x3, %ebx
xorl %r14d, %r14d
xorl %ebp, %ebp
cmpq %rdx, %r14
je 0x778d
movzwl (%rsi,%r14,2), %r12d
xorl %r15d, %r15d
testw %r12w, %r12w
cmovlel %r15d, %r12d
movzwl %r12w, %r12d
cmpl %r12d, %r15d
je 0x7788
movl %ebp, %r13d
movb %r14b, (%r8,%r13)
addl %ebx, %ebp
andl %ecx, %ebp
cmpl %r9d, %ebp
ja 0x777a
incl %r15d
jmp 0x776e
incq %r14
jmp 0x7755
movl %r11d, %ecx
xorl %r9d, %r9d
cmpq %r9, %rcx
je 0x77ba
movzbl (%r8,%r9), %ebx
leal (%rcx,%r9), %ebp
movl -0x80(%rsp,%rbx,4), %r14d
leal 0x1(%r14), %r15d
movl %r15d, -0x80(%rsp,%rbx,4)
movw %bp, 0x4(%rdi,%r14,2)
incq %r9
jmp 0x7793
movl %r10d, %r8d
shll $0x10, %r8d
subl %r11d, %r8d
leal 0x10000(%r8), %r9d
leaq (%rdi,%rax,4), %rdi
addq $0x8, %rdi
xorl %eax, %eax
xorl %r11d, %r11d
xorl %ebx, %ebx
cmpq %r11, %rdx
je 0x7844
movzwl (%rsi,%r11,2), %ecx
cmpl $0xffff, %ecx           # imm = 0xFFFF
je 0x77fb
cmpl $0x1, %ecx
je 0x77fb
testl %ecx, %ecx
jne 0x780b
movl %r9d, (%rdi,%r11,8)
jmp 0x7835
movl %r8d, (%rdi,%r11,8)
leal -0x1(%rbx), %ecx
movl %ecx, -0x4(%rdi,%r11,8)
incl %ebx
jmp 0x7835
movswl %cx, %r14d
leal -0x1(%r14), %ecx
bsrl %ecx, %ebp
movl %r10d, %ecx
subl %ebp, %ecx
movl %ebx, %ebp
subl %r14d, %ebp
addl %r14d, %ebx
shll %cl, %r14d
shll $0x10, %ecx
subl %r14d, %ecx
movl %ecx, (%rdi,%r11,8)
movl %ebp, -0x4(%rdi,%r11,8)
incq %r11
jmp 0x77da
movabsq $-0x5, %rax
addq $0x388, %rsp            # imm = 0x388
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq