// File: /workspace/github_c_makefile_star2_O3/pje[P]pixelsort/lodepng.c
// Function: lodepng_huffman_code_lengths
unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies,
                                      size_t numcodes, unsigned maxbitlen)
{
  unsigned i, j;
  size_t sum = 0, numpresent = 0;
  unsigned error = 0;
  Coin* coins; /*the coins of the currently calculated row*/
  Coin* prev_row; /*the previous row of coins*/
  size_t numcoins;
  size_t coinmem;

  if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/

  for(i = 0; i < numcodes; i++)
  {
    if(frequencies[i] > 0)
    {
      numpresent++;
      sum += frequencies[i];
    }
  }

  for(i = 0; i < numcodes; i++) lengths[i] = 0;

  /*ensure at least two present symbols. There should be at least one symbol
  according to RFC 1951 section 3.2.7. To decoders incorrectly require two. To
  make these work as well ensure there are at least two symbols. The
  Package-Merge code below also doesn't work correctly if there's only one
  symbol, it'd give it the theoritical 0 bits but in practice zlib wants 1 bit*/
  if(numpresent == 0)
  {
    lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/
  }
  else if(numpresent == 1)
  {
    for(i = 0; i < numcodes; i++)
    {
      if(frequencies[i])
      {
        lengths[i] = 1;
        lengths[i == 0 ? 1 : 0] = 1;
        break;
      }
    }
  }
  else
  {
    /*Package-Merge algorithm represented by coin collector's problem
    For every symbol, maxbitlen coins will be created*/

    coinmem = numpresent * 2; /*max amount of coins needed with the current algo*/
    coins = (Coin*)lodepng_malloc(sizeof(Coin) * coinmem);
    prev_row = (Coin*)lodepng_malloc(sizeof(Coin) * coinmem);
    if(!coins || !prev_row)
    {
      lodepng_free(coins);
      lodepng_free(prev_row);
      return 83; /*alloc fail*/
    }
    init_coins(coins, coinmem);
    init_coins(prev_row, coinmem);

    /*first row, lowest denominator*/
    error = append_symbol_coins(coins, frequencies, numcodes, sum);
    numcoins = numpresent;
    qsort(coins, numcoins, sizeof(Coin), coin_compare);
    if(!error)
    {
      unsigned numprev = 0;
      for(j = 1; j <= maxbitlen && !error; j++) /*each of the remaining rows*/
      {
        unsigned tempnum;
        Coin* tempcoins;
        /*swap prev_row and coins, and their amounts*/
        tempcoins = prev_row; prev_row = coins; coins = tempcoins;
        tempnum = numprev; numprev = numcoins; numcoins = tempnum;

        cleanup_coins(coins, numcoins);
        init_coins(coins, numcoins);

        numcoins = 0;

        /*fill in the merged coins of the previous row*/
        for(i = 0; i + 1 < numprev; i += 2)
        {
          /*merge prev_row[i] and prev_row[i + 1] into new coin*/
          Coin* coin = &coins[numcoins++];
          coin_copy(coin, &prev_row[i]);
          add_coins(coin, &prev_row[i + 1]);
        }
        /*fill in all the original symbols again*/
        if(j < maxbitlen)
        {
          error = append_symbol_coins(coins + numcoins, frequencies, numcodes, sum);
          numcoins += numpresent;
        }
        qsort(coins, numcoins, sizeof(Coin), coin_compare);
      }
    }

    if(!error)
    {
      /*calculate the lenghts of each symbol, as the amount of times a coin of each symbol is used*/
      for(i = 0; i < numpresent - 1; i++)
      {
        Coin* coin = &coins[i];
        for(j = 0; j < coin->symbols.size; j++) lengths[coin->symbols.data[j]]++;
      }
    }

    cleanup_coins(coins, coinmem);
    lodepng_free(coins);
    cleanup_coins(prev_row, coinmem);
    lodepng_free(prev_row);
  }

  return error;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
testq %rdx, %rdx
je 0x141c
movl %ecx, %ebp
movq %rdi, %r14
xorl %eax, %eax
xorl %edi, %edi
xorl %r12d, %r12d
movl (%rsi,%rax,4), %ecx
addq %rcx, %rdi
cmpq $0x1, %rcx
sbbq $-0x1, %r12
incq %rax
movl %eax, %ecx
cmpq %rdx, %rcx
jb 0x13b4
movq %rdi, 0x38(%rsp)
movq %rsi, 0x20(%rsp)
movq %rdx, 0x28(%rsp)
leaq (,%rdx,4), %rdx
xorl %ebx, %ebx
movq %r14, %rdi
xorl %esi, %esi
callq 0x10e0
testq %r12, %r12
je 0x1426
cmpq $0x1, %r12
jne 0x1438
xorl %eax, %eax
movq 0x28(%rsp), %rcx
movq 0x20(%rsp), %rdx
cmpl $0x0, (%rdx,%rax,4)
jne 0x16d5
incq %rax
cmpl %ecx, %eax
jb 0x1406
jmp 0x17c9
movl $0x50, %ebx
jmp 0x17cb
movabsq $0x100000001, %rax      # imm = 0x100000001
movq %rax, (%r14)
jmp 0x17cb
movq %r12, %rbx
shlq $0x6, %rbx
movq %rbx, %rdi
callq 0x1140
movq %rax, %r15
movq %rbx, %rdi
callq 0x1140
testq %r15, %r15
setne %dl
testq %rax, %rax
setne %cl
testb %cl, %dl
je 0x16ee
movq %r15, 0x10(%rsp)
movq %r12, %rcx
addq %r12, %rcx
movq %rcx, 0x8(%rsp)
movq 0x28(%rsp), %rdx
movq 0x20(%rsp), %rsi
movq 0x38(%rsp), %rcx
je 0x14c9
xorps %xmm0, %xmm0
movq 0x10(%rsp), %r8
movq 0x8(%rsp), %rdi
movups %xmm0, (%r8)
movq $0x0, 0x10(%r8)
addq $0x20, %r8
decq %rdi
jne 0x1494
xorps %xmm0, %xmm0
movq %rax, %r8
movq 0x8(%rsp), %rdi
movups %xmm0, (%r8)
movq $0x0, 0x10(%r8)
addq $0x20, %r8
decq %rdi
jne 0x14b4
movq %rax, %r15
movq 0x10(%rsp), %r13
movq %r13, %rdi
callq 0x17dc
leaq 0x3a6(%rip), %rcx       # 0x1886
movl $0x20, %edx
movq %r13, %rdi
movq %r12, %rsi
callq 0x1070
testl %ebp, %ebp
movq %r14, 0x48(%rsp)
je 0x170b
movl $0x1, %r14d
xorl %ebx, %ebx
xorps %xmm0, %xmm0
movq %r12, 0x18(%rsp)
movq %r15, %rax
movq %r12, 0x40(%rsp)
movl %ebp, 0x30(%rsp)
movl %r14d, 0x34(%rsp)
movq %rax, %r13
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
andq %rax, %rbx
je 0x1571
shlq $0x5, %rbx
xorl %r14d, %r14d
movups %xmm0, 0x8(%r13,%r14)
movq (%r13,%r14), %rdi
callq 0x1030
xorps %xmm0, %xmm0
movq $0x0, (%r13,%r14)
addq $0x20, %r14
cmpq %r14, %rbx
jne 0x1532
xorl %eax, %eax
movups %xmm0, (%r13,%rax)
movq $0x0, 0x10(%r13,%rax)
addq $0x20, %rax
cmpq %rax, %rbx
jne 0x1559
cmpl $0x2, 0x18(%rsp)
jb 0x165b
xorl %r14d, %r14d
xorl %r15d, %r15d
movq %r13, 0x50(%rsp)
movq %r15, %rax
shlq $0x5, %rax
leaq (%rax,%r13), %rbx
movl %r14d, %r12d
shlq $0x5, %r12
movq 0x10(%rsp), %rbp
movss 0x18(%rbp,%r12), %xmm0
movss %xmm0, 0x18(%r13,%rax)
movq 0x8(%rbp,%r12), %rsi
movq %rbx, %rdi
callq 0xa370
testl %eax, %eax
je 0x15e1
addq %rbp, %r12
movq 0x8(%r12), %rax
testq %rax, %rax
je 0x15e1
movq (%r12), %rcx
movq (%rbx), %rdx
xorl %esi, %esi
movl (%rcx,%rsi,4), %edi
movl %edi, (%rdx,%rsi,4)
incq %rsi
cmpq %rsi, %rax
jne 0x15d3
movl %r14d, %eax
orl $0x1, %eax
movl %eax, %eax
shlq $0x5, %rax
leaq (%rax,%rbp), %r13
cmpq $0x0, 0x8(%rbp,%rax)
je 0x162b
xorl %r12d, %r12d
movq (%r13), %rax
movl (%rax,%r12,4), %ebp
movq 0x8(%rbx), %rsi
incq %rsi
movq %rbx, %rdi
callq 0xa370
testl %eax, %eax
je 0x1622
movq (%rbx), %rax
movq 0x8(%rbx), %rcx
movl %ebp, -0x4(%rax,%rcx,4)
incq %r12
cmpq 0x8(%r13), %r12
jb 0x15fc
incq %r15
movss 0x18(%r13), %xmm0
addss 0x18(%rbx), %xmm0
movss %xmm0, 0x18(%rbx)
leal 0x2(%r14), %eax
addl $0x3, %r14d
cmpl 0x18(%rsp), %r14d
movl %eax, %r14d
movq 0x50(%rsp), %r13
jb 0x1587
jmp 0x165e
xorl %r15d, %r15d
movl 0x30(%rsp), %ebp
movl 0x34(%rsp), %r14d
cmpl %ebp, %r14d
jae 0x1694
movq %r15, %rdi
shlq $0x5, %rdi
addq %r13, %rdi
movq 0x20(%rsp), %rsi
movq 0x28(%rsp), %rdx
movq 0x38(%rsp), %rcx
callq 0x17dc
movq 0x40(%rsp), %r12
addq %r12, %r15
jmp 0x1699
movq 0x40(%rsp), %r12
movl $0x20, %edx
movq %r13, %rdi
movq %r15, %rsi
leaq 0x1db(%rip), %rcx       # 0x1886
callq 0x1070
incl %r14d
movq 0x10(%rsp), %rax
movq 0x18(%rsp), %rbx
movq %r15, 0x18(%rsp)
movq %r13, 0x10(%rsp)
cmpl %ebp, %r14d
xorps %xmm0, %xmm0
jbe 0x1519
jmp 0x170e
movl $0x1, %ecx
movl %ecx, (%r14,%rax,4)
xorl %edx, %edx
testl %eax, %eax
sete %dl
movl %ecx, (%r14,%rdx,4)
jmp 0x17c9
movq %r15, %rdi
movq %rax, %rbx
callq 0x1030
movq %rbx, %rdi
callq 0x1030
movl $0x53, %ebx
jmp 0x17cb
movq %r15, %rax
movq %rax, %r15
movq %r13, %rbx
movq 0x8(%rsp), %r14
decq %r12
je 0x1769
xorl %eax, %eax
movq 0x48(%rsp), %r8
movq %rax, %rdx
shlq $0x5, %rdx
movq 0x8(%r13,%rdx), %rcx
testq %rcx, %rcx
je 0x174f
addq %r13, %rdx
movq (%rdx), %rdx
xorl %esi, %esi
movl (%rdx,%rsi,4), %edi
incl (%r8,%rdi,4)
incq %rsi
movl %esi, %edi
cmpq %rdi, %rcx
ja 0x173e
incq %rax
movl %eax, %ecx
cmpq %rcx, %r12
ja 0x1725
movq %r13, %rbx
movq 0x8(%rsp), %rax
movq %rax, %r14
testq %rax, %rax
je 0x17b9
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rbx)
movq (%rbx), %rdi
callq 0x1030
movq $0x0, (%rbx)
addq $0x20, %rbx
decq %r14
jne 0x1769
movq %r13, %rdi
callq 0x1030
movq %r15, %rbx
movq 0x8(%rsp), %r14
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rbx)
movq (%rbx), %rdi
callq 0x1030
movq $0x0, (%rbx)
addq $0x20, %rbx
decq %r14
jne 0x1798
jmp 0x17c1
movq %r13, %rdi
callq 0x1030
movq %r15, %rdi
callq 0x1030
xorl %ebx, %ebx
movl %ebx, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq