// File: /workspace/github_cpp_makefile_star2_O1/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 $0xc8, %rsp
movq %rsi, %rbx
leal -0x4(%rdi), %eax
cmpl $-0x3, %eax
ja 0x4809
movq 0x981f(%rip), %r14      # 0xdff0
leaq 0x4935(%rip), %rsi      # 0x910d
movl $0x7, %edx
movq %r14, %rdi
callq 0x2290
movq (%rbx), %rbx
testq %rbx, %rbx
je 0x4857
movq %rbx, %rdi
callq 0x20d0
movq 0x97f4(%rip), %rdi      # 0xdff0
movq %rbx, %rsi
movq %rax, %rdx
callq 0x2290
jmp 0x486f
cmpl $0x3, %edi
jne 0x482f
movq 0x10(%rbx), %rdi
callq 0x2350
movl %eax, %ebp
testl %eax, %eax
jle 0x48b5
movl %ebp, 0x9a19(%rip)      # 0xe240
xorl %r14d, %r14d
jmp 0x4995
callq 0x22f0
cmpl $0x4, %eax
movl $0x4, %ecx
cmovbl %eax, %ecx
testl %eax, %eax
movl $0x1, %eax
cmovnel %ecx, %eax
movl %eax, 0x99f1(%rip)      # 0xe240
xorl %r14d, %r14d
jmp 0x499d
movq (%r14), %rax
movq -0x18(%rax), %rax
leaq (%r14,%rax), %rdi
movl 0x20(%r14,%rax), %esi
orl $0x1, %esi
callq 0x23a0
leaq 0x489f(%rip), %rsi      # 0x9115
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, %r14d
jmp 0x4fe4
movq 0x9734(%rip), %r14      # 0xdff0
leaq 0x484a(%rip), %rsi      # 0x910d
movl $0x7, %edx
movq %r14, %rdi
callq 0x2290
movq (%rbx), %r15
testq %r15, %r15
je 0x48f4
movq %r15, %rdi
callq 0x20d0
movq 0x9709(%rip), %rdi      # 0xdff0
movq %r15, %rsi
movq %rax, %rdx
callq 0x2290
jmp 0x490c
movq (%r14), %rax
movq -0x18(%rax), %rax
leaq (%r14,%rax), %rdi
movl 0x20(%r14,%rax), %esi
orl $0x1, %esi
callq 0x23a0
leaq 0x4802(%rip), %rsi      # 0x9115
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 0x47e0(%rip), %rsi      # 0x912e
movl $0x27, %edx
movq %r14, %rdi
callq 0x2290
movq %r14, %rdi
movl %ebp, %esi
callq 0x23c0
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
movl $0x1, %r14d
testl %ebp, %ebp
jle 0x4fe4
movq 0x962c(%rip), %r15      # 0xdfd0
leaq 0x47ab(%rip), %rsi      # 0x9156
movl $0x6, %edx
movq %r15, %rdi
callq 0x2290
movl 0x9882(%rip), %esi      # 0xe240
movq %r15, %rdi
callq 0x2160
movq %rax, %r15
leaq 0x478d(%rip), %rsi      # 0x915d
movl $0x9, %edx
movq %rax, %rdi
callq 0x2290
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2220
movsbl %al, %esi
movq %r15, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2180
movq 0x8(%rbx), %rdi
leaq 0x4c6d(%rip), %rsi      # 0x967c
callq 0x2330
movq %rax, %r15
movl $0x1, %edi
movl $0x70, %esi
callq 0x2140
movq %rax, %r12
movl $0x1, %edi
movl $0x20, %esi
callq 0x2140
movq %rax, %rbx
movq %r15, 0x18(%rax)
movl $0x4000, %edi           # imm = 0x4000
callq 0x22d0
movq %rax, (%rbx)
movq %rbx, 0x68(%r12)
movq %r12, %rdi
callq 0x50e5
testl %eax, %eax
js 0x4a76
xorl %ebx, %ebx
xorl %ebp, %ebp
incl %ebx
cmpl %ebp, %eax
cmovgl %eax, %ebp
movq %r12, %rdi
callq 0x50e5
testl %eax, %eax
jns 0x4a61
jmp 0x4a7a
xorl %ebp, %ebp
xorl %ebx, %ebx
cmpl $0xff, %ebp
jl 0x4afb
movq 0x9567(%rip), %r14      # 0xdff0
leaq 0x46d7(%rip), %rsi      # 0x9167
movl $0x24, %edx
movq %r14, %rdi
callq 0x2290
movq %r14, %rdi
movl %ebp, %esi
callq 0x23c0
movq %rax, %r14
leaq 0x46db(%rip), %rsi      # 0x918c
movl $0xb, %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 %r12, %rdi
callq 0x546c
movq %r15, %rdi
callq 0x2390
movl $0x1, %r14d
cmpl $0xfe, %ebp
jg 0x4fe4
movq %r15, 0x38(%rsp)
movq 0x94bd(%rip), %r15      # 0xdfd0
leaq 0x467e(%rip), %rsi      # 0x9198
movl $0x16, %edx
movq %r15, %rdi
callq 0x2290
movzbl %bpl, %r13d
movq %r15, %rdi
movq %r13, %rsi
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 0x4648(%rip), %rsi      # 0x91af
movl $0x12, %edx
movq %r15, %rdi
callq 0x2290
movl %ebx, 0x10(%rsp)
movl %ebx, %esi
movq %r15, %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 0x58(%rsp), %r14
movq %r14, -0x10(%r14)
leaq 0x4606(%rip), %rsi      # 0x91c2
leaq 0x4614(%rip), %rdx      # 0x91d7
leaq 0x48(%rsp), %rdi
callq 0x6ed6
movq %r13, 0x40(%rsp)
incl %r13d
leaq 0x98(%rsp), %rdi
leaq 0x48(%rsp), %rsi
xorl %edx, %edx
movl %r13d, %ecx
callq 0x268c
movq 0x48(%rsp), %rdi
cmpq %r14, %rdi
je 0x4c03
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x2260
leaq 0x48(%rsp), %rdi
movq %r14, (%rdi)
leaq 0x45c6(%rip), %rsi      # 0x91d8
leaq 0x45d4(%rip), %rdx      # 0x91ed
callq 0x6ed6
leaq 0xb0(%rsp), %rdi
leaq 0x48(%rsp), %rsi
xorl %edx, %edx
movl %r13d, %ecx
callq 0x268c
movq 0x48(%rsp), %rdi
cmpq %r14, %rdi
je 0x4c4c
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x2260
leaq 0x28(%rsp), %rax
movq %rax, -0x10(%rax)
leaq 0x4592(%rip), %rsi      # 0x91ee
leaq 0x459e(%rip), %rdx      # 0x9201
leaq 0x18(%rsp), %rdi
callq 0x6ed6
movq 0x935c(%rip), %r14      # 0xdfd0
leaq 0x4587(%rip), %rsi      # 0x9202
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 0x932a(%rip), %rdi      # 0xdfd0
callq 0x2040
movq %rax, %rdi
callq 0x2180
movl %r13d, %esi
leaq 0x80(%rsp), %rdi
leaq 0x48(%rsp), %rdx
callq 0x695e
leaq 0x437d(%rip), %rdx      # 0x904c
leaq 0x48(%rsp), %rdi
leaq 0x98(%rsp), %rsi
callq 0x6a1e
movq 0x38(%rsp), %rdi
movq 0x68(%r12), %rax
movq $0x0, 0x8(%rax)
xorl %ecx, %ecx
movl %ecx, 0x10(%rax)
movl %ecx, 0x60(%r12)
callq 0x2280
leaq 0xf(%rsp), %r13
movl %ebp, 0x14(%rsp)
movq %r12, %rdi
callq 0x50e5
movl %eax, %r15d
testl %eax, %eax
js 0x4dd4
movzbl %r15b, %ebx
xorl %eax, %eax
xorl %ebp, %ebp
movl %ebx, %ecx
subl %eax, %ecx
movq 0x40(%r12), %rax
movslq %ecx, %rcx
movsbl (%rax,%rcx), %edi
callq 0x8acc
movl %eax, %r14d
movb %al, 0xf(%rsp)
movzbl %bpl, %ebp
movl %ebp, %edi
shll $0x4, %edi
addq 0x68(%rsp), %rdi
movq %r13, %rsi
callq 0x5994
leaq (,%rbp,2), %rax
addq %rbp, %rax
shll $0x4, %eax
addq 0x80(%rsp), %rax
movzbl %r14b, %ecx
incq (%rax,%rcx,8)
incb %bpl
movzbl %bpl, %eax
cmpb %r15b, %al
jbe 0x4d26
incb %r15b
movzbl %r15b, %eax
cmpl %eax, 0x40(%rsp)
movl 0x14(%rsp), %ebp
jb 0x4d0b
movb $0x5, 0xf(%rsp)
movzbl %r15b, %r15d
movl %r15d, %edi
shll $0x4, %edi
addq 0x68(%rsp), %rdi
movq %r13, %rsi
callq 0x5994
movq 0x80(%rsp), %rax
leaq (%r15,%r15,2), %rcx
shll $0x4, %ecx
incq 0x28(%rax,%rcx)
incb %r15b
cmpb %bpl, %r15b
jbe 0x4d97
jmp 0x4d0b
leaq 0x68(%rsp), %rdi
callq 0x6bf6
leaq 0x48(%rsp), %rdi
callq 0x57a4
movq %r12, %rdi
callq 0x546c
movq 0x38(%rsp), %rdi
leaq 0x28(%rsp), %r15
callq 0x2390
movl 0x10(%rsp), %ebp
movq 0x40(%rsp), %r12
movq 0x91c1(%rip), %r14      # 0xdfd0
leaq 0x4404(%rip), %rsi      # 0x921a
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 0x918f(%rip), %rdi      # 0xdfd0
callq 0x2040
movq %rax, %rdi
callq 0x2180
leaq 0x98(%rsp), %rdx
leaq 0xb0(%rsp), %rcx
movl %r12d, %edi
movl %ebp, %esi
callq 0x27e5
movq 0x98(%rsp), %rbx
movq 0xa0(%rsp), %r14
cmpq %r14, %rbx
je 0x4e8b
movq (%rbx), %rdi
callq 0x2400
addq $0x20, %rbx
jmp 0x4e78
movq 0x913e(%rip), %r14      # 0xdfd0
leaq 0x439a(%rip), %rsi      # 0x9233
movl $0x1f, %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 0x910c(%rip), %rdi      # 0xdfd0
callq 0x2040
movq %rax, %rdi
callq 0x2180
leaq 0x80(%rsp), %rdx
leaq 0xb0(%rsp), %rcx
leaq 0x18(%rsp), %r8
movl %r12d, %edi
movl %ebp, %esi
callq 0x374b
movq 0x90d9(%rip), %r14      # 0xdfd0
leaq 0x4355(%rip), %rsi      # 0x9253
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 0x90a7(%rip), %rdi      # 0xdfd0
callq 0x2040
movq %rax, %rdi
callq 0x2180
leaq 0xb0(%rsp), %rdx
leaq 0x18(%rsp), %rcx
movl %r12d, %edi
movl %ebp, %esi
callq 0x45df
movq 0x907c(%rip), %rbx      # 0xdfd0
leaq 0x4309(%rip), %rsi      # 0x9264
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 0x904a(%rip), %rdi      # 0xdfd0
callq 0x2040
movq %rax, %rdi
callq 0x2180
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x4fb0
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
movq 0x18(%rsp), %rdi
cmpq %r15, %rdi
je 0x4fc7
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x2260
leaq 0xb0(%rsp), %rdi
callq 0x57a4
leaq 0x98(%rsp), %rdi
callq 0x57a4
xorl %r14d, %r14d
movl %r14d, %eax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x5073
movq %rax, %rbx
jmp 0x508a
jmp 0x5060
movq %rax, %rbx
jmp 0x50c3
movq %rax, %rbx
movq 0x48(%rsp), %rdi
cmpq %r14, %rdi
je 0x50d0
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x2260
jmp 0x50d0
movq %rax, %rbx
jmp 0x50d0
movq %rax, %rbx
movq 0x48(%rsp), %rdi
cmpq %r14, %rdi
je 0x50dd
movq 0x58(%rsp), %rsi
incq %rsi
callq 0x2260
jmp 0x50dd
movq %rax, %rbx
jmp 0x50dd
movq %rax, %rbx
leaq 0x28(%rsp), %r15
jmp 0x50ac
movq %rax, %rbx
jmp 0x508f
jmp 0x5073
jmp 0x5073
movq %rax, %rbx
leaq 0x68(%rsp), %rdi
callq 0x6bf6
leaq 0x48(%rsp), %rdi
callq 0x57a4
leaq 0x28(%rsp), %r15
movq 0x80(%rsp), %rdi
testq %rdi, %rdi
je 0x50ac
movq 0x90(%rsp), %rsi
subq %rdi, %rsi
callq 0x2260
movq 0x18(%rsp), %rdi
cmpq %r15, %rdi
je 0x50c3
movq 0x28(%rsp), %rsi
incq %rsi
callq 0x2260
leaq 0xb0(%rsp), %rdi
callq 0x57a4
leaq 0x98(%rsp), %rdi
callq 0x57a4
movq %rbx, %rdi
callq 0x23d0