// File: 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
movq %rsp, %rbp
subq $0x310, %rsp            # imm = 0x310
movb %r8b, %al
movl 0x10(%rbp), %r8d
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movb %al, -0x21(%rbp)
movq %r9, -0x30(%rbp)
movq 0x22e50(%rip), %rdi     # 0x26fd0
leaq 0x15168(%rip), %rsi     # 0x192ef
callq 0x3290
movq -0x20(%rbp), %rax
movq -0x18(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rax
movb (%rax), %al
movb %al, -0x39(%rbp)
movq -0x8(%rbp), %rax
addq $0x40, %rax
movq %rax, -0x48(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x30(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x8960
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movzbl -0x21(%rbp), %ecx
movl %ecx, %edx
decl %edx
movl %ecx, %eax
shrl $0x1f, %edx
movl %edx, %ecx
leal -0x1(%rax,%rcx), %edx
andl $-0x2, %edx
negl %edx
movl %edx, %ecx
leal -0x1(%rax,%rcx), %eax
movslq %eax, %rsi
callq 0x8080
movq %rax, %rsi
leaq -0x90(%rbp), %rdi
callq 0x8a50
jmp 0x4204
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rdi
movzbl -0x21(%rbp), %eax
andl $0x1, %eax
movl %eax, %esi
callq 0x8080
movq %rax, %rsi
xorl %eax, %eax
movl %eax, %edx
leaq -0x138(%rbp), %rdi
callq 0x8ad0
jmp 0x422f
leaq -0x150(%rbp), %rdi
callq 0x8b90
leaq -0x168(%rbp), %rdi
callq 0x8b90
movzbl -0x21(%rbp), %eax
addl $0x1, %eax
movb %al, -0x169(%rbp)
movzbl -0x169(%rbp), %eax
movzbl -0x39(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jg 0x43f2
movq -0x8(%rbp), %rdi
addq $0x18, %rdi
movzbl -0x169(%rbp), %ecx
movzbl -0x21(%rbp), %eax
notl %eax
addl %ecx, %eax
movslq %eax, %rsi
callq 0x8c30
movq %rax, -0x2a8(%rbp)
movq -0x30(%rbp), %rdi
movzbl -0x169(%rbp), %eax
movl %eax, %esi
decq %rsi
callq 0x8cc0
movq -0x2a8(%rbp), %rsi
movl (%rax), %eax
movl %eax, %edx
leaq -0x198(%rbp), %rdi
callq 0x8c50
jmp 0x42be
leaq -0x150(%rbp), %rdi
leaq -0x198(%rbp), %rsi
callq 0x8bb0
jmp 0x42d3
leaq -0x198(%rbp), %rdi
callq 0x8ce0
movq -0x8(%rbp), %rdi
addq $0x18, %rdi
movzbl -0x169(%rbp), %ecx
movzbl -0x21(%rbp), %eax
notl %eax
addl %ecx, %eax
movslq %eax, %rsi
callq 0x8c30
movq %rax, -0x2b0(%rbp)
movq -0x30(%rbp), %rdi
movzbl -0x169(%rbp), %eax
movl %eax, %esi
decq %rsi
callq 0x8cc0
movq -0x2b0(%rbp), %rsi
movl (%rax), %eax
movl %eax, %edx
leaq -0x1c0(%rbp), %rdi
callq 0x8c50
jmp 0x4333
leaq -0x168(%rbp), %rdi
leaq -0x1c0(%rbp), %rsi
callq 0x8bb0
jmp 0x4348
leaq -0x1c0(%rbp), %rdi
callq 0x8ce0
movb -0x169(%rbp), %al
addb $0x1, %al
movb %al, -0x169(%rbp)
jmp 0x4254
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x4a32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x4a26
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
jmp 0x4a02
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x198(%rbp), %rdi
callq 0x8ce0
jmp 0x4a02
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x1c0(%rbp), %rdi
callq 0x8ce0
jmp 0x4a02
leaq -0x1f0(%rbp), %rdi
callq 0x8d50
jmp 0x4400
movq -0x18(%rbp), %rax
movq %rax, -0x228(%rbp)
movb $0x0, -0x229(%rbp)
movq -0x10(%rbp), %rdi
addq $0x30, %rdi
callq 0x8d90
movq -0x10(%rbp), %rdi
addq $0x48, %rdi
callq 0x8db0
movq -0x18(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0x8dd0
jmp 0x443e
movq -0x18(%rbp), %rdx
leaq -0x138(%rbp), %rdi
movl $0x5, %esi
callq 0x8ec0
jmp 0x4455
movq -0x18(%rbp), %rax
movq %rax, -0x238(%rbp)
movq -0x238(%rbp), %rax
cmpq -0x20(%rbp), %rax
jae 0x49b0
leaq -0x90(%rbp), %rdi
callq 0x8fe0
movb %al, -0x2b1(%rbp)
jmp 0x4485
movb -0x2b1(%rbp), %al
movb %al, -0x239(%rbp)
movzbl -0x239(%rbp), %eax
movzbl -0x21(%rbp), %ecx
cmpl %ecx, %eax
jge 0x44aa
xorl %eax, %eax
movl %eax, -0x2b8(%rbp)
jmp 0x44e5
movzbl -0x239(%rbp), %eax
movzbl -0x21(%rbp), %ecx
subl %ecx, %eax
movslq %eax, %rsi
leaq -0x150(%rbp), %rdi
callq 0x8c30
movq %rax, %rdi
callq 0x8fe0
movb %al, -0x2b9(%rbp)
jmp 0x44d6
movb -0x2b9(%rbp), %al
movzbl %al, %eax
movl %eax, -0x2b8(%rbp)
movl -0x2b8(%rbp), %eax
movb %al, -0x23a(%rbp)
movzbl -0x239(%rbp), %eax
movl %eax, %esi
leaq -0x68(%rbp), %rdi
callq 0x9090
movl (%rax), %ecx
incl %ecx
movl %ecx, (%rax)
movzbl -0x23a(%rbp), %eax
movq -0x1f0(%rbp,%rax,8), %rcx
incq %rcx
movq %rcx, -0x1f0(%rbp,%rax,8)
movq -0x48(%rbp), %rdi
movq -0x238(%rbp), %rsi
callq 0x90b0
movq %rdx, -0x2d0(%rbp)
movq %rax, -0x2c8(%rbp)
jmp 0x4543
movq -0x2d0(%rbp), %rax
movq -0x2c8(%rbp), %rcx
movq %rcx, -0x250(%rbp)
movq %rax, -0x248(%rbp)
leaq -0x250(%rbp), %rdi
callq 0x9110
testb $0x1, %al
jne 0x4574
jmp 0x4997
movq -0x238(%rbp), %rax
addq $0x1, %rax
movq -0x8(%rbp), %rcx
movq 0x38(%rcx), %rcx
movl 0x10(%rbp), %edx
subl $0x1, %edx
movl %edx, %edx
cmpq (%rcx,%rdx,8), %rax
jb 0x45d8
movq -0x10(%rbp), %rdi
addq $0x30, %rdi
movq -0x238(%rbp), %rax
incq %rax
movq %rax, -0x258(%rbp)
leaq -0x258(%rbp), %rsi
callq 0x9140
jmp 0x45bc
movq -0x10(%rbp), %rdi
addq $0x48, %rdi
leaq -0x68(%rbp), %rsi
callq 0x9170
jmp 0x45cf
movl 0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, 0x10(%rbp)
movq -0x228(%rbp), %rax
cmpq -0x238(%rbp), %rax
jne 0x4663
movzbl -0x239(%rbp), %eax
movzbl -0x21(%rbp), %ecx
cmpl %ecx, %eax
jl 0x461f
movzbl -0x239(%rbp), %eax
movzbl -0x21(%rbp), %ecx
subl %ecx, %eax
movslq %eax, %rsi
leaq -0x168(%rbp), %rdi
callq 0x8c30
movq %rax, %rdi
callq 0x91e0
jmp 0x461d
jmp 0x461f
movzbl -0x239(%rbp), %edx
leaq -0x138(%rbp), %rdi
movl $0x5, %esi
callq 0x9230
jmp 0x4639
movzbl -0x23a(%rbp), %eax
movq $0x0, -0x1f0(%rbp,%rax,8)
movq -0x238(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x228(%rbp)
jmp 0x4995
movq -0x228(%rbp), %rsi
leaq -0x220(%rbp), %rdi
leaq -0x1f0(%rbp), %rdx
callq 0x9360
movb %al, -0x2d1(%rbp)
jmp 0x4685
movb -0x2d1(%rbp), %al
andb $0x1, %al
movb %al, -0x259(%rbp)
movb -0x259(%rbp), %al
andb $0x1, %al
movzbl %al, %ecx
movb -0x229(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
orl %ecx, %eax
cmpl $0x0, %eax
setne %al
andb $0x1, %al
movb %al, -0x229(%rbp)
movb $0x0, -0x25a(%rbp)
movzbl -0x25a(%rbp), %eax
cmpl $0x6, %eax
jge 0x484c
movzbl -0x25a(%rbp), %eax
cmpq $0x0, -0x1f0(%rbp,%rax,8)
jbe 0x4837
movzbl -0x25a(%rbp), %eax
movq -0x220(%rbp,%rax,8), %rax
movzbl -0x25a(%rbp), %ecx
addq -0x1f0(%rbp,%rcx,8), %rax
subq $0x1, %rax
subq -0x18(%rbp), %rax
movq %rax, -0x268(%rbp)
cmpq $0x40, -0x268(%rbp)
setb %al
andb $0x1, %al
movzbl %al, %eax
movq -0x38(%rbp), %rcx
subq -0x268(%rbp), %rcx
cmpq $0x40, %rcx
setb %cl
andb $0x1, %cl
movzbl %cl, %ecx
orl %ecx, %eax
cmpl $0x0, %eax
je 0x47e1
movq -0x8(%rbp), %rsi
addq $0x68, %rsi
leaq -0x270(%rbp), %rdi
callq 0x9410
jmp 0x475c
movq -0x48(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x268(%rbp), %rax
addq %rax, %rsi
callq 0x90b0
movq %rdx, -0x2e8(%rbp)
movq %rax, -0x2e0(%rbp)
jmp 0x4783
movq -0x2e8(%rbp), %rax
movq -0x2e0(%rbp), %rcx
movq %rcx, -0x280(%rbp)
movq %rax, -0x278(%rbp)
leaq -0x280(%rbp), %rdi
movl $0x1, %esi
callq 0x9440
leaq -0x270(%rbp), %rdi
callq 0x9490
jmp 0x4835
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x98(%rbp)
movl %eax, -0x9c(%rbp)
leaq -0x270(%rbp), %rdi
callq 0x9490
jmp 0x4a02
movq -0x48(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x268(%rbp), %rax
addq %rax, %rsi
callq 0x90b0
movq %rdx, -0x2f8(%rbp)
movq %rax, -0x2f0(%rbp)
jmp 0x4808
movq -0x2f8(%rbp), %rax
movq -0x2f0(%rbp), %rcx
movq %rcx, -0x290(%rbp)
movq %rax, -0x288(%rbp)
leaq -0x290(%rbp), %rdi
movl $0x1, %esi
callq 0x9440
jmp 0x4837
jmp 0x4839
movb -0x25a(%rbp), %al
addb $0x1, %al
movb %al, -0x25a(%rbp)
jmp 0x46c0
testb $0x1, -0x259(%rbp)
je 0x4874
movq -0x50(%rbp), %rdi
movzbl -0x21(%rbp), %esi
movq -0x218(%rbp), %rdx
leaq -0x1f0(%rbp), %rcx
callq 0x3fb0
jmp 0x4872
jmp 0x4874
movq -0x228(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0x8dd0
jmp 0x4889
leaq -0x138(%rbp), %rdi
leaq -0x220(%rbp), %rsi
callq 0x94c0
jmp 0x489e
movq -0x228(%rbp), %rax
movq %rax, -0x298(%rbp)
movq -0x298(%rbp), %rax
cmpq -0x238(%rbp), %rax
ja 0x4975
leaq -0x90(%rbp), %rdi
callq 0x8fe0
movb %al, -0x2f9(%rbp)
jmp 0x48d4
movb -0x2f9(%rbp), %al
movb %al, -0x299(%rbp)
movzbl -0x299(%rbp), %eax
movzbl -0x21(%rbp), %ecx
cmpl %ecx, %eax
jge 0x48f9
xorl %eax, %eax
movl %eax, -0x300(%rbp)
jmp 0x4934
movzbl -0x299(%rbp), %eax
movzbl -0x21(%rbp), %ecx
subl %ecx, %eax
movslq %eax, %rsi
leaq -0x168(%rbp), %rdi
callq 0x8c30
movq %rax, %rdi
callq 0x8fe0
movb %al, -0x301(%rbp)
jmp 0x4925
movb -0x301(%rbp), %al
movzbl %al, %eax
movl %eax, -0x300(%rbp)
movl -0x300(%rbp), %eax
movb %al, -0x29a(%rbp)
movzbl -0x29a(%rbp), %esi
movzbl -0x299(%rbp), %edx
leaq -0x138(%rbp), %rdi
callq 0x9230
jmp 0x495c
jmp 0x495e
movq -0x298(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x298(%rbp)
jmp 0x48ac
leaq -0x1f0(%rbp), %rdi
callq 0x8d50
jmp 0x4983
movq -0x238(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x228(%rbp)
jmp 0x4997
jmp 0x4999
movq -0x238(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x238(%rbp)
jmp 0x4460
movb -0x229(%rbp), %cl
movq -0x10(%rbp), %rax
andb $0x1, %cl
movb %cl, 0x29(%rax)
leaq -0x168(%rbp), %rdi
callq 0x9510
leaq -0x150(%rbp), %rdi
callq 0x9510
leaq -0x138(%rbp), %rdi
callq 0x9570
leaq -0x90(%rbp), %rdi
callq 0x8ce0
leaq -0x68(%rbp), %rdi
callq 0x9600
addq $0x310, %rsp            # imm = 0x310
popq %rbp
retq
leaq -0x168(%rbp), %rdi
callq 0x9510
leaq -0x150(%rbp), %rdi
callq 0x9510
leaq -0x138(%rbp), %rdi
callq 0x9570
leaq -0x90(%rbp), %rdi
callq 0x8ce0
leaq -0x68(%rbp), %rdi
callq 0x9600
movq -0x98(%rbp), %rdi
callq 0x3480
nopw (%rax,%rax)