// File: /workspace/github_c_makefile_star2_O2/Cyan4973[P]FiniteStateEntropy/programs/zlibh.c
// Function: build_tree
static void build_tree(tree_desc* desc)
{
    ct_data *tree         = desc->dyn_tree;
    const ct_data *stree  = desc->stat_desc->static_tree;
    int elems             = desc->max_code;
    unsigned long *csize  = desc->comp_size;
    int n;                              /* iterate over heap elements */
    int max_code = -1;                  /* largest code with non zero frequency */
    int huf_heap[2*ZLIBH_L_CODES+1];    /* heap used to build the Huffman trees */
    int heap_max;                       /* element of largest frequency */
    unsigned char depth[2*ZLIBH_L_CODES+1];
    /* Depth of each subtree used as tie breaker for trees of equal frequency */

    /* Construct the initial heap, with least frequent element in
    * huf_heap[SMALLEST]. The sons of huf_heap[n] are huf_heap[2*n] and huf_heap[2*n+1].
    * huf_heap[0] is used in replacement of heap_len (original Zlib).
    */

    huf_heap[0] = 0, heap_max = ZLIBH_HEAP_SIZE;

    for (n = 0; n <2*ZLIBH_L_CODES+1; n++)
        depth[n] = 0;

    for (n = 0; n < elems; n++) {
        if (tree[n].Freq != 0) {
            huf_heap[0]++;
            huf_heap[huf_heap[0]] = max_code = n;
            depth[n] = 0;
        } else {
            tree[n].Len = 0;
        }
    }

    /* The pkzip format requires that at least one distance code exists,
    * and that at least one bit should be sent even if there is only one
    * possible code.
    */

    if (huf_heap[0] > 1) {                /* at least two codes (non trivial tree) */
        int node;                           /* new node being created */
        unsigned short bl_count[ZLIBH_MAX_BITS+1];
        /* number of codes at each bit length for an optimal tree */

        desc->max_code = max_code;

        /* The elements huf_heap[huf_heap[0]/2+1 .. huf_heap[0]] are leaves of the tree,
        * establish sub-heaps of increasing lengths:
        */
        for (n = huf_heap[0]/2; n >= 1; n--) pqdownheap(tree, huf_heap, depth, n);

        /* Construct the Huffman tree by repeatedly combining the least two
        * frequent nodes.
        */
        node = elems;                          /* next internal node of the tree */
        do {
            int m;
            pqremove(tree, huf_heap, depth, n);  /* n = node of least frequency */
            m = huf_heap[SMALLEST];              /* m = node of next least frequency */

            huf_heap[--(heap_max)] = n;          /* keep the nodes sorted by frequency */
            huf_heap[--(heap_max)] = m;

            /* Create a new node father of n and m */
            tree[node].Freq = tree[n].Freq + tree[m].Freq;
            depth[node] = (unsigned char)((depth[n] >= depth[m] ? depth[n] : depth[m]) + 1);
            tree[n].Dad = tree[m].Dad = (unsigned short)node;

            /* and insert the new node in the heap */
            huf_heap[SMALLEST] = node++;
            pqdownheap(tree, huf_heap, depth, SMALLEST);

        } while (huf_heap[0] >= 2);

        huf_heap[--(heap_max)] = huf_heap[SMALLEST];

        /* At this point, the fields freq and dad are set. We can now
        * generate the bit lengths.
        */
        gen_bitlen((tree_desc *)desc, huf_heap, heap_max, bl_count);

        /* The field len is now set, we can generate the bit codes */
        gen_codes ((ct_data *)tree, max_code, bl_count);
    }
    else if (huf_heap[0] == 0) {     /* no code at all, create a single dummy zero code */
        desc->max_code = 0;
        tree[0].Len = 0;               // gen_bitlen shortcut
        tree[0].Code = 0;              // gen_codes shortcut (probably useless)
    }
    else {                           /* only one code, create a single one bit code */
        const int *extra     = desc->stat_desc->extra_bits;
        int base             = desc->stat_desc->extra_base;
        int xbits;                     /* extra bits */
        unsigned short f;              /* frequency */

        desc->max_code = max_code;
        for (n = 0; n < max_code; n++) {
            tree[n].Len = 0;
        }
        tree[max_code].Len = 1;        // gen_bitlen shortcut
        xbits = 0;
        if (max_code >= base) xbits = extra[max_code-base];
        f = tree[max_code].Freq;
        csize[0] += (unsigned long)f * (1 + xbits);
        if (stree) csize[1] += (unsigned long)f * (stree[max_code].Len + xbits);
        tree[max_code].Code = 0;       // gen_codes shortcut, not set earlier since it replaces .Freq
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa88, %rsp            # imm = 0xA88
movq (%rdi), %r12
movq 0x10(%rdi), %rax
movq 0x18(%rdi), %rcx
movq (%rcx), %rcx
movslq 0x8(%rdi), %r13
andl $0x0, 0x270(%rsp)
xorl %edx, %edx
cmpq $0x203, %rdx            # imm = 0x203
je 0x5649
movb $0x0, 0x60(%rsp,%rdx)
incq %rdx
jmp 0x5636
xorl %edx, %edx
testl %r13d, %r13d
movl $0x0, %esi
cmovgl %r13d, %esi
pushq $-0x1
popq %r9
cmpq %rdx, %rsi
je 0x569a
cmpw $0x0, (%r12,%rdx,4)
je 0x568e
movslq 0x270(%rsp), %r9
leaq 0x1(%r9), %r8
movl %r8d, 0x270(%rsp)
movl %edx, 0x274(%rsp,%r9,4)
movb $0x0, 0x60(%rsp,%rdx)
movl %edx, %r9d
jmp 0x5695
andw $0x0, 0x2(%r12,%rdx,4)
incq %rdx
jmp 0x565b
movl 0x270(%rsp), %ebp
cmpl $0x2, %ebp
jl 0x56db
movq %r9, 0x10(%rsp)
movq %rdi, 0x8(%rsp)
movl %r9d, 0x8(%rdi)
shrl %ebp
leaq 0x270(%rsp), %r15
leaq 0x60(%rsp), %r14
testl %ebp, %ebp
jle 0x5717
movq %r12, %rdi
movq %r15, %rsi
movq %r14, %rdx
movl %ebp, %ecx
callq 0x676f
decl %ebp
jmp 0x56c3
testl %ebp, %ebp
je 0x5a89
movq 0x18(%rdi), %rdx
movq 0x8(%rdx), %rsi
movl 0x10(%rdx), %r10d
movl %r9d, 0x8(%rdi)
xorl %edx, %edx
testl %r9d, %r9d
movl $0x0, %r8d
cmovgl %r9d, %r8d
cmpq %rdx, %r8
je 0x5a3c
andw $0x0, 0x2(%r12,%rdx,4)
incq %rdx
jmp 0x5702
movl $0x202, %r14d           # imm = 0x202
movabsq $0x20200000000, %rcx    # imm = 0x20200000000
leaq 0x270(%rsp), %rax
movl (%rax), %eax
movq %r13, %r15
movq %rcx, (%rsp)
movslq 0x274(%rsp), %rbp
leal -0x1(%rax), %ecx
movl %ecx, 0x270(%rsp)
cltq
movl 0x270(%rsp,%rax,4), %eax
movl %eax, 0x274(%rsp)
movq %r12, %rdi
leaq 0x270(%rsp), %rbx
movq %rbx, %rsi
leaq 0x60(%rsp), %rdx
pushq $0x1
popq %rcx
callq 0x676f
movslq 0x274(%rsp), %rax
movl %ebp, 0x270(%rsp,%r14,4)
movl %eax, 0x26c(%rsp,%r14,4)
movzwl (%r12,%rax,4), %ecx
addw (%r12,%rbp,4), %cx
movw %cx, (%r12,%r13,4)
movzbl 0x60(%rsp,%rbp), %ecx
movzbl 0x60(%rsp,%rax), %edx
cmpb %dl, %cl
cmoval %ecx, %edx
incb %dl
movb %dl, 0x60(%rsp,%r13)
movw %r13w, 0x2(%r12,%rax,4)
movw %r13w, 0x2(%r12,%rbp,4)
incq %r15
movl %r13d, 0x274(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
leaq 0x60(%rsp), %rdx
pushq $0x1
popq %rcx
callq 0x676f
movq (%rsp), %rcx
movl 0x270(%rsp), %eax
addq $-0x2, %r14
movabsq $-0x200000000, %rdx     # imm = 0xFFFFFFFE00000000
addq %rdx, %rcx
movq %r15, %r13
cmpl $0x1, %eax
jg 0x5734
movq %r12, %rbx
movslq 0x274(%rsp), %rdi
movq %rcx, %r8
sarq $0x20, %r8
sarq $0x1e, %rcx
movl %edi, 0x270(%rsp,%rcx)
movq 0x8(%rsp), %r10
movq (%r10), %rax
movl 0x8(%r10), %ecx
movq 0x18(%r10), %rdx
movq (%rdx), %r9
movq 0x8(%rdx), %rsi
movq %rsi, 0x18(%rsp)
movl 0x10(%rdx), %esi
movl %esi, (%rsp)
movslq 0x18(%rdx), %rsi
movq 0x10(%r10), %rdx
incq %r14
xorl %r10d, %r10d
cmpq $0x10, %r10
je 0x5863
andw $0x0, 0x20(%rsp,%r10,2)
incq %r10
jmp 0x5851
andw $0x0, 0x2(%rax,%rdi,4)
xorl %edi, %edi
cmpq $0x201, %r8             # imm = 0x201
jg 0x590b
movslq 0x274(%rsp,%r8,4), %r12
movzwl 0x2(%rax,%r12,4), %r10d
movzwl 0x2(%rax,%r10,4), %r10d
xorl %ebp, %ebp
movl %esi, %r13d
cmpl %r10d, %esi
setle %r15b
jle 0x58a0
incl %r10d
movl %r10d, %r13d
movw %r13w, 0x2(%rax,%r12,4)
cmpl %ecx, %r12d
jg 0x58fb
movslq %r13d, %r10
incw 0x20(%rsp,%r10,2)
xorl %r10d, %r10d
cmpl (%rsp), %r12d
jl 0x58d0
movl %r12d, %r10d
subl (%rsp), %r10d
movslq %r10d, %r10
movq 0x18(%rsp), %r11
movl (%r11,%r10,4), %r10d
movzwl (%rax,%r12,4), %r11d
addl %r10d, %r13d
movslq %r13d, %r13
imulq %r11, %r13
addq %r13, (%rdx)
testq %r9, %r9
je 0x58fb
movzwl 0x2(%r9,%r12,4), %r12d
movslq %r10d, %r10
addq %r12, %r10
imulq %r11, %r10
addq %r10, 0x8(%rdx)
movb %r15b, %bpl
addl %ebp, %edi
incl %r14d
incq %r8
jmp 0x586b
testl %edi, %edi
je 0x59cc
movq %rsi, %r9
shlq $0x20, %r9
movabsq $0x100000000, %r8       # imm = 0x100000000
addq %r9, %r8
leaq (%rsp,%rsi,2), %r9
addq $0x20, %r9
movabsq $-0x100000000, %r10     # imm = 0xFFFFFFFF00000000
movq %r9, %r15
movq %r8, %r11
addq %r10, %r11
movzwl -0x2(%r15), %ebp
addq $-0x2, %r15
testw %bp, %bp
je 0x593f
decl %ebp
movw %bp, (%r15)
sarq $0x1f, %r11
addw $0x2, 0x20(%rsp,%r11)
decw 0x20(%rsp,%rsi,2)
leal -0x2(%rdi), %r11d
cmpl $0x2, %edi
movl %r11d, %edi
jg 0x5939
leaq 0x26c(%rsp), %rdi
movq %rsi, %r8
subq $0x1, %r8
jb 0x59cc
movzwl 0x20(%rsp,%rsi,2), %r9d
subl $0x1, %r9d
jb 0x59c7
movslq %r14d, %r10
leaq (%rdi,%r10,4), %r11
movslq (%r11), %r10
decl %r14d
addq $-0x4, %r11
cmpl %ecx, %r10d
jg 0x5996
movzwl 0x2(%rax,%r10,4), %r15d
movq %rsi, %r11
subq %r15, %r11
je 0x5989
movzwl (%rax,%r10,4), %r15d
imulq %r15, %r11
addq %r11, (%rdx)
movw %si, 0x2(%rax,%r10,4)
jmp 0x5989
movq %r8, %rsi
jmp 0x597d
pushq $0x1
popq %rax
xorl %ecx, %ecx
movq 0x10(%rsp), %r9
cmpq $0x10, %rax
je 0x59ed
addw 0x1e(%rsp,%rax,2), %cx
addl %ecx, %ecx
movw %cx, 0x40(%rsp,%rax,2)
incq %rax
jmp 0x59d6
incl %r9d
xorl %eax, %eax
cmpq %r9, %rax
je 0x5a92
movzwl 0x2(%rbx,%rax,4), %ecx
testl %ecx, %ecx
je 0x5a37
movl %ecx, %esi
movzwl 0x40(%rsp,%rsi,2), %edx
movl %edx, %edi
incl %edi
movw %di, 0x40(%rsp,%rsi,2)
incl %ecx
xorl %esi, %esi
movl %edx, %r8d
andl $0x1, %r8d
movzwl %dx, %edx
movl %esi, %edi
orl %r8d, %edi
shrl %edx
leal (%rdi,%rdi), %esi
decl %ecx
cmpl $0x1, %ecx
ja 0x5a18
movw %di, (%rbx,%rax,4)
incq %rax
jmp 0x59f2
movslq %r9d, %rdx
movw $0x1, 0x2(%r12,%rdx,4)
xorl %r8d, %r8d
subl %r10d, %r9d
jl 0x5a56
movslq %r9d, %rdi
movl (%rsi,%rdi,4), %r8d
movzwl (%r12,%rdx,4), %esi
leal 0x1(%r8), %edi
movslq %edi, %rdi
imulq %rsi, %rdi
addq %rdi, (%rax)
testq %rcx, %rcx
je 0x5a81
movzwl 0x2(%rcx,%rdx,4), %ecx
movslq %r8d, %rdi
addq %rcx, %rdi
imulq %rsi, %rdi
addq %rdi, 0x8(%rax)
andw $0x0, (%r12,%rdx,4)
jmp 0x5a92
andl $0x0, 0x8(%rdi)
andl $0x0, (%r12)
addq $0xa88, %rsp            # imm = 0xA88
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq