// File: /workspace/github_cpp_makefile_star2_O1/drummyfish[P]flowchart/src/lodepng.cpp
// Function: lodepng_huffman_code_lengths(unsigned int*, unsigned int const*, unsigned long, unsigned int)
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*/
  unsigned numcoins;
  unsigned 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;

  /*there are no symbols at all, in that case add one symbol of value 0 to the tree (see RFC 1951 section 3.2.7) */
  if(numpresent == 0)
  {
    lengths[0] = 1;
  }
  /*the package merge algorithm gives wrong results if there's only one symbol
  (theoretically 0 bits would then suffice, but we need a proper symbol for zlib)*/
  else if(numpresent == 1)
  {
    for(i = 0; i < numcodes; i++) if(frequencies[i]) lengths[i] = 1;
  }
  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*)mymalloc(sizeof(Coin) * coinmem);
    prev_row = (Coin*)mymalloc(sizeof(Coin) * coinmem);
    if(!coins || !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;
    sort_coins(coins, numcoins);
    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;
        }
        sort_coins(coins, numcoins);
      }
    }

    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);
    myfree(coins);
    cleanup_coins(prev_row, coinmem);
    myfree(prev_row);
  }

  return error;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
testq %rdx, %rdx
je 0x2736
movl %ecx, %ebp
movq %rdx, %r14
movq %rsi, %r15
xorl %eax, %eax
xorl %edx, %edx
xorl %r8d, %r8d
movq %r8, %r12
movl (%r15,%rax,4), %ebx
addq %rbx, %rdx
cmpq $0x1, %rbx
sbbq $-0x1, %r8
incq %rax
movl %eax, %ecx
cmpq %r14, %rcx
jb 0x26c7
movq %rdx, 0x40(%rsp)
leaq (,%r14,4), %rdx
xorl %r13d, %r13d
movq %rdi, 0x18(%rsp)
xorl %esi, %esi
movq %r8, 0x10(%rsp)
callq 0x2100
movq 0x10(%rsp), %rax
testq %rax, %rax
je 0x2741
cmpq $0x1, %rax
jne 0x2751
xorl %eax, %eax
movq 0x18(%rsp), %rcx
cmpl $0x0, (%r15,%rax,4)
je 0x2729
movl $0x1, (%rcx,%rax,4)
incq %rax
cmpl %r14d, %eax
jb 0x271b
jmp 0x2ad3
movl $0x50, %r13d
jmp 0x2ad6
movq 0x18(%rsp), %rax
movl $0x1, (%rax)
jmp 0x2ad6
movq %r15, 0x30(%rsp)
movq %r14, 0x38(%rsp)
leal (%rax,%rax), %r14d
movq %r14, %r15
shlq $0x5, %r15
movq %r15, %rdi
callq 0x2270
movq %rax, %r13
movq %r15, %rdi
callq 0x2270
movq %rax, %r15
movq %r13, %rdx
testq %r13, %r13
sete %al
testq %r15, %r15
sete %cl
movl $0x53, %r13d
orb %al, %cl
jne 0x2ad6
testq %r14, %r14
movq %rdx, %r13
je 0x27fe
cmpl $0x1, %ebx
movl %r12d, %eax
sbbl $-0x1, %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
shlq $0x6, %rax
xorl %ecx, %ecx
xorps %xmm0, %xmm0
movups %xmm0, (%r13,%rcx)
movq $0x0, 0x10(%r13,%rcx)
addq $0x20, %rcx
cmpq %rcx, %rax
jne 0x27b8
cmpl $0x1, %ebx
movl %r12d, %eax
sbbl $-0x1, %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
shlq $0x6, %rax
xorl %ecx, %ecx
xorps %xmm0, %xmm0
movups %xmm0, (%r15,%rcx)
movq $0x0, 0x10(%r15,%rcx)
addq $0x20, %rcx
cmpq %rcx, %rax
jne 0x27e7
movq %r14, 0x50(%rsp)
movq %rbx, 0x28(%rsp)
movq %r13, %rdi
movq 0x30(%rsp), %rsi
movq 0x38(%rsp), %rdx
movq 0x40(%rsp), %rcx
callq 0x2ae8
movq 0x10(%rsp), %rbx
movl %ebx, %esi
movq %r13, %rdi
callq 0x2b92
testl %ebp, %ebp
je 0x29e9
xorl %eax, %eax
movl $0x1, %r14d
xorps %xmm0, %xmm0
movl %ebx, 0xc(%rsp)
movq %r12, 0x48(%rsp)
movl %ebp, 0x20(%rsp)
movl %r14d, 0x24(%rsp)
testl %eax, %eax
je 0x289c
movl %eax, %ebx
shlq $0x5, %rbx
xorl %r14d, %r14d
movups %xmm0, 0x8(%r15,%r14)
movq (%r15,%r14), %rdi
callq 0x2220
xorps %xmm0, %xmm0
movq $0x0, (%r15,%r14)
addq $0x20, %r14
cmpq %r14, %rbx
jne 0x2860
xorl %eax, %eax
movups %xmm0, (%r15,%rax)
movq $0x0, 0x10(%r15,%rax)
addq $0x20, %rax
cmpq %rax, %rbx
jne 0x2885
xorl %ebx, %ebx
cmpl $0x2, 0xc(%rsp)
jb 0x2989
xorl %r12d, %r12d
xorl %ebx, %ebx
movq %r13, 0x60(%rsp)
movq %r15, 0x58(%rsp)
movl %ebx, %eax
shlq $0x5, %rax
movq %r15, %rcx
addq %rax, %r15
movl %r12d, %r14d
shlq $0x5, %r14
movss 0x18(%r13,%r14), %xmm0
movss %xmm0, 0x18(%rcx,%rax)
movq 0x8(%r13,%r14), %rsi
movq %r15, %rdi
callq 0xbdaf
testl %eax, %eax
je 0x290b
addq %r13, %r14
movq 0x8(%r14), %rax
testq %rax, %rax
je 0x290b
movq (%r14), %rcx
movq (%r15), %rdx
xorl %esi, %esi
movl (%rcx,%rsi,4), %edi
movl %edi, (%rdx,%rsi,4)
incq %rsi
cmpq %rsi, %rax
jne 0x28fd
movl %r12d, %eax
orl $0x1, %eax
movl %eax, %eax
shlq $0x5, %rax
leaq (%rax,%r13), %r14
cmpq $0x0, 0x8(%r13,%rax)
je 0x2954
xorl %ebp, %ebp
movq (%r14), %rax
movl (%rax,%rbp,4), %r13d
movq 0x8(%r15), %rsi
incq %rsi
movq %r15, %rdi
callq 0xbdaf
testl %eax, %eax
je 0x294b
movq (%r15), %rax
movq 0x8(%r15), %rcx
movl %r13d, -0x4(%rax,%rcx,4)
incq %rbp
cmpq 0x8(%r14), %rbp
jb 0x2925
incl %ebx
movss 0x18(%r14), %xmm0
addss 0x18(%r15), %xmm0
movss %xmm0, 0x18(%r15)
leal 0x2(%r12), %eax
addl $0x3, %r12d
cmpl 0xc(%rsp), %r12d
movl %eax, %r12d
movq 0x60(%rsp), %r13
movq 0x58(%rsp), %r15
jb 0x28b8
movl 0x20(%rsp), %ebp
movl 0x24(%rsp), %r14d
cmpl %ebp, %r14d
jae 0x29b8
movl %ebx, %edi
shlq $0x5, %rdi
addq %r15, %rdi
movq 0x30(%rsp), %rsi
movq 0x38(%rsp), %rdx
movq 0x40(%rsp), %rcx
callq 0x2ae8
addl 0x10(%rsp), %ebx
movq 0x48(%rsp), %r12
movl %ebx, %esi
movq %r15, %rdi
callq 0x2b92
incl %r14d
movq %r15, %rdi
movq %r13, %r15
movl 0xc(%rsp), %eax
movl %ebx, 0xc(%rsp)
movq %rdi, %r13
cmpl %ebp, %r14d
xorps %xmm0, %xmm0
jbe 0x284e
jmp 0x29ec
movq %r13, %rdi
movq 0x10(%rsp), %r10
decq %r10
movq 0x28(%rsp), %r8
movq 0x18(%rsp), %r9
je 0x2a38
xorl %eax, %eax
movq %rax, %rdx
shlq $0x5, %rdx
movq 0x8(%rdi,%rdx), %rcx
testq %rcx, %rcx
je 0x2a2e
addq %rdi, %rdx
movq (%rdx), %rdx
xorl %esi, %esi
movl (%rdx,%rsi,4), %r11d
incl (%r9,%r11,4)
incq %rsi
movl %esi, %r11d
cmpq %r11, %rcx
ja 0x2a1b
incq %rax
movl %eax, %ecx
cmpq %rcx, %r10
ja 0x2a02
cmpq $0x0, 0x50(%rsp)
je 0x2ac6
cmpl $0x1, %r8d
movl %r12d, %ebx
sbbl $-0x1, %ebx
andl $0x7fffffff, %ebx       # imm = 0x7FFFFFFF
shlq $0x6, %rbx
xorl %r14d, %r14d
movq %rdi, %r13
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%r13,%r14)
movq (%r13,%r14), %rdi
callq 0x2220
movq $0x0, (%r13,%r14)
addq $0x20, %r14
cmpq %r14, %rbx
jne 0x2a5e
movq %r13, %rdi
callq 0x2220
cmpl $0x1, 0x28(%rsp)
sbbl $-0x1, %r12d
andl $0x7fffffff, %r12d      # imm = 0x7FFFFFFF
shlq $0x6, %r12
xorl %ebx, %ebx
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%r15,%rbx)
movq (%r15,%rbx), %rdi
callq 0x2220
movq $0x0, (%r15,%rbx)
addq $0x20, %rbx
cmpq %rbx, %r12
jne 0x2aa1
jmp 0x2acb
callq 0x2220
movq %r15, %rdi
callq 0x2220
xorl %r13d, %r13d
movl %r13d, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq