// File: /workspace/github_c_makefile_star2_O1/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 $0xd8, %rsp
movq %r8, %r15
movl %ecx, %r9d
movl %esi, %r8d
movl $0x1, %eax
movl %r8d, %ecx
shll %cl, %eax
movq %rax, 0x8(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x70(%rsp)
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x50(%rsp)
testl %r9d, %r9d
je 0xf158b
testq %rdx, %rdx
je 0xf15aa
testq %rdi, %rdi
setne %al
testq %r15, %r15
setne %cl
testb %cl, %al
jne 0xf114d
movq %rdi, %rax
orq %r15, %rax
jne 0xf15e8
testl %r8d, %r8d
jle 0xf15c9
movl %r9d, %ebx
testl %r9d, %r9d
jle 0xf1178
xorl %eax, %eax
xorl %ecx, %ecx
movslq (%rdx,%rcx,4), %rsi
cmpq $0xf, %rsi
jg 0xf1181
incl 0x50(%rsp,%rsi,4)
incq %rcx
cmpq %rcx, %rbx
jne 0xf1162
cmpl %r9d, 0x50(%rsp)
jne 0xf1193
xorl %eax, %eax
addq $0xd8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x0, 0x94(%rsp)
xorl %eax, %eax
xorl %esi, %esi
movl 0x54(%rsp,%rsi,4), %r11d
leal 0x1(%rsi), %ecx
movl $0x1, %r10d
shll %cl, %r10d
cmpl %r10d, %r11d
jg 0xf1181
addl 0x94(%rsp,%rsi,4), %r11d
movl %r11d, 0x98(%rsp,%rsi,4)
incq %rsi
cmpq $0xe, %rsi
jne 0xf11a2
testl %r9d, %r9d
movq 0x8(%rsp), %r9
jle 0xf1223
xorl %ecx, %ecx
movslq (%rdx,%rcx,4), %rsi
testq %rsi, %rsi
jle 0xf121b
movslq 0x90(%rsp,%rsi,4), %r9
testq %r15, %r15
je 0xf120b
cmpl %ebx, %r9d
jge 0xf117f
leal 0x1(%r9), %r10d
movl %r10d, 0x90(%rsp,%rsi,4)
movw %cx, (%r15,%r9,2)
jmp 0xf1216
incl %r9d
movl %r9d, 0x90(%rsp,%rsi,4)
movq 0x8(%rsp), %r9
incq %rcx
cmpq %rcx, %rbx
jne 0xf11dd
cmpl $0x1, 0xcc(%rsp)
jne 0xf1254
testq %r15, %r15
je 0xf124c
movzwl (%r15), %eax
shll $0x10, %eax
movslq %r9d, %rcx
incq %rcx
movl %eax, -0x8(%rdi,%rcx,4)
decq %rcx
cmpq $0x1, %rcx
jg 0xf123f
movl %r9d, %eax
jmp 0xf1181
leal -0x1(%r9), %eax
movl %eax, 0x44(%rsp)
cmpl $0x2, %r8d
movl $0x1, %eax
cmovgel %r8d, %eax
movl $0x1, %ecx
incl %eax
movl $0x2, %edx
movl $0x1, %esi
xorl %r14d, %r14d
movl $0x1, %r10d
xorl %ebp, %ebp
movl %r8d, 0x4(%rsp)
movq %rax, 0x30(%rsp)
leal (%rcx,%rcx), %ebx
subl 0x50(%rsp,%rsi,4), %ebx
js 0xf117f
testq %rdi, %rdi
je 0xf136a
movl 0x50(%rsp,%rsi,4), %r11d
testl %r11d, %r11d
jle 0xf1365
movq %rcx, 0x18(%rsp)
movq %rbx, 0x20(%rsp)
movq %r10, 0x28(%rsp)
movzbl %sil, %ebx
leal -0x1(%rdx), %r12d
leal -0x1(%rsi), %ecx
movl $0x1, %r13d
shll %cl, %r13d
movslq %r14d, %r14
movl %edx, %ecx
negl %ecx
movl %r11d, 0x14(%rsp)
movl %r11d, %eax
testl %r9d, %r12d
jne 0xf1564
movq %r15, %r8
movzwl (%r15,%r14,2), %r11d
incq %r14
shll $0x10, %r11d
orl %ebx, %r11d
movl %ebp, %r10d
leaq (%rdi,%r10,4), %r15
movl %r9d, %r10d
leal (%rcx,%r10), %r9d
subl %edx, %r10d
movslq %r9d, %r9
movl %r11d, (%r15,%r9,4)
testl %r10d, %r10d
jg 0xf130a
movl %r13d, %r11d
movl %r11d, %r10d
shrl %r11d
testl %ebp, %r10d
jne 0xf1320
leal -0x1(%r10), %r9d
andl %r9d, %ebp
addl %r10d, %ebp
leal -0x1(%rax), %r9d
cmpl $0x1, %eax
movl %r9d, %eax
movq %r8, %r15
movq 0x8(%rsp), %r9
jg 0xf12e5
xorl %r11d, %r11d
movl 0x4(%rsp), %r8d
movq 0x28(%rsp), %r10
movq 0x20(%rsp), %rbx
movq 0x30(%rsp), %rax
movq 0x18(%rsp), %rcx
movl %r11d, 0x50(%rsp,%rsi,4)
leal (%r10,%rcx,2), %r10d
incq %rsi
addl %edx, %edx
movl %ebx, %ecx
cmpq %rax, %rsi
jne 0xf128f
cmpl $0xe, %r8d
jg 0xf1547
movl %r8d, %r13d
leaq (%rsp,%r13,4), %rax
addq $0x54, %rax
movq %rax, 0x48(%rsp)
movl $0xffffffff, %r9d       # imm = 0xFFFFFFFF
movl $0x2, %eax
movq %rdi, %r12
movq 0x8(%rsp), %rcx
movl %ecx, %r11d
leal (%rbx,%rbx), %ecx
subl 0x54(%rsp,%r13,4), %ecx
js 0xf117f
movl %ecx, 0x3c(%rsp)
movq %rbx, 0x20(%rsp)
movq %r10, 0x28(%rsp)
leaq 0x1(%r13), %rdx
cmpl $0x0, 0x50(%rsp,%rdx,4)
movq %r13, 0x18(%rsp)
jle 0xf1519
movl %edx, %esi
subl 0x4(%rsp), %esi
movl $0x1, %r10d
movl %esi, %ecx
shll %cl, %r10d
movl %r10d, 0x40(%rsp)
movl $0x1, %r8d
movl %r13d, %ecx
shll %cl, %r8d
movzbl %sil, %ecx
movl %ecx, 0x14(%rsp)
leal -0x1(%rax), %ecx
movl %ecx, 0x30(%rsp)
movl %eax, %r13d
negl %r13d
movl %ebp, %esi
andl 0x44(%rsp), %esi
cmpl %r9d, %esi
je 0xf14aa
testq %rdi, %rdi
movslq %r11d, %rbx
cmoveq %rdi, %rbx
movl %edx, %r9d
cmpq $0xe, 0x18(%rsp)
je 0xf1468
movq 0x48(%rsp), %rcx
movq 0x18(%rsp), %r9
movl 0x40(%rsp), %r11d
subl (%rcx), %r11d
jle 0xf1465
addl %r11d, %r11d
incl %r9d
addq $0x4, %rcx
cmpl $0xe, %r9d
jl 0xf1448
movl $0xf, %r9d
jmp 0xf1468
incl %r9d
movl %r9d, %ecx
subl 0x4(%rsp), %ecx
movl $0x1, %r11d
shll %cl, %r11d
leaq (%r12,%rbx,4), %r12
movq 0x8(%rsp), %rcx
addl %r11d, %ecx
movq %rcx, 0x8(%rsp)
testq %rdi, %rdi
je 0xf14a7
movl %esi, %ecx
movb %r9b, (%rdi,%rcx,4)
movl %r12d, %r9d
subl %edi, %r9d
shrl $0x2, %r9d
subl %esi, %r9d
movw %r9w, 0x2(%rdi,%rcx,4)
movl %esi, %r9d
testq %rdi, %rdi
je 0xf14ed
movl %ebp, %esi
movl 0x4(%rsp), %ecx
shrl %cl, %esi
testl %r11d, 0x30(%rsp)
jne 0xf156c
movslq %r14d, %r10
incl %r14d
leaq (%r12,%rsi,4), %rcx
movzwl (%r15,%r10,2), %esi
shll $0x10, %esi
addl 0x14(%rsp), %esi
movl %r11d, %r10d
leal (%r10,%r13), %ebx
subl %eax, %r10d
movslq %ebx, %rbx
movl %esi, (%rcx,%rbx,4)
testl %r10d, %r10d
jg 0xf14db
movl %r8d, %ecx
movl %ecx, %esi
shrl %ecx
testl %ebp, %esi
jne 0xf14f0
leal -0x1(%rsi), %ecx
andl %ebp, %ecx
addl %esi, %ecx
movl 0x50(%rsp,%rdx,4), %esi
leal -0x1(%rsi), %r10d
movl %r10d, 0x50(%rsp,%rdx,4)
movl %ecx, %ebp
cmpl $0x1, %esi
jg 0xf1415
jmp 0xf151b
movl %ebp, %ecx
movq 0x28(%rsp), %r10
movq 0x20(%rsp), %rsi
leal (%r10,%rsi,2), %r10d
addl %eax, %eax
addq $0x4, 0x48(%rsp)
movl 0x3c(%rsp), %esi
movl %esi, %ebx
movl %ecx, %ebp
cmpl $0xe, 0x18(%rsp)
movq %rdx, %r13
jl 0xf13ae
movl 0xcc(%rsp), %eax
leal -0x1(,%rax,2), %ecx
xorl %eax, %eax
cmpl %ecx, %r10d
cmovel 0x8(%rsp), %eax
jmp 0xf1181
movl 0x14(%rsp), %eax
movl %eax, 0x50(%rsp,%rsi,4)
leaq 0x3d638(%rip), %rdi     # 0x12ebab
leaq 0x3d4a9(%rip), %rsi     # 0x12ea23
leaq 0x3d63a(%rip), %rcx     # 0x12ebbb
movl $0x38, %edx
callq 0x55710
leaq 0x3d541(%rip), %rdi     # 0x12ead3
leaq 0x3d48a(%rip), %rsi     # 0x12ea23
leaq 0x3d54a(%rip), %rcx     # 0x12eaea
movl $0x5c, %edx
callq 0x55710
leaq 0x3d586(%rip), %rdi     # 0x12eb37
leaq 0x3d46b(%rip), %rsi     # 0x12ea23
leaq 0x3d52b(%rip), %rcx     # 0x12eaea
movl $0x5d, %edx
callq 0x55710
leaq 0x3d5cd(%rip), %rdi     # 0x12eb9d
leaq 0x3d44c(%rip), %rsi     # 0x12ea23
leaq 0x3d50c(%rip), %rcx     # 0x12eaea
movl $0x60, %edx
callq 0x55710
leaq 0x3d55d(%rip), %rdi     # 0x12eb4c
leaq 0x3d42d(%rip), %rsi     # 0x12ea23
leaq 0x3d4ed(%rip), %rcx     # 0x12eaea
movl $0x5f, %edx
callq 0x55710