// File: /workspace/github_cpp_makefile_star2_O1/phillip-h[P]fractal-gen/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 error = 0;
  unsigned i;
  size_t numpresent = 0; /*number of symbols with non-zero frequency*/
  BPMNode* leaves; /*the symbols, only those with > 0 frequency*/

  if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/
  if((1u << maxbitlen) < numcodes) return 80; /*error: represent all symbols*/

  leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves));
  if(!leaves) return 83; /*alloc fail*/

  for(i = 0; i != numcodes; ++i)
  {
    if(frequencies[i] > 0)
    {
      leaves[numpresent].weight = (int)frequencies[i];
      leaves[numpresent].index = i;
      ++numpresent;
    }
  }

  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. Some 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)
  {
    lengths[leaves[0].index] = 1;
    lengths[leaves[0].index == 0 ? 1 : 0] = 1;
  }
  else
  {
    BPMLists lists;
    BPMNode* node;

    bpmnode_sort(leaves, numpresent);

    lists.listsize = maxbitlen;
    lists.memsize = 2 * maxbitlen * (maxbitlen + 1);
    lists.nextfree = 0;
    lists.numfree = lists.memsize;
    lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory));
    lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*));
    lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*));
    lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*));
    if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/

    if(!error)
    {
      for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i];

      bpmnode_create(&lists, leaves[0].weight, 1, 0);
      bpmnode_create(&lists, leaves[1].weight, 2, 0);

      for(i = 0; i != lists.listsize; ++i)
      {
        lists.chains0[i] = &lists.memory[0];
        lists.chains1[i] = &lists.memory[1];
      }

      /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/
      for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i);

      for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail)
      {
        for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index];
      }
    }

    lodepng_free(lists.memory);
    lodepng_free(lists.freelist);
    lodepng_free(lists.chains0);
    lodepng_free(lists.chains1);
  }

  lodepng_free(leaves);
  return error;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movl %ecx, %r12d
movl $0x1, %eax
shlxl %ecx, %eax, %eax
movl %eax, %eax
leaq -0x1(%rdx), %rcx
movl $0x50, %ebp
cmpq %rax, %rcx
jae 0x4604
movq %rdx, %r13
movq %rsi, %r15
movq %rdi, %rbx
leaq (,%rdx,8), %rax
leaq (%rax,%rax,2), %rdi
callq 0x21e0
testq %rax, %rax
je 0x42b3
movq %rax, %r14
movq %r12, (%rsp)
testq %r13, %r13
je 0x42bd
xorl %eax, %eax
xorl %r12d, %r12d
movl (%r15,%rax,4), %ecx
testl %ecx, %ecx
je 0x42a7
leaq (%r12,%r12,2), %rdx
movl %ecx, (%r14,%rdx,8)
movl %eax, 0x4(%r14,%rdx,8)
incq %r12
incq %rax
movl %eax, %ecx
cmpq %r13, %rcx
jne 0x428f
jmp 0x42c0
movl $0x53, %ebp
jmp 0x4604
xorl %r12d, %r12d
testq %r13, %r13
je 0x42d8
xorl %eax, %eax
movl $0x0, (%rbx,%rax,4)
incq %rax
movl %eax, %ecx
cmpq %r13, %rcx
jne 0x42c7
cmpq $0x1, %r12
je 0x42f2
testq %r12, %r12
jne 0x4310
movabsq $0x100000001, %rax      # imm = 0x100000001
movq %rax, (%rbx)
jmp 0x4309
movl 0x4(%r14), %eax
xorl %ecx, %ecx
testq %rax, %rax
sete %cl
movl $0x1, %edx
movl %edx, (%rbx,%rax,4)
movl %edx, (%rbx,%rcx,4)
xorl %ebp, %ebp
jmp 0x45fc
movq %rbx, 0x50(%rsp)
leaq (,%r12,8), %rax
leaq (%rax,%rax,2), %rbx
movq %rbx, %rdi
callq 0x21e0
movq %rax, %r15
cmpq $0x2, %r12
jb 0x4428
movq %rbx, 0x48(%rsp)
movl $0x1, %eax
xorl %ecx, %ecx
movq %r14, 0x60(%rsp)
movq %r15, 0x58(%rsp)
movq %rcx, 0x8(%rsp)
testb $0x1, %cl
movq %r15, %rsi
cmoveq %r14, %rsi
movq %r14, %rbx
cmoveq %r15, %rbx
leaq (%rax,%rax), %rdx
movq %rax, %rcx
shlq $0x4, %rcx
leaq (%rcx,%rcx,2), %r8
xorl %r9d, %r9d
movq %r9, %r10
leaq (%r9,%rax), %r14
cmpq %r12, %r14
cmovaeq %r12, %r14
addq %rdx, %r9
cmpq %r12, %r9
movq %r12, %r15
cmovbq %r9, %r15
cmpq %r15, %r10
jae 0x43eb
movq %rbx, %rdi
movq %r14, %r13
movq %r10, %rcx
cmpq %r14, %rcx
jae 0x43ba
cmpq %r15, %r13
jae 0x43c2
leaq (%rcx,%rcx,2), %r11
movl (%rsi,%r11,8), %r11d
leaq (%r13,%r13,2), %rbp
cmpl (%rsi,%rbp,8), %r11d
jle 0x43c2
movq %r13, %r11
incq %r13
jmp 0x43c8
movq %rcx, %r11
incq %rcx
leaq (%r11,%r11,2), %r11
movq 0x10(%rsi,%r11,8), %rbp
movq %rbp, 0x10(%rdi)
vmovups (%rsi,%r11,8), %xmm0
vmovups %xmm0, (%rdi)
incq %r10
addq $0x18, %rdi
cmpq %r15, %r10
jb 0x439d
addq %r8, %rbx
cmpq %r12, %r9
jb 0x4374
movq 0x8(%rsp), %rsi
leaq 0x1(%rsi), %rcx
movq %rdx, %rax
cmpq %r12, %rdx
movq 0x60(%rsp), %r14
movq 0x58(%rsp), %r15
jb 0x434c
testb $0x1, %sil
movq 0x48(%rsp), %rdx
jne 0x4428
movq %r14, %rdi
movq %r15, %rsi
callq 0x2100
movq %r15, %rdi
callq 0x21b0
movq (%rsp), %rbx
movl %ebx, 0x30(%rsp)
leal 0x1(%rbx), %r13d
imull %ebx, %r13d
addl %r13d, %r13d
movl %r13d, 0x10(%rsp)
xorl %eax, %eax
movl %eax, 0x24(%rsp)
movl %r13d, 0x20(%rsp)
leaq (,%r13,8), %r15
leaq (%r15,%r15,2), %rdi
callq 0x21e0
movq %rax, %rbp
movq %rax, 0x18(%rsp)
movq %r15, %rdi
callq 0x21e0
movq %rax, 0x8(%rsp)
movq %rax, 0x28(%rsp)
movl %ebx, %ebx
shlq $0x3, %rbx
movq %rbx, %rdi
callq 0x21e0
movq %rax, %r15
movq %rax, 0x38(%rsp)
movq %rbx, %rdi
callq 0x21e0
movq %rax, 0x40(%rsp)
testq %rbp, %rbp
setne %cl
cmpq $0x0, 0x8(%rsp)
setne %dl
testq %r15, %r15
setne %sil
andb %dl, %sil
andb %cl, %sil
testq %rax, %rax
setne %al
movl $0x53, %ebp
testb %al, %sil
movl $0x0, %eax
cmovnel %eax, %ebp
je 0x45d4
testl %r13d, %r13d
je 0x4501
movl %r13d, %eax
xorl %ecx, %ecx
leaq (%rcx,%rcx,2), %rdx
shlq $0x3, %rdx
addq 0x18(%rsp), %rdx
movq 0x28(%rsp), %rsi
movq %rdx, (%rsi,%rcx,8)
incq %rcx
cmpq %rax, %rcx
jne 0x44e3
movl (%r14), %esi
leaq 0x10(%rsp), %r15
movq %r15, %rdi
movl $0x1, %edx
xorl %ecx, %ecx
callq 0x4615
movl 0x18(%r14), %esi
movq %r15, %rdi
movl $0x2, %edx
xorl %ecx, %ecx
callq 0x4615
movl 0x20(%r15), %eax
testq %rax, %rax
je 0x455e
xorl %ecx, %ecx
movq 0x18(%rsp), %rdx
movq 0x38(%rsp), %rsi
movq %rdx, (%rsi,%rcx,8)
movq 0x18(%rsp), %rdx
movq 0x40(%rsp), %rsi
addq $0x18, %rdx
movq %rdx, (%rsi,%rcx,8)
incq %rcx
cmpq %rcx, %rax
jne 0x4536
leaq -0x2(%r12,%r12), %rbx
cmpq $0x2, %rbx
je 0x4595
movq (%rsp), %rax
leal -0x1(%rax), %r15d
movl $0x2, %r13d
leaq 0x10(%rsp), %rdi
movq %r14, %rsi
movq %r12, %rdx
movl %r15d, %ecx
movl %r13d, %r8d
callq 0x475a
incl %r13d
cmpq %r13, %rbx
jne 0x4577
movq 0x40(%rsp), %rax
movq (%rsp), %rcx
decl %ecx
movq (%rax,%rcx,8), %rax
testq %rax, %rax
movq 0x50(%rsp), %rsi
je 0x45d4
cmpl $0x0, 0x4(%rax)
je 0x45cb
xorl %ecx, %ecx
movl %ecx, %edx
leaq (%rdx,%rdx,2), %rdx
movl 0x4(%r14,%rdx,8), %edx
incl (%rsi,%rdx,4)
incl %ecx
cmpl 0x4(%rax), %ecx
jne 0x45b6
movq 0x8(%rax), %rax
testq %rax, %rax
jne 0x45ae
movq 0x18(%rsp), %rdi
callq 0x21b0
movq 0x28(%rsp), %rdi
callq 0x21b0
movq 0x38(%rsp), %rdi
callq 0x21b0
movq 0x40(%rsp), %rdi
callq 0x21b0
movq %r14, %rdi
callq 0x21b0
movl %ebp, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq