// File: /workspace/github_cpp_makefile_star2_O3/AlgoLab[P]bwt-lcp-parallel/bwt_lcp.cpp
// Function: main
int main(int argc, char *argv[]) {
  // Initialization
  gzFile fp;
  kseq_t *seq;

  // Error if no file is given as input
  if (argc < 2 || argc > 3) {
    std::cerr << "Usage: " << argv[0] << " <in.fasta> [<nthreads>]" << std::endl;
    return 1;
  }

  if (argc == 3) {
    int nthreads = std::atoi(argv[2]);
    if (nthreads <= 0) {
      std::cerr << "Usage: " << argv[0] << " <in.fasta> [<nthreads>]" << std::endl;
      std::cerr << "nthreads cannot be less than 1. Given: " << nthreads << std::endl;
      return 1;
    }
    concurrency_level = static_cast<unsigned>(nthreads);
  } else {
    unsigned ncores = std::thread::hardware_concurrency();
    concurrency_level = ncores == 0 ? 1 : std::min(ncores, 4u);
  }
  std::cout << "Using " << concurrency_level << " threads." << std::endl;

  fp = gzopen(argv[1], "r");
  seq = kseq_init(fp);

  strnum_t read_num = 0;
  int maxl = 0;

  {
    // int is required by library kseq
    int l = 0;

    // Calculate the length of the longest read
    while ((l = kseq_read(seq)) >= 0) {
      ++read_num;
      if (l > maxl) maxl = l;
    }

    if (maxl > 254) {
      std::cerr << "Input reads are too long! Current = "
                << maxl << ", max = 254"
                << std::endl;
      kseq_destroy(seq);
      gzclose(fp);
      return 1;
    }
  }

  const strlen_t read_max_length = static_cast<strlen_t>(maxl);

  std::cout << "longest read length = " << static_cast<fuint_t>(read_max_length) << std::endl;
  std::cout << "number of reads = " << read_num << std::endl;

  const fnames_t S_tpl= template_generator("supportfile-S%.3d.tmp", 0, read_max_length+1);
  const fnames_t B_tpl= template_generator("supportfile-B%.3d.tmp", 0, read_max_length+1);
  const fname_t IXk_name("supportfile-IXk.tmp");

  std::cout << "Preparing arrays S_l..." << std::endl;
  occ_countv_t occv(read_max_length+1);
  {
    multi_enc_fasta_writer_t S(S_tpl);
    kseq_rewind(seq);
    gzrewind(fp);

    int l = 0;
    while ((l = kseq_read(seq)) >= 0) {
      const strlen_t len = static_cast<strlen_t>(l);
      for (strlen_t i = 0; i <= len; ++i) {
        const enc_nucl_t c = encode(seq->seq.s[len-i]);
        S.write(i, c);
        ++occv[i][c];
      }
      for (strlen_t i = len+1; i <= read_max_length; ++i) {
        S.write(i, ALPHSIZE-1);
        ++occv[i][ALPHSIZE-1];
      }
    }

  }

  kseq_destroy(seq);
  gzclose(fp);

  std::cout << "Computing partial BWT..." << std::endl;
  compute_partial_BWT(read_max_length, read_num, S_tpl, B_tpl);
  remove_files(S_tpl);

  std::cout << "Computing interleave and LCP..." << std::endl;
  compute_interleave_LCP(read_max_length, read_num, occv, B_tpl, IXk_name);

  std::cout << "Computing BWT..." << std::endl;
  compute_BWT(read_max_length, read_num, B_tpl, IXk_name);

  std::cout << "Done." << std::endl;

  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb8, %rsp
movq %rsi, %rbx
leal -0x4(%rdi), %eax
cmpl $-0x3, %eax
ja 0x4866
movq 0x97c9(%rip), %r14      # 0xdff0
leaq 0x491f(%rip), %rsi      # 0x914d
movl $0x7, %edx
movq %r14, %rdi
callq 0x2290
movq (%rbx), %rbx
testq %rbx, %rbx
je 0x4e91
movq %rbx, %rdi
callq 0x20d0
movq 0x979a(%rip), %rdi      # 0xdff0
movq %rbx, %rsi
movq %rax, %rdx
callq 0x2290
jmp 0x4ea9
cmpl $0x3, %edi
jne 0x48c0
movq 0x10(%rbx), %rdi
callq 0x2350
movl %eax, %ebp
testl %eax, %eax
jg 0x48da
movq 0x976f(%rip), %r14      # 0xdff0
leaq 0x48c5(%rip), %rsi      # 0x914d
movl $0x7, %edx
movq %r14, %rdi
callq 0x2290
movq (%rbx), %rbx
testq %rbx, %rbx
je 0x4f76
movq %rbx, %rdi
callq 0x20d0
movq 0x9740(%rip), %rdi      # 0xdff0
movq %rbx, %rsi
movq %rax, %rdx
callq 0x2290
jmp 0x4f8e
callq 0x22f0
cmpl $0x4, %eax
movl $0x4, %ecx
cmovbl %eax, %ecx
testl %eax, %eax
movl $0x1, %ebp
cmovnel %ecx, %ebp
movl %ebp, 0x9960(%rip)      # 0xe240
movq 0x96e9(%rip), %r14      # 0xdfd0
leaq 0x48a8(%rip), %rsi      # 0x9196
movl $0x6, %edx
movq %r14, %rdi
callq 0x2290
movl 0x993f(%rip), %esi      # 0xe240
movq %r14, %rdi
callq 0x2160
movq %rax, %r14
leaq 0x488a(%rip), %rsi      # 0x919d
movl $0x9, %edx
movq %rax, %rdi
callq 0x2290
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2180
movq 0x8(%rbx), %rdi
leaq 0x4d6a(%rip), %rsi      # 0x96bc
callq 0x2330
movq %rax, %r14
movl $0x1, %edi
movl $0x70, %esi
callq 0x2140
movq %rax, %r15
movl $0x1, %edi
movl $0x20, %esi
callq 0x2140
movq %rax, %rbx
movq %r14, 0x8(%rsp)
movq %r14, 0x18(%rax)
movl $0x4000, %edi           # imm = 0x4000
callq 0x22d0
movq %rax, (%rbx)
movq %rbx, 0x68(%r15)
movq %r15, %rdi
callq 0x50ec
xorl %ebx, %ebx
xorl %r12d, %r12d
testl %eax, %eax
js 0x49cb
incl %ebx
cmpl %r12d, %eax
cmovgl %eax, %r12d
movq %r15, %rdi
callq 0x50ec
testl %eax, %eax
jns 0x49a9
cmpl $0xff, %r12d
jae 0x4efb
movq 0x95fe(%rip), %r13      # 0xdfd0
leaq 0x47ff(%rip), %rsi      # 0x91d8
movl $0x16, %edx
movq %r13, %rdi
callq 0x2290
movl %r12d, %esi
movq %r13, %rdi
callq 0x2160
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2180
leaq 0x47cd(%rip), %rsi      # 0x91ef
movl $0x12, %edx
movq %r13, %rdi
callq 0x2290
movl %ebx, %esi
movq %r13, %rdi
callq 0x2160
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2180
leaq 0x40(%rsp), %r14
movq %r14, -0x10(%r14)
leaq 0x478f(%rip), %rsi      # 0x9202
leaq 0x479d(%rip), %rdx      # 0x9217
leaq 0x30(%rsp), %rdi
callq 0x711e
leal 0x1(%r12), %ebp
leaq 0x80(%rsp), %rdi
leaq 0x30(%rsp), %rsi
xorl %edx, %edx
movl %ebp, %ecx
callq 0x26cc
movq 0x30(%rsp), %rdi
cmpq %r14, %rdi
je 0x4ab6
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x2260
leaq 0x30(%rsp), %rdi
movq %r14, (%rdi)
leaq 0x4753(%rip), %rsi      # 0x9218
leaq 0x4761(%rip), %rdx      # 0x922d
callq 0x711e
leaq 0xa0(%rsp), %rdi
leaq 0x30(%rsp), %rsi
xorl %edx, %edx
movl %ebp, %ecx
callq 0x26cc
movq 0x30(%rsp), %rdi
cmpq %r14, %rdi
je 0x4afe
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x2260
leaq 0x20(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x4720(%rip), %rsi      # 0x922e
leaq 0x472c(%rip), %rdx      # 0x9241
leaq 0x10(%rsp), %rdi
callq 0x711e
movq 0x94aa(%rip), %r14      # 0xdfd0
leaq 0x4715(%rip), %rsi      # 0x9242
movl $0x17, %edx
movq %r14, %rdi
callq 0x2290
movq (%r14), %rax
addq -0x18(%rax), %r14
movq %r14, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq 0x9478(%rip), %rdi      # 0xdfd0
callq 0x2040
movq %rax, %rdi
callq 0x2180
movl %ebp, %esi
leaq 0x68(%rsp), %rdi
leaq 0x30(%rsp), %rdx
callq 0x6ba2
movl %ebx, 0x4(%rsp)
leaq 0x450b(%rip), %rdx      # 0x908c
leaq 0x30(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0x6c70
movq 0x68(%r15), %rax
movq $0x0, 0x8(%rax)
xorl %ecx, %ecx
movl %ecx, 0x10(%rax)
movl %ecx, 0x60(%r15)
movq 0x8(%rsp), %rdi
callq 0x2280
leaq 0x3(%rsp), %rbp
movq %r12, 0x98(%rsp)
movq %r15, %rdi
callq 0x50ec
movl %eax, %r13d
testl %eax, %eax
js 0x4c89
movzbl %r13b, %ebx
xorl %eax, %eax
xorl %r12d, %r12d
movl %ebx, %ecx
subl %eax, %ecx
movq 0x40(%r15), %rax
movslq %ecx, %rcx
movsbl (%rax,%rcx), %edi
callq 0x8cc0
movl %eax, %r14d
movb %al, 0x3(%rsp)
movzbl %r12b, %r12d
movl %r12d, %edi
shll $0x4, %edi
addq 0x50(%rsp), %rdi
movq %rbp, %rsi
callq 0x597e
leaq (%r12,%r12,2), %rax
shll $0x4, %eax
addq 0x68(%rsp), %rax
movzbl %r14b, %ecx
incq (%rax,%rcx,8)
incb %r12b
movzbl %r12b, %eax
cmpb %r13b, %al
jbe 0x4bdb
movl %r13d, %eax
incb %al
movzbl %al, %eax
movq 0x98(%rsp), %r12
cmpl %eax, %r12d
jb 0x4bbf
leal 0x2(%r13), %ebx
leal -0x1(%rbx), %eax
movb $0x5, 0x3(%rsp)
movzbl %al, %r14d
movl %r14d, %edi
shll $0x4, %edi
addq 0x50(%rsp), %rdi
movq %rbp, %rsi
callq 0x597e
movq 0x68(%rsp), %rax
leaq (%r14,%r14,2), %rcx
shll $0x4, %ecx
incq 0x28(%rax,%rcx)
movzbl %bl, %eax
incb %bl
cmpl %eax, %r12d
jae 0x4c4a
jmp 0x4bbf
leaq 0x50(%rsp), %rdi
callq 0x6e4e
leaq 0x30(%rsp), %rdi
callq 0x578c
movq %r15, %rdi
callq 0x5455
movq 0x8(%rsp), %rdi
leaq 0x20(%rsp), %r15
callq 0x2390
movl 0x4(%rsp), %ebx
movq 0x9311(%rip), %r14      # 0xdfd0
leaq 0x4594(%rip), %rsi      # 0x925a
movl $0x18, %edx
movq %r14, %rdi
callq 0x2290
movq (%r14), %rax
addq -0x18(%rax), %r14
movq %r14, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq 0x92df(%rip), %rdi      # 0xdfd0
callq 0x2040
movq %rax, %rdi
callq 0x2180
movzbl %r12b, %ebp
leaq 0x80(%rsp), %rdx
leaq 0xa0(%rsp), %rcx
movl %ebp, %edi
movl %ebx, %esi
callq 0x2837
movq 0x80(%rsp), %rbx
movq 0x88(%rsp), %r14
cmpq %r14, %rbx
je 0x4d3e
movq (%rbx), %rdi
callq 0x2400
addq $0x20, %rbx
jmp 0x4d2b
movq 0x928b(%rip), %r14      # 0xdfd0
leaq 0x4527(%rip), %rsi      # 0x9273
movl $0x1f, %edx
movq %r14, %rdi
callq 0x2290
movl 0x4(%rsp), %ebx
movq (%r14), %rax
addq -0x18(%rax), %r14
movq %r14, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq 0x9255(%rip), %rdi      # 0xdfd0
callq 0x2040
movq %rax, %rdi
callq 0x2180
leaq 0x68(%rsp), %rdx
leaq 0xa0(%rsp), %rcx
leaq 0x10(%rsp), %r8
movl %ebp, %edi
movl %ebx, %esi
callq 0x378a
movq 0x9226(%rip), %r14      # 0xdfd0
leaq 0x44e2(%rip), %rsi      # 0x9293
movl $0x10, %edx
movq %r14, %rdi
callq 0x2290
movq (%r14), %rax
addq -0x18(%rax), %r14
movq %r14, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq 0x91f4(%rip), %rdi      # 0xdfd0
callq 0x2040
movq %rax, %rdi
callq 0x2180
leaq 0xa0(%rsp), %rdx
leaq 0x10(%rsp), %rcx
movl %ebp, %edi
movl %ebx, %esi
callq 0x4631
movq 0x91ca(%rip), %rbx      # 0xdfd0
leaq 0x4497(%rip), %rsi      # 0x92a4
movl $0x5, %edx
movq %rbx, %rdi
callq 0x2290
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq 0x9198(%rip), %rdi      # 0xdfd0
callq 0x2040
movq %rax, %rdi
callq 0x2180
movq 0x68(%rsp), %rdi
testq %rdi, %rdi
je 0x4e5c
movq 0x78(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
movq 0x10(%rsp), %rdi
cmpq %r15, %rdi
je 0x4e73
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2260
leaq 0xa0(%rsp), %rdi
callq 0x578c
leaq 0x80(%rsp), %rdi
callq 0x578c
xorl %eax, %eax
jmp 0x4ee9
movq (%r14), %rax
movq -0x18(%rax), %rax
leaq (%r14,%rax), %rdi
movl 0x20(%r14,%rax), %esi
orl $0x1, %esi
callq 0x23a0
leaq 0x42a5(%rip), %rsi      # 0x9155
movl $0x18, %edx
movq %r14, %rdi
callq 0x2290
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2180
movl $0x1, %eax
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x90ee(%rip), %rbx      # 0xdff0
leaq 0x429e(%rip), %rsi      # 0x91a7
movl $0x24, %edx
movq %rbx, %rdi
callq 0x2290
movq %rbx, %rdi
movl %r12d, %esi
callq 0x23c0
movq %rax, %rbx
leaq 0x42a1(%rip), %rsi      # 0x91cc
movl $0xb, %edx
movq %rax, %rdi
callq 0x2290
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2180
movq %r15, %rdi
callq 0x5455
movq 0x8(%rsp), %rdi
callq 0x2390
jmp 0x4ee4
movq (%r14), %rax
movq -0x18(%rax), %rax
leaq (%r14,%rax), %rdi
movl 0x20(%r14,%rax), %esi
orl $0x1, %esi
callq 0x23a0
leaq 0x41c0(%rip), %rsi      # 0x9155
movl $0x18, %edx
movq %r14, %rdi
callq 0x2290
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2180
leaq 0x419e(%rip), %rsi      # 0x916e
movl $0x27, %edx
movq %r14, %rdi
callq 0x2290
movq %r14, %rdi
movl %ebp, %esi
callq 0x23c0
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq %rbx, %rdi
jmp 0x4ed7
jmp 0x5080
movq %rax, %rbx
jmp 0x5097
jmp 0x506d
movq %rax, %rbx
jmp 0x50ca
movq %rax, %rbx
movq 0x30(%rsp), %rdi
cmpq %r14, %rdi
je 0x50d7
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x2260
jmp 0x50d7
movq %rax, %rbx
jmp 0x50d7
movq %rax, %rbx
movq 0x30(%rsp), %rdi
cmpq %r14, %rdi
je 0x50e4
movq 0x40(%rsp), %rsi
incq %rsi
callq 0x2260
jmp 0x50e4
movq %rax, %rbx
jmp 0x50e4
movq %rax, %rbx
leaq 0x20(%rsp), %r15
jmp 0x50b3
movq %rax, %rbx
jmp 0x509c
jmp 0x5080
jmp 0x5080
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x6e4e
leaq 0x30(%rsp), %rdi
callq 0x578c
leaq 0x20(%rsp), %r15
movq 0x68(%rsp), %rdi
testq %rdi, %rdi
je 0x50b3
movq 0x78(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
movq 0x10(%rsp), %rdi
cmpq %r15, %rdi
je 0x50ca
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2260
leaq 0xa0(%rsp), %rdi
callq 0x578c
leaq 0x80(%rsp), %rdi
callq 0x578c
movq %rbx, %rdi
callq 0x23d0