// File: /workspace/github_c_makefile_star2_O1/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 0x1411
movl %ecx, %ebp
xorl %eax, %eax
xorl %r8d, %r8d
xorl %r14d, %r14d
movl (%rsi,%rax,4), %ecx
addq %rcx, %r8
cmpq $0x1, %rcx
sbbq $-0x1, %r14
incq %rax
movl %eax, %ecx
cmpq %rdx, %rcx
jb 0x13a2
movq %r8, 0x40(%rsp)
movq %rsi, 0x28(%rsp)
movq %rdx, 0x30(%rsp)
leaq (,%rdx,4), %rdx
xorl %ebx, %ebx
movq %rdi, 0x20(%rsp)
xorl %esi, %esi
callq 0x10e0
testq %r14, %r14
je 0x141b
cmpq $0x1, %r14
jne 0x1432
xorl %eax, %eax
movq 0x20(%rsp), %rsi
movq 0x30(%rsp), %rcx
movq 0x28(%rsp), %rdx
cmpl $0x0, (%rdx,%rax,4)
jne 0x16ca
incq %rax
cmpl %ecx, %eax
jb 0x13fb
jmp 0x17b1
movl $0x50, %ebx
jmp 0x17b3
movabsq $0x100000001, %rax      # imm = 0x100000001
movq 0x20(%rsp), %rcx
movq %rax, (%rcx)
jmp 0x17b3
movq %r14, %rbx
shlq $0x6, %rbx
movq %rbx, %rdi
callq 0x1130
movq %rax, %r15
movq %rbx, %rdi
callq 0x1130
testq %r15, %r15
setne %dl
testq %rax, %rax
setne %cl
testb %cl, %dl
je 0x16e1
movq %r15, 0x8(%rsp)
movq %r14, %rcx
addq %r14, %rcx
movq %rcx, 0x10(%rsp)
movq 0x30(%rsp), %rdx
movq 0x28(%rsp), %rsi
movq 0x40(%rsp), %rcx
je 0x14c3
xorps %xmm0, %xmm0
movq 0x8(%rsp), %r8
movq 0x10(%rsp), %rdi
movups %xmm0, (%r8)
movq $0x0, 0x10(%r8)
addq $0x20, %r8
decq %rdi
jne 0x148e
xorps %xmm0, %xmm0
movq %rax, %r8
movq 0x10(%rsp), %rdi
movups %xmm0, (%r8)
movq $0x0, 0x10(%r8)
addq $0x20, %r8
decq %rdi
jne 0x14ae
movq %rax, %r15
movq 0x8(%rsp), %r13
movq %r13, %rdi
callq 0x17c4
leaq 0x394(%rip), %rcx       # 0x186e
movl $0x20, %edx
movq %r13, %rdi
movq %r14, %rsi
callq 0x1070
testl %ebp, %ebp
je 0x16fe
movl $0x1, %r12d
xorl %ebx, %ebx
xorps %xmm0, %xmm0
movq %r14, 0x18(%rsp)
movq %r15, %r9
movq %r14, 0x48(%rsp)
movl %ebp, 0x38(%rsp)
movq %r9, %r13
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
andq %rax, %rbx
je 0x1561
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 0x1522
xorl %eax, %eax
movups %xmm0, (%r13,%rax)
movq $0x0, 0x10(%r13,%rax)
addq $0x20, %rax
cmpq %rax, %rbx
jne 0x1549
movl %r12d, 0x3c(%rsp)
cmpl $0x2, 0x18(%rsp)
jb 0x1650
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 0x8(%rsp), %rbp
movss 0x18(%rbp,%r12), %xmm0
movss %xmm0, 0x18(%r13,%rax)
movq 0x8(%rbp,%r12), %rsi
movq %rbx, %rdi
callq 0x9e97
testl %eax, %eax
je 0x15d6
addq %rbp, %r12
movq 0x8(%r12), %rax
testq %rax, %rax
je 0x15d6
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 0x15c8
movl %r14d, %eax
orl $0x1, %eax
movl %eax, %eax
shlq $0x5, %rax
leaq (%rax,%rbp), %r13
cmpq $0x0, 0x8(%rbp,%rax)
je 0x1620
xorl %r12d, %r12d
movq (%r13), %rax
movl (%rax,%r12,4), %ebp
movq 0x8(%rbx), %rsi
incq %rsi
movq %rbx, %rdi
callq 0x9e97
testl %eax, %eax
je 0x1617
movq (%rbx), %rax
movq 0x8(%rbx), %rcx
movl %ebp, -0x4(%rax,%rcx,4)
incq %r12
cmpq 0x8(%r13), %r12
jb 0x15f1
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 0x157c
jmp 0x1653
xorl %r15d, %r15d
movl 0x38(%rsp), %ebp
movl 0x3c(%rsp), %r12d
cmpl %ebp, %r12d
jae 0x1689
movq %r15, %rdi
shlq $0x5, %rdi
addq %r13, %rdi
movq 0x28(%rsp), %rsi
movq 0x30(%rsp), %rdx
movq 0x40(%rsp), %rcx
callq 0x17c4
movq 0x48(%rsp), %r14
addq %r14, %r15
jmp 0x168e
movq 0x48(%rsp), %r14
movl $0x20, %edx
movq %r13, %rdi
movq %r15, %rsi
leaq 0x1ce(%rip), %rcx       # 0x186e
callq 0x1070
incl %r12d
movq 0x8(%rsp), %r9
movq 0x18(%rsp), %rbx
movq %r15, 0x18(%rsp)
movq %r13, 0x8(%rsp)
cmpl %ebp, %r12d
xorps %xmm0, %xmm0
jbe 0x150e
jmp 0x1701
movl $0x1, %ecx
movl %ecx, (%rsi,%rax,4)
xorl %edx, %edx
testl %eax, %eax
sete %dl
movl %ecx, (%rsi,%rdx,4)
jmp 0x17b1
movq %r15, %rdi
movq %rax, %rbx
callq 0x1030
movq %rbx, %rdi
callq 0x1030
movl $0x53, %ebx
jmp 0x17b3
movq %r15, %r9
decq %r14
movq 0x20(%rsp), %r8
je 0x1741
xorl %eax, %eax
movq %rax, %rdx
shlq $0x5, %rdx
movq 0x8(%r13,%rdx), %rcx
testq %rcx, %rcx
je 0x1737
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 0x1726
incq %rax
movl %eax, %ecx
cmpq %rcx, %r14
ja 0x170d
movq 0x10(%rsp), %r14
movq %r9, %r15
testq %r14, %r14
je 0x17a1
movq %r13, %rbx
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rbx)
movq (%rbx), %rdi
callq 0x1030
movq $0x0, (%rbx)
addq $0x20, %rbx
decq %r14
jne 0x1751
movq %r13, %rdi
callq 0x1030
movq %r15, %rbx
movq 0x10(%rsp), %r14
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rbx)
movq (%rbx), %rdi
callq 0x1030
movq $0x0, (%rbx)
addq $0x20, %rbx
decq %r14
jne 0x1780
jmp 0x17a9
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