// File: /workspace/github_c_makefile_star2_O3/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
shll %cl, %eax
movl $0x1, %r11d
movl %eax, %r14d
shrl %r14d
testl %ecx, %ecx
cmovnel %r14d, %r11d
shrq %cl, %r9
testq %r9, %r9
je 0x8c86
movl %ecx, %r10d
leal -0x1(%rax), %ecx
movl %eax, %r15d
shrl $0x3, %r15d
movw %r10w, (%rdi)
movw %dx, 0x2(%rdi)
movl $0x0, -0x80(%rsp)
movl %edx, %r9d
movl %ecx, %ebx
incl %r9d
je 0x8b95
addl $0x2, %edx
cmpl $0x3, %edx
movl $0x2, %r12d
cmovael %edx, %r12d
decq %r12
xorl %edx, %edx
xorl %ebp, %ebp
movl %ecx, %ebx
movswl (%rsi,%rdx,2), %r13d
cmpl $-0x1, %r13d
je 0x8b7e
addl %r13d, %ebp
jmp 0x8b89
incl %ebp
movl %ebx, %r13d
decl %ebx
movb %dl, (%r8,%r13)
movl %ebp, -0x7c(%rsp,%rdx,4)
incq %rdx
cmpq %rdx, %r12
jne 0x8b6e
leal 0x1(%rax), %edx
movl %r9d, %r12d
movl %edx, -0x80(%rsp,%r12,4)
leal (%r15,%r14), %edx
addl $0x3, %edx
cmpl $0x1, %r9d
adcl $0x0, %r9d
xorl %r14d, %r14d
xorl %ebp, %ebp
movswl (%rsi,%r14,2), %r15d
testl %r15d, %r15d
jle 0x8bd8
xorl %r12d, %r12d
movl %ebp, %r13d
movb %r14b, (%r8,%r13)
addl %edx, %ebp
andl %ecx, %ebp
cmpl %ebx, %ebp
ja 0x8bc8
incl %r12d
cmpl %r15d, %r12d
jne 0x8bc1
incq %r14
cmpq %r9, %r14
jne 0x8bb4
movl %eax, %ecx
xorl %edx, %edx
movzbl (%r8,%rdx), %ebx
leal (%rcx,%rdx), %ebp
movl -0x80(%rsp,%rbx,4), %r14d
leal 0x1(%r14), %r15d
movl %r15d, -0x80(%rsp,%rbx,4)
movw %bp, 0x4(%rdi,%r14,2)
incq %rdx
cmpq %rdx, %rcx
jne 0x8be4
movl %r10d, %edx
shll $0x10, %edx
subl %eax, %edx
leal 0x10000(%rdx), %r8d
leaq (%rdi,%r11,4), %rdi
addq $0x8, %rdi
xorl %eax, %eax
xorl %r11d, %r11d
xorl %ebx, %ebx
movzwl (%rsi,%r11,2), %ecx
cmpl $0xffff, %ecx           # imm = 0xFFFF
je 0x8c42
cmpl $0x1, %ecx
je 0x8c42
testl %ecx, %ecx
jne 0x8c52
movl %r8d, (%rdi,%r11,8)
jmp 0x8c7c
movl %edx, (%rdi,%r11,8)
leal -0x1(%rbx), %ecx
movl %ecx, -0x4(%rdi,%r11,8)
incl %ebx
jmp 0x8c7c
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
cmpq %r11, %r9
jne 0x8c26
jmp 0x8c8d
movq $-0x5, %rax
addq $0x388, %rsp            # imm = 0x388
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq