// File: /workspace/github_cpp_makefile_star2_O2/AlgoLab[P]bwt-lcp-parallel/bwt_lcp.cpp
// Function: compute_interleave_LCP_segment(base_env_t&, bfv_env_t&, unsigned long, unsigned long, unsigned char, std::vector<unsigned int, std::allocator<unsigned int>> const&, unsigned int)
void compute_interleave_LCP_segment(
                                    base_env_t& base_env,
                                    bfv_env_t& bfv_env,
                                    const luint_t segm_b, const luint_t segm_e,
                                    const strlen_t p,
                                    const std::vector<strnum_t>& Qppos,
                                    unsigned idx
) {
  std::cout << ".";
  const luint_t tot = segm_e - segm_b;
  const strlen_t k = base_env.k;
  auto& E = base_env.E;

  auto& LCP = bfv_env.LCP;
  std::vector<strnum_t> Qppos_int = Qppos;

  mmap_reader_t<strlen_t> IX0(base_env.IX_names[(p-1)%2]);
  mmap_writer_t<strlen_t, ALPHSIZE> IX1(base_env.IX_names[p%2]);
  qp_readers_t Qp, Qpbis;
  for (strlen_t l = p+1; l <= k+1; ++l) {
    Qp.emplace_back(base_env.Qp[l-p-1].cloneAndSeek(Qppos[l-1]));
    Qpbis.emplace_back(base_env.Qp[l-p-1].cloneAndSeek(Qppos[l-1]));
  }
  luint_t Lcount[ALPHSIZE];
  fill_with_0<luint_t, ALPHSIZE>(Lcount);
  luint_t Lpos[ALPHSIZE];
  luint_t b = segm_b;
  bool has_pseg_wider_than_1 = false;
  bfv_env.end_pos.clear();
  bfv_env.end_pos_Qp.clear();
  IX0.seek(segm_b);
  IX1.seek(ALPHSIZE-1, segm_b);
  for (luint_t i = segm_b; i < segm_e; ++i) {
    const strlen_t IX0i = IX0.read();
    const enc_nucl_t c = (IX0i < p) ? 0 : Qp[IX0i-p].read();
    ///printf("p=%d i=%lu IX=%d c=%x L%x=%d\n", p, i, IX0i, c, c, IX0i);
    ++Qppos_int[IX0i];
    ++Lcount[c];
    if (E[i]) {
      ///printf("finished segment at pos %lu\n", i);
      if (i+1 >= base_env.midpoints[idx-1]) {
        bfv_env.end_pos.push_back(i + 1);
        bfv_env.end_pos_Qp.push_back(Qppos_int);
        ++idx;
      }
      if (b==i) {
        // Special case of a single-element segment
        if (IX0i >= p) Qpbis[IX0i-p].skip();  // advance Qpbis as well
        IX1.write(ALPHSIZE-1, IX0i);
        Lcount[c] = 0;
        b = i + 1;
      } else {
        const bool this_has_pseg_wider_than_1 = compute_Lpos(Lpos, b, Lcount);
        has_pseg_wider_than_1 |= this_has_pseg_wider_than_1;
        for (enc_nucl_t sigma = 0; sigma<ALPHSIZE; ++sigma) {
          if (Lcount[sigma] > 0) {
            const luint_t new_e = Lpos[sigma]+Lcount[sigma]-1-segm_b;
            ///printf("ending pos for sigma=%d in idx=%lu\n", sigma, Lpos[sigma]+Lcount[sigma]-1);
            if ((new_e < MARGIN) | (tot-new_e < MARGIN)) {
              std::lock_guard<std::mutex> lg(base_env.Emutex);
              E[segm_b+new_e] = true;
            } else {
              E[segm_b+new_e] = true;
            }
          }
        }
        if (this_has_pseg_wider_than_1) {
          update_LCP(LCP, p, Lpos[1], Lcount);
        }
        IX0.seek(b);
        IX1.seek(Lpos);
        for (luint_t r = b; r <= i; ++r) {
          const strlen_t IX0r = IX0.read();
          const enc_nucl_t cr = (IX0r < p) ? 0 : Qpbis[IX0r-p].read();
          ///printf("*p=%d i=%lu IX=%d c=%x L%x=%d\n", p, r, IX0r, cr, cr, IX0r);
          IX1.write(cr, IX0r);
        }
        fill_with_0<luint_t, ALPHSIZE>(Lcount);
        b = i + 1;
      }
    }
  }
  bfv_env.has_pseg_wider_than_1 = has_pseg_wider_than_1;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1d8, %rsp            # imm = 0x1D8
movq %r9, %rbx
movl %r8d, %r15d
movq %rcx, 0x48(%rsp)
movq %rdx, 0x40(%rsp)
movq %rsi, %r14
movq %rdi, %r13
movq 0xc3f4(%rip), %rdi      # 0xefd0
leaq 0x666e(%rip), %rsi      # 0x9251
callq 0x2230
movzbl (%r13), %eax
movl %eax, (%rsp)
leaq 0xd0(%rsp), %rdi
movq %rbx, %rsi
callq 0x4e98
movq 0x8(%r13), %rcx
leal -0x1(%r15), %eax
movw $0x2, %si
cwtd
idivw %si
movswq %dx, %rsi
shlq $0x5, %rsi
addq (%rcx), %rsi
leaq 0xe8(%rsp), %rdi
callq 0x4ee6
movq %r14, 0x20(%rsp)
movq 0x8(%r13), %rax
movl %r15d, %esi
andl $0x1, %esi
shll $0x5, %esi
addq (%rax), %rsi
leaq 0x140(%rsp), %rdi
xorl %edx, %edx
callq 0x4f2a
movl 0x210(%rsp), %eax
movq %rax, 0x18(%rsp)
leaq 0x40(%r13), %rax
movq %rax, 0x28(%rsp)
leaq 0xb0(%rsp), %rax
andq $0x0, 0x10(%rax)
xorps %xmm0, %xmm0
movaps %xmm0, (%rax)
leaq 0x50(%rsp), %rax
movaps %xmm0, (%rax)
andq $0x0, 0x10(%rax)
incl (%rsp)
movl %r15d, %r12d
notl %r12d
movq %r15, 0x8(%rsp)
incl %r15d
leaq 0x80(%rsp), %rbp
movq %r13, 0x30(%rsp)
movzbl %r15b, %eax
cmpl %eax, (%rsp)
jb 0x2d26
leal (%rax,%r12), %ecx
movslq %ecx, %rcx
imulq $0x28, %rcx, %r14
movq 0x18(%r13), %rsi
addq %r14, %rsi
movl %eax, %r13d
movq (%rbx), %rax
movl -0x4(%rax,%r13,4), %edx
movq %rbp, %rdi
callq 0x4fda
leaq 0xb0(%rsp), %rdi
movq %rbp, %rsi
callq 0x4f9e
decq %r13
movq %rbp, %rdi
callq 0x500e
movq 0x30(%rsp), %rax
addq 0x18(%rax), %r14
movq (%rbx), %rax
movl (%rax,%r13,4), %edx
movq %rbp, %rdi
movq %r14, %rsi
callq 0x4fda
leaq 0x50(%rsp), %rdi
movq %rbp, %rsi
callq 0x4f9e
movq %rbp, %rdi
callq 0x500e
incb %r15b
movq 0x30(%rsp), %r13
jmp 0x2ca0
leaq 0x80(%rsp), %rdi
callq 0x5040
movq 0x20(%rsp), %rcx
movq 0x30(%rcx), %rax
cmpq %rax, 0x38(%rcx)
je 0x2d46
movq %rax, 0x38(%rcx)
leaq 0x30(%rcx), %rax
movq %rax, 0x70(%rsp)
leaq 0x48(%rcx), %rdi
movq %rdi, 0x68(%rsp)
callq 0x5054
leaq 0xe8(%rsp), %rdi
movq 0x40(%rsp), %rbx
movq %rbx, %rsi
callq 0x505c
leaq 0x140(%rsp), %rdi
pushq $0x5
popq %rsi
movq %rbx, %rdx
callq 0x50f4
leaq 0x68(%r13), %rax
movq %rax, 0x10(%rsp)
movq $0x0, (%rsp)
movzbl 0x8(%rsp), %eax
movl %eax, 0x3c(%rsp)
xorl %r14d, %r14d
leaq (%rbx,%r14), %rbp
cmpq 0x48(%rsp), %rbp
jae 0x300c
leaq 0xe8(%rsp), %rdi
callq 0x5194
movl %eax, %r15d
movzbl %al, %r12d
movq 0x8(%rsp), %rcx
cmpb %cl, %r12b
jae 0x2dd4
xorl %r13d, %r13d
jmp 0x2df0
movl %r12d, %eax
subl %ecx, %eax
cltq
imulq $0x28, %rax, %rdi
addq 0xb0(%rsp), %rdi
callq 0x5194
movzbl %al, %r13d
movq 0xd0(%rsp), %rax
movl %r12d, %ecx
incl (%rax,%rcx,4)
incq 0x80(%rsp,%r13,8)
movq 0x28(%rsp), %rdi
movq %rbp, %rsi
callq 0x5210
incq %r14
testq %rdx, (%rax)
je 0x2da2
movq 0x30(%rsp), %rax
movq 0x38(%rax), %rax
movq 0x18(%rsp), %rcx
decl %ecx
leaq (%rbx,%r14), %rbp
cmpq (%rax,%rcx,8), %rbp
jb 0x2e67
movq %rbp, 0x78(%rsp)
movq 0x70(%rsp), %rdi
leaq 0x78(%rsp), %rsi
callq 0x6ae2
movq 0x68(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x522e
movq 0x18(%rsp), %rax
incl %eax
movq %rax, 0x18(%rsp)
cmpq $0x1, %r14
jne 0x2eb0
movq 0x8(%rsp), %rcx
cmpb %cl, %r15b
jb 0x2e8c
movl %r12d, %eax
subl %ecx, %eax
cltq
imulq $0x28, %rax, %rdi
addq 0x50(%rsp), %rdi
callq 0x525a
leaq 0x140(%rsp), %rdi
pushq $0x5
popq %rsi
movl %r12d, %edx
callq 0x5278
andq $0x0, 0x80(%rsp,%r13,8)
movq %rbp, %rbx
jmp 0x2d9f
leaq 0x110(%rsp), %rdi
movq %rbx, %rsi
leaq 0x80(%rsp), %rdx
callq 0x5324
movl %eax, %r15d
movq (%rsp), %rax
orb %r15b, %al
movq %rax, (%rsp)
leaq (%rbx,%r14), %r12
decq %r12
xorl %r13d, %r13d
cmpq $0x6, %r13
je 0x2f5f
movq 0x80(%rsp,%r13,8), %rax
testq %rax, %rax
je 0x2f5a
movq 0x110(%rsp,%r13,8), %rcx
leaq (%rax,%rcx), %r14
decq %r14
movq %r14, %rax
subq 0x40(%rsp), %rax
cmpq $0x40, %rax
setae %al
movq 0x48(%rsp), %rcx
subq %r14, %rcx
cmpq $0x40, %rcx
setae %cl
testb %cl, %al
jne 0x2f4a
movq 0x10(%rsp), %rdi
callq 0x6e36
movq 0x28(%rsp), %rdi
movq %r14, %rsi
callq 0x5210
orq %rdx, (%rax)
movq 0x10(%rsp), %rdi
callq 0x21c0
jmp 0x2f5a
movq 0x28(%rsp), %rdi
movq %r14, %rsi
callq 0x5210
orq %rdx, (%rax)
incq %r13
jmp 0x2ee0
testb %r15b, %r15b
je 0x2f82
movq 0x118(%rsp), %rdx
movq 0x20(%rsp), %rdi
movl 0x3c(%rsp), %esi
leaq 0x80(%rsp), %rcx
callq 0x2a8f
leaq 0xe8(%rsp), %rdi
movq %rbx, %rsi
callq 0x505c
leaq 0x140(%rsp), %rdi
leaq 0x110(%rsp), %rsi
callq 0x535c
movq 0x8(%rsp), %r14
cmpq %r12, %rbx
ja 0x2ffa
movq %rbp, %r15
leaq 0xe8(%rsp), %rdi
callq 0x5194
xorl %esi, %esi
movzbl %al, %ebp
cmpb %r14b, %al
jb 0x2fe3
movl %ebp, %eax
subl %r14d, %eax
cltq
imulq $0x28, %rax, %rdi
addq 0x50(%rsp), %rdi
callq 0x5194
movzbl %al, %esi
leaq 0x140(%rsp), %rdi
movl %ebp, %edx
callq 0x5278
incq %rbx
movq %r15, %rbp
jmp 0x2fac
leaq 0x80(%rsp), %rdi
callq 0x5040
jmp 0x2ea8
movq (%rsp), %rcx
andb $0x1, %cl
movq 0x20(%rsp), %rax
movb %cl, 0x29(%rax)
leaq 0x50(%rsp), %rdi
callq 0x538a
leaq 0xb0(%rsp), %rdi
callq 0x538a
leaq 0x140(%rsp), %rdi
callq 0x53ac
leaq 0xe8(%rsp), %rdi
callq 0x500e
leaq 0xd0(%rsp), %rdi
callq 0x67ee
addq $0x1d8, %rsp            # imm = 0x1D8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x3092
movq %rax, %rbx
movq 0x10(%rsp), %rdi
callq 0x21c0
jmp 0x30a7
jmp 0x3092
jmp 0x3092
jmp 0x3092
movq %rax, %rbx
jmp 0x30cb
movq %rax, %rbx
jmp 0x30d8
jmp 0x3092
jmp 0x3092
jmp 0x3097
movq %rax, %rbx
jmp 0x30a7
movq %rax, %rbx
leaq 0x80(%rsp), %rdi
callq 0x500e
leaq 0x50(%rsp), %rdi
callq 0x538a
leaq 0xb0(%rsp), %rdi
callq 0x538a
leaq 0x140(%rsp), %rdi
callq 0x53ac
leaq 0xe8(%rsp), %rdi
callq 0x500e
leaq 0xd0(%rsp), %rdi
callq 0x67ee
movq %rbx, %rdi
callq 0x23d0