// File: /workspace/github_c_makefile_star2_O2/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:
testq %rdx, %rdx
je 0x13eb
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rdx, %r15
movq %rsi, %r12
movl %ecx, 0x8(%rsp)
xorl %ebx, %ebx
xorl %ebp, %ebp
xorl %eax, %eax
movl %eax, %eax
cmpq %r15, %rax
jae 0x13b3
movl (%r12,%rax,4), %ecx
addq %rcx, %rbp
cmpq $0x1, %rcx
sbbq $-0x1, %rbx
incl %eax
jmp 0x1399
xorl %eax, %eax
cmpl %r15d, %eax
jae 0x13c3
andl $0x0, (%rdi,%rax,4)
incq %rax
jmp 0x13b5
testq %rbx, %rbx
je 0x13ef
cmpq $0x1, %rbx
jne 0x1401
xorl %eax, %eax
xorl %ecx, %ecx
cmpl %r15d, %ecx
jae 0x167d
cmpl $0x0, (%r12,%rcx,4)
jne 0x166c
incq %rcx
jmp 0x13d2
pushq $0x50
popq %rax
retq
movabsq $0x100000001, %rax      # imm = 0x100000001
movq %rax, (%rdi)
jmp 0x1668
movq %rdi, 0x28(%rsp)
movq %rbx, %r14
shlq $0x6, %r14
movq %r14, %rdi
callq 0x1130
movq %rax, %r13
movq %r14, %rdi
callq 0x1130
movq %rax, %r14
testq %r13, %r13
setne %al
testq %r14, %r14
setne %cl
testb %cl, %al
je 0x15e4
movq %r14, (%rsp)
leaq (%rbx,%rbx), %r14
movq %r13, %rdi
movq %r14, %rsi
callq 0x168c
movq (%rsp), %rdi
movq %r14, 0x20(%rsp)
movq %r14, %rsi
callq 0x168c
movq %r13, %rdi
movq %r12, 0x38(%rsp)
movq %r12, %rsi
movq %r15, 0x40(%rsp)
movl %r15d, %edx
movq %rbp, 0x30(%rsp)
movq %rbp, %rcx
callq 0x16a4
leaq 0x2aa(%rip), %rcx       # 0x172c
pushq $0x20
popq %rdx
movq %r13, %rdi
movq %rbx, %rsi
callq 0x1070
pushq $0x1
popq %rcx
xorl %eax, %eax
movq %rbx, 0x10(%rsp)
movq %rbx, %r14
movl 0x8(%rsp), %ebx
movq (%rsp), %r15
movq %r14, 0x18(%rsp)
movq %r13, %rbp
cmpl %ebx, %ecx
ja 0x15fc
movl %ecx, 0xc(%rsp)
movl %eax, %r14d
movq %r15, %rdi
movq %r14, %rsi
callq 0x174a
movq %r15, (%rsp)
movq %r15, %rdi
movq %r14, %rsi
callq 0x168c
xorl %r14d, %r14d
xorl %r15d, %r15d
movl %r15d, %ebx
orl $0x1, %ebx
cmpl 0x18(%rsp), %ebx
jae 0x1585
movq %r14, %rax
shlq $0x5, %rax
movq (%rsp), %rcx
leaq (%rcx,%rax), %r13
movl %r15d, %r12d
shlq $0x5, %r12
movss 0x18(%rbp,%r12), %xmm0
movss %xmm0, 0x18(%rcx,%rax)
movq 0x8(%rbp,%r12), %rsi
movq %r13, %rdi
callq 0x7b59
testl %eax, %eax
je 0x1542
addq %rbp, %r12
movq 0x8(%r12), %rax
xorl %ecx, %ecx
cmpq %rcx, %rax
je 0x1542
movq (%r12), %rdx
movl (%rdx,%rcx,4), %edx
movq (%r13), %rsi
movl %edx, (%rsi,%rcx,4)
incq %rcx
jmp 0x152a
incq %r14
movl %ebx, %ebx
shlq $0x5, %rbx
addq %rbp, %rbx
xorl %r12d, %r12d
cmpq 0x8(%rbx), %r12
jae 0x156b
movq (%rbx), %rax
movl (%rax,%r12,4), %esi
movq %r13, %rdi
callq 0x7b26
incq %r12
jmp 0x1551
movss 0x18(%rbx), %xmm0
addss 0x18(%r13), %xmm0
movss %xmm0, 0x18(%r13)
addl $0x2, %r15d
jmp 0x14dc
movl 0x8(%rsp), %ebx
cmpl %ebx, 0xc(%rsp)
jae 0x15b8
movq %r14, %rdi
shlq $0x5, %rdi
movq (%rsp), %r13
addq %r13, %rdi
movq 0x38(%rsp), %rsi
movq 0x40(%rsp), %rdx
movq 0x30(%rsp), %rcx
callq 0x16a4
addq 0x10(%rsp), %r14
jmp 0x15bc
movq (%rsp), %r13
movq %r13, %rdi
movq %r14, %rsi
pushq $0x20
popq %rdx
leaq 0x160(%rip), %rcx       # 0x172c
callq 0x1070
movl 0xc(%rsp), %ecx
incl %ecx
movq %rbp, %r15
movq 0x18(%rsp), %rax
jmp 0x14a5
movq %r13, %rdi
callq 0x1030
movq %r14, %rdi
callq 0x1030
pushq $0x53
popq %rax
jmp 0x167d
movq 0x10(%rsp), %r9
decq %r9
xorl %eax, %eax
movq 0x28(%rsp), %r8
movl %eax, %eax
cmpq %rax, %r9
jbe 0x163d
movq %rax, %rdx
shlq $0x5, %rdx
leaq (%rdx,%rbp), %rcx
movq 0x8(%rbp,%rdx), %rdx
xorl %esi, %esi
movl %esi, %esi
cmpq %rsi, %rdx
jbe 0x1639
movq (%rcx), %rdi
movl (%rdi,%rsi,4), %edi
incl (%r8,%rdi,4)
incl %esi
jmp 0x1624
incl %eax
jmp 0x160b
movq %rbp, %rdi
movq 0x20(%rsp), %rbx
movq %rbx, %rsi
callq 0x174a
movq %rbp, %rdi
callq 0x1030
movq %r15, %rdi
movq %rbx, %rsi
callq 0x174a
movq %r15, %rdi
callq 0x1030
xorl %eax, %eax
jmp 0x167d
pushq $0x1
popq %rdx
movl %edx, (%rdi,%rcx,4)
xorl %esi, %esi
testl %ecx, %ecx
sete %sil
movl %edx, (%rdi,%rsi,4)
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq