// File: /workspace/github_c_makefile_star2_O2/enzo1982[P]smooth/libraries/libwebp/src/utils/huffman_utils.c
// Function: BuildHuffmanTable
static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
                             const int code_lengths[], int code_lengths_size,
                             uint16_t sorted[]) {
  HuffmanCode* table = root_table;  // next available space in table
  int total_size = 1 << root_bits;  // total size root table + 2nd level table
  int len;                          // current code length
  int symbol;                       // symbol index in original or sorted table
  // number of codes of each length:
  int count[MAX_ALLOWED_CODE_LENGTH + 1] = { 0 };
  // offsets in sorted table for each length:
  int offset[MAX_ALLOWED_CODE_LENGTH + 1];

  assert(code_lengths_size != 0);
  assert(code_lengths != NULL);
  assert((root_table != NULL && sorted != NULL) ||
         (root_table == NULL && sorted == NULL));
  assert(root_bits > 0);

  // Build histogram of code lengths.
  for (symbol = 0; symbol < code_lengths_size; ++symbol) {
    if (code_lengths[symbol] > MAX_ALLOWED_CODE_LENGTH) {
      return 0;
    }
    ++count[code_lengths[symbol]];
  }

  // Error, all code lengths are zeros.
  if (count[0] == code_lengths_size) {
    return 0;
  }

  // Generate offsets into sorted symbol table by code length.
  offset[1] = 0;
  for (len = 1; len < MAX_ALLOWED_CODE_LENGTH; ++len) {
    if (count[len] > (1 << len)) {
      return 0;
    }
    offset[len + 1] = offset[len] + count[len];
  }

  // Sort symbols by length, by symbol order within each length.
  for (symbol = 0; symbol < code_lengths_size; ++symbol) {
    const int symbol_code_length = code_lengths[symbol];
    if (code_lengths[symbol] > 0) {
      if (sorted != NULL) {
        if(offset[symbol_code_length] >= code_lengths_size) {
            return 0;
        }
        sorted[offset[symbol_code_length]++] = symbol;
      } else {
        offset[symbol_code_length]++;
      }
    }
  }

  // Special case code with only one value.
  if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) {
    if (sorted != NULL) {
      HuffmanCode code;
      code.bits = 0;
      code.value = (uint16_t)sorted[0];
      ReplicateValue(table, 1, total_size, code);
    }
    return total_size;
  }

  {
    int step;              // step size to replicate values in current table
    uint32_t low = 0xffffffffu;        // low bits for current root entry
    uint32_t mask = total_size - 1;    // mask for low bits
    uint32_t key = 0;      // reversed prefix code
    int num_nodes = 1;     // number of Huffman tree nodes
    int num_open = 1;      // number of open branches in current tree level
    int table_bits = root_bits;        // key length of current table
    int table_size = 1 << table_bits;  // size of current table
    symbol = 0;
    // Fill in root table.
    for (len = 1, step = 2; len <= root_bits; ++len, step <<= 1) {
      num_open <<= 1;
      num_nodes += num_open;
      num_open -= count[len];
      if (num_open < 0) {
        return 0;
      }
      if (root_table == NULL) continue;
      for (; count[len] > 0; --count[len]) {
        HuffmanCode code;
        code.bits = (uint8_t)len;
        code.value = (uint16_t)sorted[symbol++];
        ReplicateValue(&table[key], step, table_size, code);
        key = GetNextKey(key, len);
      }
    }

    // Fill in 2nd level tables and add pointers to root table.
    for (len = root_bits + 1, step = 2; len <= MAX_ALLOWED_CODE_LENGTH;
         ++len, step <<= 1) {
      num_open <<= 1;
      num_nodes += num_open;
      num_open -= count[len];
      if (num_open < 0) {
        return 0;
      }
      for (; count[len] > 0; --count[len]) {
        HuffmanCode code;
        if ((key & mask) != low) {
          if (root_table != NULL) table += table_size;
          table_bits = NextTableBitSize(count, len, root_bits);
          table_size = 1 << table_bits;
          total_size += table_size;
          low = key & mask;
          if (root_table != NULL) {
            root_table[low].bits = (uint8_t)(table_bits + root_bits);
            root_table[low].value = (uint16_t)((table - root_table) - low);
          }
        }
        if (root_table != NULL) {
          code.bits = (uint8_t)(len - root_bits);
          code.value = (uint16_t)sorted[symbol++];
          ReplicateValue(&table[key >> root_bits], step, table_size, code);
        }
        key = GetNextKey(key, len);
      }
    }

    // Check if tree is full.
    if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) {
      return 0;
    }
  }

  return total_size;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xf8, %rsp
movl %ecx, %eax
movl %esi, %ecx
pushq $0x1
popq %rbx
movl %ebx, %r10d
movq %rcx, 0x18(%rsp)
shll %cl, %r10d
pxor %xmm0, %xmm0
movdqa %xmm0, 0xa0(%rsp)
movdqa %xmm0, 0x90(%rsp)
movdqa %xmm0, 0x80(%rsp)
movdqa %xmm0, 0x70(%rsp)
testl %eax, %eax
je 0xe1239
testq %rdx, %rdx
je 0xe1252
movq %rdi, %r12
testq %rdi, %rdi
setne %cl
testq %r8, %r8
setne %sil
testb %sil, %cl
jne 0xe0db0
movq %r12, %rcx
orq %r8, %rcx
jne 0xe1284
cmpl $0x0, 0x18(%rsp)
jle 0xe126b
xorl %ecx, %ecx
testl %eax, %eax
movl $0x0, %esi
cmovgl %eax, %esi
cmpq %rcx, %rsi
je 0xe0ddf
movslq (%rdx,%rcx,4), %rdi
cmpq $0xf, %rdi
jg 0xe0de5
incl 0x70(%rsp,%rdi,4)
incq %rcx
jmp 0xe0dc7
cmpl %eax, 0x70(%rsp)
jne 0xe0dfd
xorl %r10d, %r10d
movl %r10d, %eax
addq $0xf8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
andl $0x0, 0xb4(%rsp)
xorl %edi, %edi
cmpq $0xe, %rdi
je 0xe0e35
movl 0x74(%rsp,%rdi,4), %r11d
leal 0x1(%rdi), %ecx
movl %ebx, %r9d
shll %cl, %r9d
cmpl %r9d, %r11d
jg 0xe0de5
addl 0xb4(%rsp,%rdi,4), %r11d
movl %r11d, 0xb8(%rsp,%rdi,4)
incq %rdi
jmp 0xe0e07
xorl %ecx, %ecx
cmpq %rcx, %rsi
je 0xe0e7a
movslq (%rdx,%rcx,4), %rdi
testq %rdi, %rdi
jle 0xe0e75
movslq 0xb0(%rsp,%rdi,4), %r11
testq %r8, %r8
je 0xe0e6a
cmpl %eax, %r11d
jge 0xe0de5
leal 0x1(%r11), %r9d
movl %r9d, 0xb0(%rsp,%rdi,4)
movw %cx, (%r8,%r11,2)
jmp 0xe0e75
incl %r11d
movl %r11d, 0xb0(%rsp,%rdi,4)
incq %rcx
jmp 0xe0e37
movl 0xec(%rsp), %eax
cmpl $0x1, %eax
jne 0xe0f98
testq %r8, %r8
je 0xe0de8
movzwl (%r8), %eax
shll $0x10, %eax
movslq %r10d, %rdx
cmpq $0x2, %rdx
pushq $0x1
popq %rsi
cmovgeq %rdx, %rsi
leal 0x3(%rsi), %ecx
andl $-0x4, %ecx
decq %rsi
movq %rsi, %xmm0
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
leaq (%r12,%rdx,4), %rdx
addq $-0x4, %rdx
xorl %esi, %esi
movdqa 0x3ca83(%rip), %xmm1    # 0x11d950
movdqa 0x382fb(%rip), %xmm2    # 0x1191d0
movdqa 0x3ba93(%rip), %xmm3    # 0x11c970
pxor %xmm3, %xmm0
pcmpeqd %xmm4, %xmm4
movq %rsi, %xmm5
pshufd $0x44, %xmm5, %xmm5     # xmm5 = xmm5[0,1,0,1]
movdqa %xmm5, %xmm6
por %xmm2, %xmm6
pxor %xmm3, %xmm6
movdqa %xmm6, %xmm7
pcmpgtd %xmm0, %xmm7
pcmpeqd %xmm0, %xmm6
pshufd $0xf5, %xmm6, %xmm8     # xmm8 = xmm6[1,1,3,3]
pand %xmm7, %xmm8
pshufd $0xf5, %xmm7, %xmm6     # xmm6 = xmm7[1,1,3,3]
por %xmm8, %xmm6
movd %xmm6, %edi
notl %edi
testb $0x1, %dil
je 0xe0f2a
movl %eax, (%rdx)
pxor %xmm4, %xmm6
pextrw $0x4, %xmm6, %edi
testb $0x1, %dil
je 0xe0f3c
movl %eax, -0x4(%rdx)
por %xmm1, %xmm5
pxor %xmm3, %xmm5
movdqa %xmm5, %xmm6
pcmpgtd %xmm0, %xmm6
pcmpeqd %xmm0, %xmm5
pshufd $0xf5, %xmm5, %xmm7     # xmm7 = xmm5[1,1,3,3]
pand %xmm6, %xmm7
pshufd $0xf5, %xmm6, %xmm5     # xmm5 = xmm6[1,1,3,3]
por %xmm7, %xmm5
pxor %xmm4, %xmm5
pextrw $0x0, %xmm5, %edi
testb $0x1, %dil
je 0xe0f74
movl %eax, -0x8(%rdx)
pextrw $0x4, %xmm5, %edi
testb $0x1, %dil
je 0xe0f82
movl %eax, -0xc(%rdx)
addq $0x4, %rsi
addq $-0x10, %rdx
cmpq %rsi, %rcx
jne 0xe0ee5
jmp 0xe0de8
movq %rax, 0x68(%rsp)
movq %r8, 0x60(%rsp)
leal -0x1(%r10), %eax
movl %eax, 0x54(%rsp)
movq 0x18(%rsp), %rax
incl %eax
movq %rax, 0x38(%rsp)
xorl %ebp, %ebp
pushq $0x2
popq %rax
movl %eax, 0x8(%rsp)
pushq $0x1
popq %r13
movl %ebx, %edx
movl $0x0, 0x4(%rsp)
cmpq 0x38(%rsp), %r13
je 0xe1083
movq %rdx, 0x28(%rsp)
leal (%rdx,%rdx), %ecx
movl 0x70(%rsp,%r13,4), %r14d
subl %r14d, %ecx
js 0xe0de5
testq %r12, %r12
je 0xe1067
movl %ecx, 0x14(%rsp)
movq %rbx, 0x20(%rsp)
movzbl %r13b, %eax
movl %eax, 0x40(%rsp)
movslq 0x4(%rsp), %rax
movq 0x60(%rsp), %rcx
leaq (%rcx,%rax,2), %r15
testl %r14d, %r14d
jle 0xe105e
movl %ebp, %eax
leaq (%r12,%rax,4), %rdi
movzwl (%r15), %ecx
shll $0x10, %ecx
addl 0x40(%rsp), %ecx
movl 0x8(%rsp), %esi
movl %r10d, %edx
movq %r12, %rbx
movq %r10, %r12
callq 0xe1321
movl %ebp, %edi
movl %r13d, %esi
callq 0xe1362
movq %r12, %r10
movq %rbx, %r12
movl %eax, %ebp
decl %r14d
movl %r14d, 0x70(%rsp,%r13,4)
incl 0x4(%rsp)
addq $0x2, %r15
jmp 0xe1012
movq 0x20(%rsp), %rbx
movl 0x14(%rsp), %ecx
movq 0x28(%rsp), %rax
leal (%rbx,%rax,2), %ebx
incq %r13
movl 0x8(%rsp), %eax
addl %eax, %eax
movl %eax, 0x8(%rsp)
movl %ecx, %edx
jmp 0xe0fcd
movq %rbx, 0x20(%rsp)
movl 0x18(%rsp), %ecx
leaq (%rsp,%rcx,4), %rax
addq $0x74, %rax
movq %rax, 0x58(%rsp)
pushq $0x2
popq %rax
movl %eax, 0x28(%rsp)
pushq $-0x1
popq %rbx
movl %r10d, 0x34(%rsp)
movq %r12, 0x8(%rsp)
cmpl $0xe, %ecx
jg 0xe121b
incq %rcx
leal (%rdx,%rdx), %eax
movl 0x70(%rsp,%rcx,4), %r15d
subl %r15d, %eax
js 0xe0de5
movl %eax, 0x4c(%rsp)
movq 0x20(%rsp), %rax
leal (%rax,%rdx,2), %eax
movq %rax, 0x20(%rsp)
movq %rcx, 0x40(%rsp)
subl 0x18(%rsp), %ecx
pushq $0x1
popq %rax
shll %cl, %eax
movl %eax, 0x50(%rsp)
movzbl %cl, %eax
movl %eax, 0x14(%rsp)
testl %r15d, %r15d
jle 0xe11ef
movl %ebp, %r14d
andl 0x54(%rsp), %r14d
cmpl %ebx, %r14d
jne 0xe1117
testq %r12, %r12
jne 0xe1186
movq %r10, %r13
jmp 0xe11c4
movslq %r10d, %rax
movq 0x8(%rsp), %rcx
leaq (%rcx,%rax,4), %rax
movq 0x38(%rsp), %rcx
movl %ecx, %edx
movq 0x58(%rsp), %rcx
movl 0x50(%rsp), %esi
cmpl $0xe, %edx
jg 0xe1146
subl (%rcx), %esi
jle 0xe1149
addl %esi, %esi
addq $0x4, %rcx
incl %edx
jmp 0xe1133
pushq $0xf
popq %rdx
movl %edx, %ecx
subl 0x18(%rsp), %ecx
pushq $0x1
popq %rsi
movl %esi, %r10d
shll %cl, %r10d
addl %r10d, 0x34(%rsp)
testq %r12, %r12
je 0xe11ea
movl %r14d, %ecx
movb %dl, (%r12,%rcx,4)
movl %eax, %edx
subl %r12d, %edx
shrl $0x2, %edx
subl %r14d, %edx
movw %dx, 0x2(%r12,%rcx,4)
movq %rax, 0x8(%rsp)
movl %r14d, %ebx
movl 0x4(%rsp), %ecx
movslq %ecx, %rax
incl %ecx
movl %ecx, 0x4(%rsp)
movl %ebp, %edx
movq 0x18(%rsp), %rcx
shrl %cl, %edx
movq 0x8(%rsp), %rcx
leaq (%rcx,%rdx,4), %rdi
movq 0x60(%rsp), %rcx
movzwl (%rcx,%rax,2), %ecx
shll $0x10, %ecx
addl 0x14(%rsp), %ecx
movl 0x28(%rsp), %esi
movq %r10, %r13
movl %r10d, %edx
callq 0xe1321
movl %ebx, %r14d
movl %ebp, %edi
movq 0x40(%rsp), %rbx
movl %ebx, %esi
callq 0xe1362
movl %eax, %ebp
decl %r15d
movl %r15d, 0x70(%rsp,%rbx,4)
movl %r14d, %ebx
movq %r13, %r10
jmp 0xe10f4
movq %r10, %r13
jmp 0xe11c7
movl 0x28(%rsp), %eax
addl %eax, %eax
movl %eax, 0x28(%rsp)
addq $0x4, 0x58(%rsp)
movq 0x38(%rsp), %rax
incl %eax
movq %rax, 0x38(%rsp)
movl 0x4c(%rsp), %eax
movl %eax, %edx
movq 0x40(%rsp), %rcx
jmp 0xe10ad
movq 0x68(%rsp), %rax
leal -0x1(,%rax,2), %eax
xorl %r10d, %r10d
cmpl %eax, 0x20(%rsp)
cmovel 0x34(%rsp), %r10d
jmp 0xe0de8
leaq 0x3c7f5(%rip), %rdi     # 0x11da35
leaq 0x3c73e(%rip), %rsi     # 0x11d985
leaq 0x3c7fe(%rip), %rcx     # 0x11da4c
pushq $0x5c
jmp 0xe129b
leaq 0x3c840(%rip), %rdi     # 0x11da99
leaq 0x3c725(%rip), %rsi     # 0x11d985
leaq 0x3c7e5(%rip), %rcx     # 0x11da4c
pushq $0x5d
jmp 0xe129b
leaq 0x3c88d(%rip), %rdi     # 0x11daff
leaq 0x3c70c(%rip), %rsi     # 0x11d985
leaq 0x3c7cc(%rip), %rcx     # 0x11da4c
pushq $0x60
jmp 0xe129b
leaq 0x3c823(%rip), %rdi     # 0x11daae
leaq 0x3c6f3(%rip), %rsi     # 0x11d985
leaq 0x3c7b3(%rip), %rcx     # 0x11da4c
pushq $0x5f
popq %rdx
callq 0x56770