// File: /workspace/github_cpp_makefile_star2_O1/phillip-h[P]fractal-gen/lodepng.cpp
// Function: encodeLZ77(uivector*, Hash*, unsigned char const*, unsigned long, unsigned long, unsigned int, unsigned int, unsigned int, unsigned int)
static unsigned encodeLZ77(uivector* out, Hash* hash,
                           const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize,
                           unsigned minmatch, unsigned nicematch, unsigned lazymatching)
{
  size_t pos;
  unsigned i, error = 0;
  /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/
  unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8;
  unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64;

  unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/
  unsigned numzeros = 0;

  unsigned offset; /*the offset represents the distance in LZ77 terminology*/
  unsigned length;
  unsigned lazy = 0;
  unsigned lazylength = 0, lazyoffset = 0;
  unsigned hashval;
  unsigned current_offset, current_length;
  unsigned prev_offset;
  const unsigned char *lastptr, *foreptr, *backptr;
  unsigned hashpos;

  if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/
  if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/

  if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH;

  for(pos = inpos; pos < insize; ++pos)
  {
    size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/
    unsigned chainlength = 0;

    hashval = getHash(in, insize, pos);

    if(usezeros && hashval == 0)
    {
      if(numzeros == 0) numzeros = countZeros(in, insize, pos);
      else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;
    }
    else
    {
      numzeros = 0;
    }

    updateHashChain(hash, wpos, hashval, numzeros);

    /*the length and offset found for the current position*/
    length = 0;
    offset = 0;

    hashpos = hash->chain[wpos];

    lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH];

    /*search for the longest string*/
    prev_offset = 0;
    for(;;)
    {
      if(chainlength++ >= maxchainlength) break;
      current_offset = hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize;

      if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/
      prev_offset = current_offset;
      if(current_offset > 0)
      {
        /*test the next characters*/
        foreptr = &in[pos];
        backptr = &in[pos - current_offset];

        /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/
        if(numzeros >= 3)
        {
          unsigned skip = hash->zeros[hashpos];
          if(skip > numzeros) skip = numzeros;
          backptr += skip;
          foreptr += skip;
        }

        while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/
        {
          ++backptr;
          ++foreptr;
        }
        current_length = (unsigned)(foreptr - &in[pos]);

        if(current_length > length)
        {
          length = current_length; /*the longest length*/
          offset = current_offset; /*the offset that is related to this longest length*/
          /*jump out once a length of max length is found (speed gain). This also jumps
          out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/
          if(current_length >= nicematch) break;
        }
      }

      if(hashpos == hash->chain[hashpos]) break;

      if(numzeros >= 3 && length > numzeros)
      {
        hashpos = hash->chainz[hashpos];
        if(hash->zeros[hashpos] != numzeros) break;
      }
      else
      {
        hashpos = hash->chain[hashpos];
        /*outdated hash value, happens if particular value was not encountered in whole last window*/
        if(hash->val[hashpos] != (int)hashval) break;
      }
    }

    if(lazymatching)
    {
      if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH)
      {
        lazy = 1;
        lazylength = length;
        lazyoffset = offset;
        continue; /*try the next byte*/
      }
      if(lazy)
      {
        lazy = 0;
        if(pos == 0) ERROR_BREAK(81);
        if(length > lazylength + 1)
        {
          /*push the previous character as literal*/
          if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/);
        }
        else
        {
          length = lazylength;
          offset = lazyoffset;
          hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/
          hash->headz[numzeros] = -1; /*idem*/
          --pos;
        }
      }
    }
    if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/);

    /*encode it as length/distance pair or literal value*/
    if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/
    {
      if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);
    }
    else if(length < minmatch || (length == 3 && offset > 4096))
    {
      /*compensate for the fact that longer offsets have more extra bits, a
      length of only 3 may be not worth it then*/
      if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);
    }
    else
    {
      addLengthDistance(out, length, offset);
      for(i = 1; i < length; ++i)
      {
        ++pos;
        wpos = pos & (windowsize - 1);
        hashval = getHash(in, insize, pos);
        if(usezeros && hashval == 0)
        {
          if(numzeros == 0) numzeros = countZeros(in, insize, pos);
          else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;
        }
        else
        {
          numzeros = 0;
        }
        updateHashChain(hash, wpos, hashval, numzeros);
      }
    }
  } /*end of the loop through each character of input*/

  return error;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rcx, %r12
movq %rdx, 0x8(%rsp)
movq %rsi, 0x40(%rsp)
movl %r9d, %eax
shrl $0x3, %eax
cmpl $0x2000, %r9d           # imm = 0x2000
cmovael %r9d, %eax
movl %eax, 0x4c(%rsp)
movl $0x102, %eax            # imm = 0x102
movl $0x40, %ecx
cmovael %eax, %ecx
movl %ecx, 0x60(%rsp)
movq %r9, 0x50(%rsp)
leal -0x8001(%r9), %eax
movl $0x3c, 0x4(%rsp)
cmpl $0xffff8000, %eax       # imm = 0xFFFF8000
jb 0xe769
movq 0x50(%rsp), %rcx
leal -0x1(%rcx), %eax
movl $0x5a, 0x4(%rsp)
testl %eax, %ecx
jne 0xe769
movq %r8, %rbx
movl 0xd8(%rsp), %ecx
movl $0x102, %edx            # imm = 0x102
cmpl %edx, %ecx
cmovbl %ecx, %edx
movl %edx, 0x64(%rsp)
movl $0x0, 0x4(%rsp)
cmpq %r8, %r12
jae 0xe769
movl %eax, %eax
movq %rax, 0x80(%rsp)
movq 0x8(%rsp), %rax
addq %rbx, %rax
movq %rax, 0x78(%rsp)
movl 0x50(%rsp), %eax
movq %rax, 0x90(%rsp)
movq $0x0, 0x68(%rsp)
movq $0x0, 0x70(%rsp)
movq $0x0, 0x28(%rsp)
xorl %ebp, %ebp
movl $0x0, 0x4(%rsp)
movq %rbx, 0x10(%rsp)
movq %rdi, 0x30(%rsp)
movq 0x8(%rsp), %rdi
movq %rbx, %rsi
movq %r12, %rdx
callq 0xe8e1
movl $0x0, %r14d
testl %eax, %eax
jne 0xe170
testl %ebp, %ebp
je 0xe137
movl %ebp, %ecx
addq %r12, %rcx
cmpq %rbx, %rcx
ja 0xe130
movq 0x8(%rsp), %rdx
cmpb $0x0, -0x1(%rdx,%rcx)
je 0xe132
decl %ebp
movl %ebp, %r14d
jmp 0xe170
movq 0x8(%rsp), %rdx
leaq (%rdx,%r12), %rcx
leaq 0x102(%rdx,%r12), %rdx
movq 0x78(%rsp), %rsi
cmpq %rsi, %rdx
cmovaq %rsi, %rdx
movq %rcx, %r14
cmpq %rdx, %rcx
je 0xe16d
movq %rcx, %r14
cmpb $0x0, (%r14)
jne 0xe16d
incq %r14
cmpq %rdx, %r14
jne 0xe15f
subl %ecx, %r14d
movl %r12d, %edi
andl 0x80(%rsp), %edi
movq 0x40(%rsp), %rbp
movq 0x10(%rbp), %r8
movl %eax, (%r8,%rdi,4)
movq (%rbp), %rsi
movl %eax, %r9d
movl (%rsi,%r9,4), %ecx
cmpl $-0x1, %ecx
je 0xe19f
movq 0x8(%rbp), %rdx
movw %cx, (%rdx,%rdi,2)
movq %rsi, 0x38(%rsp)
movq %r9, 0x58(%rsp)
movl %edi, (%rsi,%r9,4)
movq 0x28(%rbp), %r9
movw %r14w, (%r9,%rdi,2)
movq 0x18(%rbp), %r11
movzwl %r14w, %ecx
movl (%r11,%rcx,4), %edx
cmpl $-0x1, %edx
je 0xe1cf
movq 0x20(%rbp), %rsi
movw %dx, (%rsi,%rdi,2)
leaq 0x102(%r12), %r10
cmpq %rbx, %r10
cmovaeq %rbx, %r10
movq %r11, 0x88(%rsp)
movl %edi, (%r11,%rcx,4)
cmpl $0x0, 0x4c(%rsp)
movq %r12, 0x20(%rsp)
je 0xe2f9
movq 0x8(%rsp), %rcx
addq %rcx, %r10
movq 0x8(%rbp), %r11
movzwl (%r11,%rdi,2), %r15d
leaq (%rcx,%r12), %rsi
xorl %edx, %edx
movl $0x1, %ecx
xorl %r13d, %r13d
movl $0x0, 0x18(%rsp)
movl %edx, %ebx
movzwl %r15w, %r12d
movq %rdi, %rdx
subq %r12, %rdx
movl $0x0, %r15d
cmovbq 0x90(%rsp), %r15
addq %r15, %rdx
cmpl %edx, %ebx
ja 0xe304
testq %rdx, %rdx
je 0xe2b3
movl %edx, %r15d
movq 0x20(%rsp), %rbx
subq %r15, %rbx
addq 0x8(%rsp), %rbx
cmpl $0x3, %r14d
jb 0xe276
movzwl (%r9,%r12,2), %r15d
cmpl %r15d, %r14d
cmovbl %r14d, %r15d
addq %r15, %rbx
addq %rsi, %r15
jmp 0xe279
movq %rsi, %r15
cmpq %r10, %r15
je 0xe299
movb (%rbx), %bpl
cmpb (%r15), %bpl
jne 0xe294
incq %rbx
incq %r15
cmpq %r10, %r15
jne 0xe27e
movq %r10, %r15
movq 0x40(%rsp), %rbp
subl %esi, %r15d
cmpl %r15d, %r13d
jae 0xe2b3
movl %edx, 0x18(%rsp)
movl %r15d, %r13d
cmpl %r15d, 0x64(%rsp)
jbe 0xe745
movzwl (%r11,%r12,2), %r15d
cmpw %r15w, %r12w
je 0xe304
cmpl $0x3, %r14d
jb 0xe2de
cmpl %r14d, %r13d
jbe 0xe2de
movq 0x20(%rbp), %rbx
movzwl (%rbx,%r12,2), %r15d
movzwl (%r9,%r15,2), %ebx
cmpl %ebx, %r14d
je 0xe2e8
jmp 0xe304
movzwl %r15w, %ebx
cmpl %eax, (%r8,%rbx,4)
jne 0xe304
leal 0x1(%rcx), %ebx
cmpl 0x4c(%rsp), %ecx
movl %ebx, %ecx
jne 0xe221
jmp 0xe304
movl $0x0, 0x18(%rsp)
xorl %r13d, %r13d
cmpl $0x0, 0xe0(%rsp)
je 0xe376
movq 0x28(%rsp), %rdx
testl %edx, %edx
movq 0x30(%rsp), %r15
movl 0x18(%rsp), %esi
jne 0xe35e
cmpl $0x3, %r13d
jb 0xe35e
cmpl 0x60(%rsp), %r13d
setbe %al
cmpl $0x102, %r13d           # imm = 0x102
setb %cl
testb %cl, %al
je 0xe35e
movb $0x1, %al
movl $0x1, %ecx
movq %rcx, 0x28(%rsp)
movl %r13d, %ecx
movq %rcx, 0x70(%rsp)
movl %esi, %ecx
movq %rcx, 0x68(%rsp)
movq 0x10(%rsp), %rbx
jmp 0xe39a
testl %edx, %edx
movq 0x10(%rsp), %rbx
jne 0xe400
movq $0x0, 0x28(%rsp)
jmp 0xe384
movq 0x10(%rsp), %rbx
movq 0x30(%rsp), %r15
movl 0x18(%rsp), %esi
cmpl $0x3, %r13d
jb 0xe3a4
cmpl 0x50(%rsp), %esi
jbe 0xe3a4
xorl %eax, %eax
movl $0x56, 0x4(%rsp)
movq 0x20(%rsp), %r12
jmp 0xe730
cmpl $0x2, %r13d
jbe 0xe3ca
cmpl 0xd0(%rsp), %r13d
jb 0xe3ca
cmpl $0x3, %r13d
jne 0xe4c0
cmpl $0x1000, %esi           # imm = 0x1000
jbe 0xe4c0
movq 0x8(%rsp), %rax
movq 0x20(%rsp), %r12
movb (%rax,%r12), %bl
movq 0x8(%r15), %rsi
incq %rsi
movq %r15, %rdi
callq 0xdfaf
testl %eax, %eax
je 0xe459
movzbl %bl, %eax
movq (%r15), %rcx
movq 0x8(%r15), %rdx
movl %eax, -0x4(%rcx,%rdx,4)
movb $0x1, %al
jmp 0xe72b
cmpq $0x0, 0x20(%rsp)
movq 0x70(%rsp), %rdx
je 0xe468
leal 0x1(%rdx), %eax
cmpl %eax, %r13d
jbe 0xe483
movq 0x8(%rsp), %rax
movq 0x20(%rsp), %rcx
movzbl -0x1(%rax,%rcx), %ebx
movq 0x8(%r15), %rsi
incq %rsi
movq %r15, %rdi
callq 0xdfaf
testl %eax, %eax
je 0xe751
movq (%r15), %rax
movq 0x8(%r15), %rcx
movl %ebx, -0x4(%rax,%rcx,4)
movq $0x0, 0x28(%rsp)
movq 0x10(%rsp), %rbx
jmp 0xe380
movl $0x53, 0x4(%rsp)
xorl %eax, %eax
jmp 0xe72b
movq $0x0, 0x28(%rsp)
movl $0x51, 0x4(%rsp)
xorl %r12d, %r12d
xorl %eax, %eax
jmp 0xe730
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movq 0x38(%rsp), %rax
movq 0x58(%rsp), %rsi
movl %ecx, (%rax,%rsi,4)
movl %r14d, %eax
movq 0x88(%rsp), %rsi
movl %ecx, (%rsi,%rax,4)
decq 0x20(%rsp)
movq $0x0, 0x28(%rsp)
movq 0x68(%rsp), %rax
movl %eax, %esi
movl %edx, %r13d
jmp 0xe384
movl $0x1c, %eax
movl $0x1, %r15d
leaq (%rax,%r15), %rcx
shrq %rcx
leaq 0x3847(%rip), %rdx      # 0x11d20
cmpl %r13d, (%rdx,%rcx,4)
jb 0xe4e7
decq %rcx
movq %rcx, %rax
jmp 0xe4ed
incq %rcx
movq %rcx, %r15
cmpq %rax, %r15
jbe 0xe4cb
cmpq $0x1c, %r15
ja 0xe505
leaq 0x3821(%rip), %rax      # 0x11d20
cmpl %r13d, (%rax,%r15,4)
jbe 0xe508
decq %r15
movl %r15d, %eax
leaq 0x380e(%rip), %rcx      # 0x11d20
movl (%rcx,%rax,4), %edi
movl $0x1d, %eax
movl $0x1, %r12d
leaq (%rax,%r12), %rcx
shrq %rcx
leaq 0x38f2(%rip), %rdx      # 0x11e20
cmpl %esi, (%rdx,%rcx,4)
jb 0xe53b
decq %rcx
movq %rcx, %rax
jmp 0xe541
incq %rcx
movq %rcx, %r12
cmpq %rax, %r12
jbe 0xe520
cmpq $0x1d, %r12
movl %edi, 0x38(%rsp)
ja 0xe55d
leaq 0x38c9(%rip), %rax      # 0x11e20
cmpl %esi, (%rax,%r12,4)
jbe 0xe560
decq %r12
movl %r12d, %eax
leaq 0x38b6(%rip), %rcx      # 0x11e20
subl (%rcx,%rax,4), %esi
movl %esi, 0x18(%rsp)
movq 0x30(%rsp), %rdi
movq 0x8(%rdi), %rsi
incq %rsi
callq 0xdfaf
testl %eax, %eax
je 0xe59e
addl $0x101, %r15d           # imm = 0x101
movq 0x30(%rsp), %rcx
movq (%rcx), %rax
movq 0x8(%rcx), %rcx
movl %r15d, -0x4(%rax,%rcx,4)
movq 0x30(%rsp), %r15
movq 0x8(%r15), %rsi
incq %rsi
movq %r15, %rdi
callq 0xdfaf
testl %eax, %eax
je 0xe5c8
movl %r13d, %eax
subl 0x38(%rsp), %eax
movq (%r15), %rcx
movq 0x8(%r15), %rdx
movl %eax, -0x4(%rcx,%rdx,4)
movq 0x8(%r15), %rsi
incq %rsi
movq %r15, %rdi
callq 0xdfaf
testl %eax, %eax
je 0xe5e7
movq (%r15), %rax
movq 0x8(%r15), %rcx
movl %r12d, -0x4(%rax,%rcx,4)
movq 0x8(%r15), %rsi
incq %rsi
movq %r15, %rdi
callq 0xdfaf
testl %eax, %eax
je 0xe609
movq (%r15), %rax
movq 0x8(%r15), %rcx
movl 0x18(%rsp), %edx
movl %edx, -0x4(%rax,%rcx,4)
movq (%rbp), %r12
movq 0x10(%rbp), %rax
movq %rax, 0x18(%rsp)
movq 0x28(%rbp), %rax
movq %rax, 0x38(%rsp)
movq 0x18(%rbp), %r9
cmpl $0x3, %r13d
movl $0x2, %eax
cmovbl %eax, %r13d
movl $0x1, %r15d
movq 0x20(%rsp), %rbp
movq %r9, 0x58(%rsp)
leaq 0x1(%rbp), %rbx
movq 0x8(%rsp), %rdi
movq 0x10(%rsp), %rsi
movq %rbx, %rdx
callq 0xe8e1
xorl %ecx, %ecx
testl %eax, %eax
jne 0xe6b9
testl %r14d, %r14d
je 0xe682
movl %r14d, %ecx
leaq (%rbx,%rcx), %rdx
cmpq 0x10(%rsp), %rdx
ja 0xe67a
addq 0x8(%rsp), %rbp
cmpb $0x0, (%rcx,%rbp)
je 0xe67d
decl %r14d
movl %r14d, %ecx
jmp 0xe6b9
movq 0x8(%rsp), %rcx
leaq (%rcx,%rbx), %rdx
leaq 0x102(%rcx,%rbx), %rsi
movq 0x78(%rsp), %rcx
cmpq %rcx, %rsi
cmovaq %rcx, %rsi
movq %rdx, %rcx
cmpq %rsi, %rdx
je 0xe6b7
movq %rdx, %rcx
cmpb $0x0, (%rcx)
jne 0xe6b7
incq %rcx
cmpq %rsi, %rcx
jne 0xe6aa
subl %edx, %ecx
movl %ebx, %edx
andl 0x80(%rsp), %edx
movq 0x18(%rsp), %rsi
movl %eax, (%rsi,%rdx,4)
movl %eax, %eax
movl (%r12,%rax,4), %esi
cmpl $-0x1, %esi
movq 0x58(%rsp), %r9
je 0xe6e7
movq 0x40(%rsp), %rdi
movq 0x8(%rdi), %rdi
movw %si, (%rdi,%rdx,2)
movl %edx, (%r12,%rax,4)
movq 0x38(%rsp), %rax
movw %cx, (%rax,%rdx,2)
movzwl %cx, %eax
movl (%r9,%rax,4), %esi
cmpl $-0x1, %esi
je 0xe70d
movq 0x40(%rsp), %rdi
movq 0x20(%rdi), %rdi
movw %si, (%rdi,%rdx,2)
movl %edx, (%r9,%rax,4)
incl %r15d
movq %rbx, %rbp
movl %ecx, %r14d
cmpl %r13d, %r15d
jne 0xe640
movb $0x1, %al
movl %ecx, %r14d
movq %rbx, %r12
movq 0x10(%rsp), %rbx
testb %al, %al
je 0xe769
incq %r12
movl %r14d, %ebp
cmpq %rbx, %r12
jb 0xe0fc
jmp 0xe769
movl %edx, 0x18(%rsp)
movl %r15d, %r13d
jmp 0xe304
movq $0x0, 0x28(%rsp)
movl $0x53, 0x4(%rsp)
xorl %eax, %eax
jmp 0xe357
movl 0x4(%rsp), %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq