// File: /workspace/github_cpp_makefile_star2_O3/jaudoux[P]countTags/src/countTags.cpp
// Function: main
int main (int argc, char *argv[]) {

  // Config vars
  const char * tags_file;
  const char * seq_file;
  uint32_t tag_length = 22;
  bool stranded = false;
  bool normalize = false;
  bool print_tag_names = false;
  uint32_t nb_tags = 0;
  uint32_t max_reads = UINT32_MAX;
  int nb_threads = 1;
  uint32_t nb_samples;
  uint32_t i;
  uint32_t read_id;

  char * seq;
  std::string tag_name;
  uint32_t seq_length;
  uint64_t tag;
  uint64_t valrev,valfwd;
  uint64_t nb_factors;
  int64_t last;
  std::unordered_map<uint64_t,double*>  tags_counts;
  std::unordered_map<uint64_t,std::vector<std::string>> tags_names;
  std::unordered_map<uint64_t,double*>::iterator it_counts;
  std::vector<uint64_t> nb_factors_by_sample;

  // File vars
  std::string gzip_pipe = "gunzip -fc ";
  std::string cat_pipe = "cat ";
  std::string tmp;
  FILE * file;
  char * line = NULL;
  size_t len = 0;
  ssize_t read;
  uint32_t line_id = 0;

  /**********************************
   *
   *        Parsing options
   *
   *********************************/
  argc-=(argc>0); argv+=(argc>0); // skip program name argv[0] if present
  option::Stats  stats(usage, argc, argv);
  option::Option options[stats.options_max], buffer[stats.buffer_max];
  option::Parser parse(usage, argc, argv, options, buffer);

  if (parse.error())
    return 1;

  if (options[HELP] || argc == 0) {
    option::printUsage(std::cout, usage);
    return 0;
  }

  // TODO we should check the length to choose the appropriate
  // integer size to use
  if (options[PROBE_LENGTH]) {
    tag_length = atoi(options[PROBE_LENGTH].arg);
  }

  if (options[MAX_READS]) {
    max_reads = atoi(options[MAX_READS].arg);
  }

  //if (options[NB_THREADS]) {
  //  nb_threads = atoi(options[NB_THREADS].arg);
  //}

  if (options[STRANDED]) {
    stranded = true;
  }

  if (options[NORMALIZE]) {
    normalize = true;
  }

  if (options[TAG_NAMES]) {
    print_tag_names = true;
  }

  if(parse.nonOptionsCount() < 2) {
    option::printUsage(std::cout, usage);
    return 0;
  }

  tags_file = parse.nonOption(0);
  nb_samples = parse.nonOptionsCount() - 1;

  /**********************************
   *
   *   Create tags counting table
   *
   *********************************/
  file = popen(tmp.append(cat_pipe).append(tags_file).c_str(),"r");
  line_id = 0;

  std::cerr << "Counting k-mers" << std::endl;
  // Create hash table of k-mer counts
  line_id = 0;
  nb_tags = 0;
  while ((read = getline(&line, &len, file)) != -1) {
    if(line_id % 2 == 0) {
      tag_name = line;
      tag_name.pop_back(); // remove new_line char
      tag_name.erase(0,1); // remove the fasta ">" prefix
    }
    if(line_id % 2 == 1) {
      tag = DNAtoInt(line,tag_length,stranded);
      tags_counts[tag] = new double[nb_samples]();
      tags_names[tag].push_back(tag_name);
      nb_tags++;
    }
    line_id++;
  }
  fclose(file);
  if (line)
    free(line);

  std::cerr << "Finished indexing tags" << std::endl;


  /**********************************
   *
   *            First pass
   *
   *********************************/
//#pragma omp parallel num_threads(nb_threads)
  for (int s = 0; s < nb_samples; ++s) {
    std::cerr << "Counting tags for file: " << parse.nonOption(s+1) << "\n";

    line = NULL;
    len = 0;
    line_id = 0;
    tmp = "";
    file = popen(tmp.append(gzip_pipe).append(parse.nonOption(s+1)).c_str(),"r");
    nb_factors = 0;

    while ((read = getline(&line, &len, file)) != -1) {
      // If this line is a sequence
      if(line_id % 4 == 1) {
        read_id = ((int)((double)line_id*0.25) + 1);
        if(read_id >= max_reads) {
          break;
        }
        // Print a user-friendly output on STDERR every each XXXX reads processed
        if(read_id % MILLION == 0) {
          std::cerr << (int)((double)line_id*0.25) + 1 << " reads parsed" << std::endl;
        }
        // set seq to line
        seq = line;
        seq_length = strlen(seq) - 1; // Minus 1 because we have a new line

        // Skip the sequence if the read length is < to the tag_length
        if(seq_length < tag_length)
          continue;

        nb_tags = seq_length - tag_length + 1;
        nb_factors += nb_tags;

        //uint64_t valrev,valfwd;
        last = -3;

        for(i = 0; i < nb_tags; i++) {
          it_counts = tags_counts.find(valns(i,seq,tag_length,&last,&valfwd,&valrev,stranded));
          if(it_counts != tags_counts.end()) {
            it_counts->second[s]++;
          }
        }
      }
      line_id++;
    }

    nb_factors_by_sample.push_back(nb_factors);

    if(normalize && nb_factors > 0) {
      std::cerr << "Normalize counts" << std::endl;
      for (it_counts=tags_counts.begin(); it_counts!=tags_counts.end(); ++it_counts) {
        // TODO We should take into accout the error rate...
        if(it_counts->second[s] > 0)
          it_counts->second[s] = it_counts->second[s] * MILLION / nb_factors;
      }
    }

    // Close file and clear line buffer
    fclose(file);
    if (line)
      free(line);
  }

  /****
   * PRINT THE RESULTS
   */
  // First print headers
  std::cout << "tag";
  if (print_tag_names)
    std::cout << "\ttag_names";
  for (int s = 0; s < nb_samples; ++s) {
    std::cout << "\t" << parse.nonOption(s+1);
  }
  std::cout << "\n";
  char *tag_seq = new char[tag_length];
  for (it_counts=tags_counts.begin(); it_counts!=tags_counts.end(); ++it_counts) {
    intToDNA(it_counts->first,tag_length,tag_seq);
    std::cout << tag_seq;
    if(print_tag_names) {
      std::cout << "\t" << join(tags_names[it_counts->first],",");
    }
    for (int s = 0; s < nb_samples; ++s) {
      std::cout << "\t" << it_counts->second[s];
    }
    std::cout << std::endl;
  }

  std::cout << "total_factors";
  if (print_tag_names)
    std::cout << "\t*";
  for (int s = 0; s < nb_samples; ++s) {
    std::cout << "\t" << nb_factors_by_sample[s];
  }
  std::cout << std::endl;

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x208, %rsp            # imm = 0x208
movq %rsi, %r14
movl %edi, %ebx
leaq -0x78(%rbp), %r15
movq %r15, -0x10(%r15)
xorl %eax, %eax
movq %rax, -0x8(%r15)
movb $0x0, (%r15)
leaq -0x1c0(%rbp), %rcx
movq %rcx, -0x30(%rcx)
movl $0x1, %edx
movq %rdx, -0x28(%rcx)
xorpd %xmm0, %xmm0
movupd %xmm0, -0x20(%rcx)
movl $0x3f800000, %esi       # imm = 0x3F800000
movl %esi, -0x10(%rcx)
movupd %xmm0, -0x8(%rcx)
leaq -0x1f8(%rbp), %rcx
movq %rcx, -0x30(%rcx)
movq %rdx, -0x28(%rcx)
movupd %xmm0, -0x20(%rcx)
movl %esi, -0x10(%rcx)
movupd %xmm0, -0x8(%rcx)
movq %rax, -0xc0(%rbp)
movapd %xmm0, -0xd0(%rbp)
leaq -0x168(%rbp), %rax
movq %rax, -0x10(%rax)
leaq 0x49b1(%rip), %rsi      # 0x70c0
leaq 0x49b5(%rip), %rdx      # 0x70cb
leaq -0x178(%rbp), %rdi
callq 0x4080
leaq -0x148(%rbp), %rax
movq %rax, -0x10(%rax)
leaq 0x4998(%rip), %rsi      # 0x70cc
leaq 0x4995(%rip), %rdx      # 0x70d0
leaq -0x158(%rbp), %rdi
callq 0x4080
leaq -0xf8(%rbp), %rcx
movq %rcx, -0x10(%rcx)
xorl %eax, %eax
movq %rax, -0x8(%rcx)
movb $0x0, (%rcx)
movq %rax, -0x48(%rbp)
movq %rax, -0xa8(%rbp)
xorl %eax, %eax
testl %ebx, %ebx
setg %al
subl %eax, %ebx
xorl %eax, %eax
testl %ebx, %ebx
setg %al
leaq (%r14,%rax,8), %r15
leaq 0x741f(%rip), %rsi      # 0x9ba0
leaq -0x118(%rbp), %rdi
movl %ebx, %edx
movq %r15, %rcx
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0x365e
movq %rsp, -0x198(%rbp)
movl -0x114(%rbp), %ecx
movq %rsp, %r14
movq %rcx, %rax
shlq $0x4, %rax
leaq (%rax,%rax,2), %rax
subq %rax, %r14
movq %r14, %rsp
testq %rcx, %rcx
je 0x27ee
leaq 0x10(%r14), %rcx
leaq 0x1(%r14), %rdx
xorl %esi, %esi
xorpd %xmm0, %xmm0
leaq (%rdx,%rsi), %rdi
movupd %xmm0, 0xc(%rcx,%rsi)
movapd %xmm0, (%rcx,%rsi)
movq %rdi, -0x8(%rcx,%rsi)
movq %rdi, -0x10(%rcx,%rsi)
addq $0x30, %rsi
cmpq %rsi, %rax
jne 0x27cc
movl -0x118(%rbp), %ecx
movq %rsp, %r9
movq %rcx, %rax
shlq $0x4, %rax
leaq (%rax,%rax,2), %rax
subq %rax, %r9
movq %r9, %rsp
testq %rcx, %rcx
je 0x283d
leaq 0x10(%r9), %rcx
leaq 0x1(%r9), %rdx
xorl %esi, %esi
xorpd %xmm0, %xmm0
leaq (%rdx,%rsi), %rdi
movupd %xmm0, 0xc(%rcx,%rsi)
movapd %xmm0, (%rcx,%rsi)
movq %rdi, -0x8(%rcx,%rsi)
movq %rdi, -0x10(%rcx,%rsi)
addq $0x30, %rsi
cmpq %rsi, %rax
jne 0x281b
subq $0x8, %rsp
xorl %eax, %eax
leaq 0x7356(%rip), %rsi      # 0x9ba0
leaq -0x190(%rbp), %rdi
movl %ebx, %edx
movq %r15, %rcx
movq %r14, %r8
pushq $-0x1
pushq %rax
pushq %rax
callq 0x36ca
addq $0x20, %rsp
movl $0x1, %r15d
cmpb $0x0, -0x180(%rbp)
jne 0x3481
testl %ebx, %ebx
je 0x2899
cmpq $0x0, 0x40(%r14)
jne 0x2899
cmpq $0x0, 0x70(%r14)
je 0x28d3
movq 0x80(%r14), %rdi
callq 0x22a0
jmp 0x28d8
leaq 0x74d0(%rip), %rax      # 0x9d70
leaq -0x138(%rbp), %rdi
movq %rax, (%rdi)
movq 0x7717(%rip), %rax      # 0x9fc8
movq %rax, 0x8(%rdi)
leaq 0x72e4(%rip), %rsi      # 0x9ba0
movl $0x50, %edx
movl $0x32, %ecx
movl $0x4b, %r8d
callq 0x415c
jmp 0x2941
movl $0x16, %eax
movq %rax, -0x38(%rbp)
cmpq $0x0, 0xd0(%r14)
je 0x28f7
movq 0xe0(%r14), %rdi
callq 0x22a0
movl %eax, -0x54(%rbp)
jmp 0x28fe
movl $0xffffffff, -0x54(%rbp) # imm = 0xFFFFFFFF
movl -0x18c(%rbp), %eax
cmpl $0x1, %eax
jg 0x2949
leaq 0x7460(%rip), %rax      # 0x9d70
leaq -0x138(%rbp), %rdi
movq %rax, (%rdi)
movq 0x76a7(%rip), %rax      # 0x9fc8
movq %rax, 0x8(%rdi)
leaq 0x7274(%rip), %rsi      # 0x9ba0
movl $0x50, %edx
movl $0x32, %ecx
movl $0x4b, %r8d
callq 0x415c
xorl %r15d, %r15d
jmp 0x3481
movl %eax, %r15d
movq 0xa0(%r14), %rax
movq %rax, -0xe0(%rbp)
movq 0x130(%r14), %rax
movq %rax, -0x1a0(%rbp)
movq 0x160(%r14), %rax
movq %rax, -0x90(%rbp)
movq -0x188(%rbp), %rax
movq (%rax), %rbx
movq -0x158(%rbp), %rsi
movq -0x150(%rbp), %rdx
leaq -0x108(%rbp), %rdi
callq 0x2080
movq %rax, %rdi
movq %rbx, %rsi
callq 0x2330
movq (%rax), %rdi
leaq 0x4722(%rip), %rsi      # 0x70d1
callq 0x2070
movq %rax, -0x30(%rbp)
movq 0x7631(%rip), %rbx      # 0x9ff0
leaq 0x470d(%rip), %rsi      # 0x70d3
movl $0xf, %edx
movq %rbx, %rdi
callq 0x21c0
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x2160
movsbl %al, %esi
movq 0x75ff(%rip), %rdi      # 0x9ff0
callq 0x2040
movq %rax, %rdi
callq 0x2110
decl %r15d
movq -0x38(%rbp), %rdx
movl %edx, %eax
movq %rax, -0x68(%rbp)
leal (%rdx,%rdx), %ecx
movq $-0x1, %rax
movq $-0x1, %rsi
movq %rcx, -0x98(%rbp)
shlq %cl, %rsi
cmpl $0x20, %edx
notq %rsi
cmoveq %rax, %rsi
movq %rsi, -0xd8(%rbp)
movl %r15d, -0x3c(%rbp)
movl %r15d, %eax
movq %rax, -0x60(%rbp)
leaq (,%rax,8), %r13
xorl %r14d, %r14d
leaq -0x88(%rbp), %r12
leaq -0x48(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
movq -0x30(%rbp), %rdx
callq 0x2200
cmpq $-0x1, %rax
je 0x2bda
movq -0x48(%rbp), %r15
testb $0x1, %r14b
jne 0x2ab7
movq -0x80(%rbp), %rbx
movq %r15, %rdi
callq 0x20c0
movq %r12, %rdi
xorl %esi, %esi
movq %rbx, %rdx
movq %r15, %rcx
movq %rax, %r8
callq 0x2290
movq %r12, %rdi
callq 0x21f0
movl $0x1, %edx
movq %r12, %rdi
xorl %esi, %esi
callq 0x2050
jmp 0x2bd2
cmpl $0x0, -0x38(%rbp)
je 0x2b7d
xorl %ecx, %ecx
xorl %eax, %eax
movzbl (%r15,%rcx), %edx
addl $-0x43, %edx
cmpl $0x31, %edx
ja 0x2b2c
movabsq $0x100000001, %rsi      # imm = 0x100000001
btq %rdx, %rsi
jb 0x2b15
movabsq $0x1000000010, %rsi     # imm = 0x1000000010
btq %rdx, %rsi
jb 0x2b0e
movabsq $0x2000000020000, %rsi  # imm = 0x2000000020000
btq %rdx, %rsi
movl $0x0, %edx
jae 0x2b1a
movl $0x3, %edx
jmp 0x2b1a
movl $0x2, %edx
jmp 0x2b1a
movl $0x1, %edx
shlq $0x2, %rax
orq %rdx, %rax
incq %rcx
cmpq %rcx, -0x68(%rbp)
jne 0x2ac5
jmp 0x2b30
xorl %edx, %edx
jmp 0x2b1a
cmpq $0x0, -0xe0(%rbp)
jne 0x2b7f
movq %rax, %rdx
xorq -0xd8(%rbp), %rdx
movl $0x3, %esi
movq -0x38(%rbp), %rcx
movl %ecx, %r8d
xorl %edi, %edi
xorl %ecx, %ecx
movq %rdi, %r9
shlq $0x2, %r9
movq %rsi, %rdi
andq %rdx, %rdi
shrq %cl, %rdi
orq %r9, %rdi
shlq $0x2, %rsi
addq $0x2, %rcx
decl %r8d
jne 0x2b54
cmpq %rax, %rdi
cmovbq %rdi, %rax
jmp 0x2b7f
xorl %eax, %eax
movq %rax, -0x110(%rbp)
movq %r13, %rdi
callq 0x2030
movq %rax, %rbx
movq %rax, %rdi
xorl %esi, %esi
movq %r13, %rdx
callq 0x20f0
leaq -0x1f0(%rbp), %rdi
leaq -0x110(%rbp), %rsi
callq 0x4c6e
movq %rbx, (%rax)
leaq -0x228(%rbp), %rdi
leaq -0x110(%rbp), %rsi
callq 0x4f1c
movq %rax, %rdi
movq %r12, %rsi
callq 0x376e
incl %r14d
jmp 0x2a54
movq -0x30(%rbp), %rdi
callq 0x2170
movq -0x48(%rbp), %rdi
testq %rdi, %rdi
je 0x2bf1
callq 0x21e0
movq 0x73f8(%rip), %rbx      # 0x9ff0
leaq 0x44e4(%rip), %rsi      # 0x70e3
movl $0x16, %edx
movq %rbx, %rdi
callq 0x21c0
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x2160
movsbl %al, %esi
movq 0x73c6(%rip), %rdi      # 0x9ff0
callq 0x2040
movq %rax, %rdi
callq 0x2110
cmpl $0x0, -0x3c(%rbp)
je 0x31cb
movq -0x98(%rbp), %rcx
addl $-0x2, %ecx
movq $-0x1, %rax
movq %rcx, -0x98(%rbp)
shlq %cl, %rax
notq %rax
movq %rax, -0x1b8(%rbp)
movq -0x38(%rbp), %rax
decl %eax
movq %rax, -0x1b0(%rbp)
leaq -0x108(%rbp), %r15
movq $0x0, -0x30(%rbp)
movl $0x18, %edx
movq 0x7362(%rip), %rdi      # 0x9ff0
leaq 0x4465(%rip), %rsi      # 0x70fa
callq 0x21c0
movq -0x188(%rbp), %rax
movq -0x30(%rbp), %rcx
movq 0x8(%rax,%rcx,8), %rbx
testq %rbx, %rbx
je 0x2ccb
movq %rbx, %rdi
callq 0x20c0
movq 0x7332(%rip), %rdi      # 0x9ff0
movq %rbx, %rsi
movq %rax, %rdx
callq 0x21c0
jmp 0x2ce9
movq 0x731e(%rip), %rcx      # 0x9ff0
movq (%rcx), %rax
movq -0x18(%rax), %rax
leaq (%rcx,%rax), %rdi
movl 0x20(%rcx,%rax), %esi
orl $0x1, %esi
callq 0x22f0
movl $0x1, %edx
movq 0x72fb(%rip), %rdi      # 0x9ff0
leaq 0x45b8(%rip), %rsi      # 0x72b4
callq 0x21c0
xorl %eax, %eax
movq %rax, -0x48(%rbp)
movq %rax, -0xa8(%rbp)
movq -0x100(%rbp), %rdx
movq %r15, %rdi
xorl %esi, %esi
leaq 0x4421(%rip), %rcx      # 0x7142
xorl %r8d, %r8d
callq 0x2290
movq -0x178(%rbp), %rsi
movq -0x170(%rbp), %rdx
movq %r15, %rdi
callq 0x2080
movq -0x30(%rbp), %rcx
leaq 0x1(%rcx), %rdx
movq -0x188(%rbp), %rcx
movq %rdx, -0x1a8(%rbp)
movq (%rcx,%rdx,8), %rsi
movq %rax, %rdi
callq 0x2330
movq (%rax), %rdi
leaq 0x4366(%rip), %rsi      # 0x70d1
callq 0x2070
movq %rax, -0xe8(%rbp)
movq $0x0, -0x50(%rbp)
xorl %eax, %eax
movl %eax, %ecx
andl $0x3, %ecx
movl %ecx, -0xa0(%rbp)
movl %eax, -0xac(%rbp)
movl %eax, %eax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
mulsd 0x4264(%rip), %xmm0     # 0x7008
cvttsd2si %xmm0, %r15d
incl %r15d
imulq $0x431bde83, %r15, %rax # imm = 0x431BDE83
shrq $0x32, %rax
imull $0xf4240, %eax, %eax    # imm = 0xF4240
movl %r15d, %ecx
subl %eax, %ecx
movl %ecx, -0xb0(%rbp)
leaq -0x48(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
movq -0xe8(%rbp), %rdx
callq 0x2200
cmpq $-0x1, %rax
je 0x3095
cmpl $0x1, -0xa0(%rbp)
jne 0x3088
cmpl -0x54(%rbp), %r15d
jae 0x3095
cmpl $0x0, -0xb0(%rbp)
jne 0x2e56
movq 0x71e0(%rip), %rdi      # 0x9ff0
movl %r15d, %esi
callq 0x2300
movq %rax, %rbx
movl $0xd, %edx
movq %rax, %rdi
leaq 0x42e9(%rip), %rsi      # 0x7113
callq 0x21c0
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x2160
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2110
movq -0x48(%rbp), %r13
movq %r13, %rdi
callq 0x20c0
decl %eax
subl -0x38(%rbp), %eax
jb 0x2dc8
leal 0x1(%rax), %r8d
addq %r8, -0x50(%rbp)
incl %eax
je 0x3088
movq -0x1f0(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0x1e8(%rbp), %r10
movl $0xfffffffd, %r15d      # imm = 0xFFFFFFFD
movq %r13, %r11
xorl %ebx, %ebx
movl %r15d, %eax
movl %ebx, %r15d
movl %ebx, %ecx
subl %eax, %ecx
cmpl $0x1, %ecx
jne 0x2f20
andq -0x1b8(%rbp), %r12
shlq $0x2, %r12
movq -0x1b0(%rbp), %rax
addl %r15d, %eax
movzbl (%r13,%rax), %ecx
movl $0x3, %eax
addl $-0x43, %ecx
cmpl $0x31, %ecx
ja 0x2ff6
movabsq $0x100000001, %rdx      # imm = 0x100000001
btq %rcx, %rdx
jb 0x2fe9
movabsq $0x1000000010, %rdx     # imm = 0x1000000010
btq %rcx, %rdx
jb 0x2fdd
movabsq $0x2000000020000, %rdx  # imm = 0x2000000020000
btq %rcx, %rdx
jae 0x2ff6
movl $0x3, %ecx
xorl %eax, %eax
jmp 0x2ff3
cmpl $0x0, -0x38(%rbp)
je 0x2fd5
xorl %eax, %eax
xorl %r12d, %r12d
movabsq $0x100000001, %rdx      # imm = 0x100000001
movabsq $0x1000000010, %rsi     # imm = 0x1000000010
movabsq $0x2000000020000, %rdi  # imm = 0x2000000020000
movzbl (%r11,%rax), %ecx
addl $-0x43, %ecx
cmpl $0x31, %ecx
ja 0x2f96
btq %rcx, %rdx
jb 0x2f7f
btq %rcx, %rsi
jb 0x2f78
btq %rcx, %rdi
movl $0x0, %ecx
jae 0x2f84
movl $0x3, %ecx
jmp 0x2f84
movl $0x2, %ecx
jmp 0x2f84
movl $0x1, %ecx
shlq $0x2, %r12
orq %rcx, %r12
incq %rax
cmpq %rax, -0x68(%rbp)
jne 0x2f4d
jmp 0x2f9a
xorl %ecx, %ecx
jmp 0x2f84
movq %r12, %rax
xorq -0xd8(%rbp), %rax
movl $0x3, %edx
movq -0x38(%rbp), %rcx
movl %ecx, %esi
xorl %r14d, %r14d
xorl %ecx, %ecx
movq %r14, %rdi
shlq $0x2, %rdi
movq %rdx, %r14
andq %rax, %r14
shrq %cl, %r14
orq %rdi, %r14
shlq $0x2, %rdx
addq $0x2, %rcx
decl %esi
jne 0x2fb4
jmp 0x3007
xorl %r12d, %r12d
xorl %r14d, %r14d
jmp 0x3007
movl $0x1, %eax
movl $0x2, %ecx
jmp 0x2ff3
movl $0x2, %eax
movl $0x1, %ecx
orq %rcx, %r12
shrq $0x2, %r14
movq -0x98(%rbp), %rcx
shlq %cl, %rax
addq %rax, %r14
cmpq %r14, %r12
movq %r14, %rcx
cmovbq %r12, %rcx
cmpq $0x0, -0xe0(%rbp)
cmovneq %r12, %rcx
movq %rcx, %rax
xorl %edx, %edx
divq %r10
movq -0xa0(%rbp), %rax
movq (%rax,%rdx,8), %rax
testq %rax, %rax
je 0x3079
movq %rdx, %rsi
movq (%rax), %r9
cmpq 0x8(%r9), %rcx
je 0x305f
movq (%r9), %r9
testq %r9, %r9
je 0x3079
movq 0x8(%r9), %rdi
movq %rdi, %rax
xorl %edx, %edx
divq %r10
cmpq %rsi, %rdx
jne 0x3079
cmpq %rdi, %rcx
jne 0x3041
movq 0x10(%r9), %rax
movq -0x30(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
addsd 0x3f9c(%rip), %xmm0     # 0x7010
movsd %xmm0, (%rax,%rcx,8)
incq %rbx
incq %r11
cmpq %r8, %rbx
jne 0x2e9d
movl -0xac(%rbp), %eax
incl %eax
jmp 0x2d81
movq -0xc8(%rbp), %rsi
cmpq -0xc0(%rbp), %rsi
je 0x30c0
movq -0x50(%rbp), %rax
movq %rax, (%rsi)
addq $0x8, %rsi
movq %rsi, -0xc8(%rbp)
leaq -0x108(%rbp), %r15
jmp 0x30db
leaq -0xd0(%rbp), %rdi
leaq -0x50(%rbp), %rdx
callq 0x53fe
leaq -0x108(%rbp), %r15
movq -0x50(%rbp), %rax
cmpq $0x0, -0x1a0(%rbp)
je 0x319c
testq %rax, %rax
je 0x319c
movl $0x10, %edx
movq 0x6ef2(%rip), %rdi      # 0x9ff0
leaq 0x401c(%rip), %rsi      # 0x7121
callq 0x21c0
movq 0x6edf(%rip), %rcx      # 0x9ff0
movq (%rcx), %rax
movq -0x18(%rax), %rdi
addq %rcx, %rdi
movl $0xa, %esi
callq 0x2160
movsbl %al, %esi
movq 0x6ec1(%rip), %rdi      # 0x9ff0
callq 0x2040
movq %rax, %rdi
callq 0x2110
movq -0x1e0(%rbp), %rax
testq %rax, %rax
je 0x319c
movsd -0x50(%rbp), %xmm1
unpcklps 0x3edc(%rip), %xmm1     # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x3ee4(%rip), %xmm1     # 0x7040
movapd %xmm1, %xmm0
unpckhpd %xmm1, %xmm0            # xmm0 = xmm0[1],xmm1[1]
addsd %xmm1, %xmm0
movq 0x10(%rax), %rcx
movq -0x30(%rbp), %rdx
movsd (%rcx,%rdx,8), %xmm1
ucomisd 0x3ea3(%rip), %xmm1     # 0x7020
jbe 0x3194
mulsd 0x3e91(%rip), %xmm1     # 0x7018
divsd %xmm0, %xmm1
movq -0x30(%rbp), %rdx
movsd %xmm1, (%rcx,%rdx,8)
movq (%rax), %rax
testq %rax, %rax
jne 0x3168
movq -0xe8(%rbp), %rdi
callq 0x2170
movq -0x48(%rbp), %rdi
testq %rdi, %rdi
je 0x31b6
callq 0x21e0
movq -0x1a8(%rbp), %rax
movq %rax, -0x30(%rbp)
cmpq -0x60(%rbp), %rax
jne 0x2c82
movq 0x6df6(%rip), %r15      # 0x9fc8
leaq 0x3f59(%rip), %rsi      # 0x7132
movl $0x3, %edx
movq %r15, %rdi
callq 0x21c0
cmpq $0x0, -0x90(%rbp)
je 0x3208
movq 0x6dd1(%rip), %rdi      # 0x9fc8
leaq 0x3f38(%rip), %rsi      # 0x7136
movl $0xa, %edx
callq 0x21c0
cmpl $0x0, -0x3c(%rbp)
je 0x3272
xorl %r14d, %r14d
leaq 0x3f29(%rip), %rbx      # 0x7141
movl $0x1, %edx
movq %r15, %rdi
movq %rbx, %rsi
callq 0x21c0
movq -0x188(%rbp), %rax
movq 0x8(%rax,%r14,8), %r12
testq %r12, %r12
je 0x3251
movq %r12, %rdi
callq 0x20c0
movq %r15, %rdi
movq %r12, %rsi
movq %rax, %rdx
callq 0x21c0
jmp 0x3269
movq (%r15), %rax
movq -0x18(%rax), %rax
leaq (%r15,%rax), %rdi
movl 0x20(%r15,%rax), %esi
orl $0x1, %esi
callq 0x22f0
incq %r14
cmpq %r14, -0x60(%rbp)
jne 0x3218
movq 0x6d4f(%rip), %r15      # 0x9fc8
leaq 0x4034(%rip), %rsi      # 0x72b4
movl $0x1, %edx
movq %r15, %rdi
callq 0x21c0
movq -0x68(%rbp), %rdi
callq 0x2030
movq -0x1e0(%rbp), %r14
testq %r14, %r14
je 0x33d3
movq %rax, %r12
leaq 0x3e91(%rip), %r13      # 0x7141
leaq 0x8(%r14), %rbx
cmpl $0x0, -0x38(%rbp)
je 0x32e1
movq (%rbx), %rax
movq -0x68(%rbp), %rdx
leal (,%rax,8), %ecx
movl $0x54474341, %esi       # imm = 0x54474341
shrl %cl, %esi
decq %rdx
movl %edx, %ecx
movb %sil, (%r12,%rcx)
shrq $0x2, %rax
testq %rdx, %rdx
jne 0x32c1
movq %r12, %rdi
callq 0x20c0
movq %r15, %rdi
movq %r12, %rsi
movq %rax, %rdx
callq 0x21c0
cmpq $0x0, -0x90(%rbp)
je 0x336e
movl $0x1, %edx
movq %r15, %rdi
movq %r13, %rsi
callq 0x21c0
leaq -0x228(%rbp), %rdi
movq %rbx, %rsi
callq 0x4f1c
leaq -0x138(%rbp), %rdi
movq %rax, %rsi
leaq 0x3e12(%rip), %rdx      # 0x7143
callq 0x253c
movq -0x138(%rbp), %rsi
movq -0x130(%rbp), %rdx
movq %r15, %rdi
callq 0x21c0
movq -0x138(%rbp), %rdi
leaq -0x128(%rbp), %rax
cmpq %rax, %rdi
je 0x336e
movq -0x128(%rbp), %rsi
incq %rsi
callq 0x2190
cmpl $0x0, -0x3c(%rbp)
je 0x33a0
xorl %ebx, %ebx
movl $0x1, %edx
movq %r15, %rdi
movq %r13, %rsi
callq 0x21c0
movq 0x10(%r14), %rax
movsd (%rax,%rbx,8), %xmm0
movq %r15, %rdi
callq 0x22c0
incq %rbx
cmpq %rbx, -0x60(%rbp)
jne 0x3376
movq (%r15), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x2160
movsbl %al, %esi
movq %r15, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2110
movq (%r14), %r14
testq %r14, %r14
jne 0x32b0
movq 0x6bee(%rip), %rbx      # 0x9fc8
leaq 0x3d64(%rip), %rsi      # 0x7145
movl $0xd, %edx
movq %rbx, %rdi
callq 0x21c0
cmpq $0x0, -0x90(%rbp)
je 0x3410
movq 0x6bc9(%rip), %rdi      # 0x9fc8
leaq 0x3d4d(%rip), %rsi      # 0x7153
movl $0x2, %edx
callq 0x21c0
cmpl $0x0, -0x3c(%rbp)
je 0x3453
xorl %r12d, %r12d
movq 0x6ba8(%rip), %r14      # 0x9fc8
leaq 0x3d1a(%rip), %r15      # 0x7141
movl $0x1, %edx
movq %r14, %rdi
movq %r15, %rsi
callq 0x21c0
movq -0xd0(%rbp), %rax
movq (%rax,%r12,8), %rsi
movq %r14, %rdi
callq 0x2100
incq %r12
cmpq %r12, -0x60(%rbp)
jne 0x3427
movq (%rbx), %rax
addq -0x18(%rax), %rbx
movq %rbx, %rdi
movl $0xa, %esi
callq 0x2160
movsbl %al, %esi
movq 0x6b57(%rip), %rdi      # 0x9fc8
callq 0x2040
xorl %r15d, %r15d
movq %rax, %rdi
callq 0x2110
movq -0x198(%rbp), %rsp
movq -0x108(%rbp), %rdi
leaq -0xf8(%rbp), %rax
cmpq %rax, %rdi
je 0x34aa
movq -0xf8(%rbp), %rsi
incq %rsi
callq 0x2190
movq -0x158(%rbp), %rdi
leaq -0x148(%rbp), %rax
cmpq %rax, %rdi
je 0x34cc
movq -0x148(%rbp), %rsi
incq %rsi
callq 0x2190
movq -0x178(%rbp), %rdi
leaq -0x168(%rbp), %rax
cmpq %rax, %rdi
je 0x34ee
movq -0x168(%rbp), %rsi
incq %rsi
callq 0x2190
movq -0xd0(%rbp), %rdi
testq %rdi, %rdi
je 0x3509
movq -0xc0(%rbp), %rsi
subq %rdi, %rsi
callq 0x2190
leaq -0x228(%rbp), %rdi
callq 0x3e78
leaq -0x1f0(%rbp), %rdi
callq 0x3f7a
movq -0x88(%rbp), %rdi
leaq -0x78(%rbp), %rax
cmpq %rax, %rdi
je 0x353d
movq -0x78(%rbp), %rsi
incq %rsi
callq 0x2190
movl %r15d, %eax
leaq -0x28(%rbp), %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x359e
jmp 0x359e
movq %rax, %rbx
leaq -0x78(%rbp), %r15
jmp 0x35e9
movq %rax, %rbx
jmp 0x360b
movq %rax, %rbx
movq -0x138(%rbp), %rdi
leaq -0x128(%rbp), %rax
cmpq %rax, %rdi
je 0x35a1
movq -0x128(%rbp), %rsi
incq %rsi
callq 0x2190
jmp 0x35a1
jmp 0x359e
jmp 0x359e
jmp 0x359e
jmp 0x359e
jmp 0x359e
jmp 0x359e
jmp 0x359e
jmp 0x359e
movq %rax, %rbx
leaq -0x78(%rbp), %r15
movq -0x108(%rbp), %rdi
leaq -0xf8(%rbp), %rax
cmpq %rax, %rdi
je 0x35c7
movq -0xf8(%rbp), %rsi
incq %rsi
callq 0x2190
movq -0x158(%rbp), %rdi
leaq -0x148(%rbp), %rax
cmpq %rax, %rdi
je 0x35e9
movq -0x148(%rbp), %rsi
incq %rsi
callq 0x2190
movq -0x178(%rbp), %rdi
leaq -0x168(%rbp), %rax
cmpq %rax, %rdi
je 0x360b
movq -0x168(%rbp), %rsi
incq %rsi
callq 0x2190
movq -0xd0(%rbp), %rdi
testq %rdi, %rdi
je 0x3626
movq -0xc0(%rbp), %rsi
subq %rdi, %rsi
callq 0x2190
leaq -0x228(%rbp), %rdi
callq 0x3e78
leaq -0x1f0(%rbp), %rdi
callq 0x3f7a
movq -0x88(%rbp), %rdi
cmpq %r15, %rdi
je 0x3656
movq -0x78(%rbp), %rsi
incq %rsi
callq 0x2190
movq %rbx, %rdi
callq 0x2310