// File: /workspace/github_cpp_makefile_star2_O1/ctSkennerton[P]fxtract/util/ordhuff.c
// Function: ordhuff
void
ordhuff( 
    int             ncodes,        // length of (all) vectors.
    unsigned const  vFreq[], 
    unsigned        vCode[],
    unsigned        vBits[])
{
    int             i;
    unsigned        scale, sum, z;
    unsigned        prevcode, prevbits, currbits, prevmask, comb;

    for (i = ncodes, sum = vFreq[0]; --i > 0;) sum += vFreq[i];

    /* Calculate initial code widths, as left-justified bitmasks;
     *   e.g 0xF8000000 for a code with length "5".
     * NOTE: 0x7FFFFFFF as a quotient can cause overflows,
     *   i.e. vCode[i] < vCode[i-1].
     */
    scale   = 0x3FFFFFFF / sum;
        //XXX: use a nonlinear scaling
    for (i = ncodes; --i >= 0;)
	vBits[i] = -1 << fls(vFreq[i] * scale);

    /* Calculate initial code values, also left-justified.
     * gcc has a bit of trouble optimizing induction values here.
     */
    prevcode = vCode[0] = 0;
    prevbits = vBits[0];

    for (i = 1; i < ncodes; ++i) {
        currbits = vBits[i];
        vCode[i] = (prevcode - (currbits & prevbits)) & currbits;
        prevcode = vCode[i];
        prevbits = currbits;
    }

    /* Comb out unnecessary bits, equivalent to tree nodes with
     * one child. A bit is combed out, if it is a zero bit in 
     * the current code, and it was either an unnecessary bit 
     * in the previous code, or not part of the previous code 
     * (below the masked bits).
     */
    prevmask = comb = 0;
    for (i = ncodes; --i >= 0;) {
        int             x;  // signed for easy high-bit test
        unsigned        currmask = vBits[i], currcode = vCode[i];

        comb = (~prevmask | comb) & ~currcode & currmask;
        prevmask = currmask;

        // Squeeze out leading useless bits in a tiny loop:
        for (x = comb; x < 0; x <<= 1, currmask <<= 1)
            currcode <<= 1;

        // Squeeze out remaining combed bits in a larger loop:
        for (; x; x &= x - 1, currmask <<= 1)
            currcode += ((x - 1) ^ x) & currcode;

        vBits[i] = currmask, vCode[i] = currcode;
    }

    /* Convert left-justified codes and corresponding bitmasks
     *  to right-justified codes and corresponding lengths.
     * OTOH: probably more useful to leave codes left-justified
     *	and use an int64_t shifter (e.g SHLD %cl, %edx, %eax)
     */
    for (i = ncodes; --i >= 0;) {
        vCode[i] >>= z = bsrl(vBits[i]);
        vBits[i] = 32 - z;
    }
}

// Assembly:
movq %rcx, %r8
movq %rdx, %r9
movl (%rsi), %ecx
movl %edi, %r10d
cmpl $0x2, %edi
jl 0x14ed
leaq 0x1(%r10), %rax
addl -0x8(%rsi,%rax,4), %ecx
decq %rax
cmpq $0x2, %rax
jg 0x14e0
movl $0x3fffffff, %eax       # imm = 0x3FFFFFFF
xorl %edx, %edx
divl %ecx
testl %edi, %edi
jle 0x152c
movl %eax, %edx
leaq 0x1(%r10), %r11
movl -0x8(%rsi,%r11,4), %eax
imull %edx, %eax
testl %eax, %eax
je 0x1515
bsrl %eax, %eax
movl %eax, %ecx
incl %ecx
jmp 0x1517
xorl %ecx, %ecx
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
shll %cl, %eax
movl %eax, -0x8(%r8,%r11,4)
decq %r11
cmpq $0x1, %r11
jg 0x1500
movl $0x0, (%r9)
cmpl $0x2, %edi
jl 0x155a
movl (%r8), %edx
xorl %eax, %eax
movl $0x1, %ecx
movl (%r8,%rcx,4), %esi
andl %esi, %edx
subl %edx, %eax
andl %esi, %eax
movl %eax, (%r9,%rcx,4)
incq %rcx
movl %esi, %edx
cmpq %rcx, %r10
jne 0x1542
testl %edi, %edi
jle 0x15c6
pushq %rbp
pushq %r14
pushq %rbx
xorl %eax, %eax
movq %r10, %rcx
xorl %edx, %edx
movl -0x4(%r9,%rcx,4), %esi
notl %edx
orl %eax, %edx
movl %esi, %eax
notl %eax
andl %edx, %eax
movl -0x4(%r8,%rcx,4), %edx
movl %edx, %r11d
andl %edx, %eax
movl %eax, %ebx
jns 0x1591
addl %esi, %esi
addl %ebx, %ebx
addl %r11d, %r11d
testl %ebx, %ebx
js 0x1586
testl %ebx, %ebx
je 0x15ad
leal -0x1(%rbx), %ebp
movl %ebp, %r14d
xorl %ebx, %r14d
andl %esi, %r14d
addl %r14d, %esi
addl %r11d, %r11d
andl %ebx, %ebp
movl %ebp, %ebx
jne 0x1595
leaq -0x1(%rcx), %rbx
movl %r11d, (%r8,%rbx,4)
movl %esi, (%r9,%rbx,4)
cmpq $0x1, %rcx
movq %rbx, %rcx
jg 0x1569
popq %rbx
popq %r14
popq %rbp
testl %edi, %edi
jle 0x15ef
incq %r10
movl -0x8(%r8,%r10,4), %eax
bsrl %ecx, %ecx
shrl %cl, -0x8(%r9,%r10,4)
movl $0x20, %eax
subl %ecx, %eax
movl %eax, -0x8(%r8,%r10,4)
decq %r10
cmpq $0x1, %r10
jg 0x15cd
retq