// File: /workspace/github_cpp_makefile_star2_O2/adamnovak[P]rlcsa/document_graph.cpp
// Function: main
int
main(int argc, char** argv)
{
  std::cout << "Document graph extractor" << std::endl;
  if(argc < 2)
  {
    std::cout << "Usage:" << std::endl;
    std::cout << "document_graph basename block_size storing_factor" << std::endl;
    std::cout << "  to build the document graph and sparse suffix tree" << std::endl;
    std::cout << "document_graph basename prefix" << std::endl;
    std::cout << "  to compress the grammar and build the index" << std::endl;
    std::cout << "document_graph basename" << std::endl;
    std::cout << "  to test the document array" << std::endl;
    return 1;
  }
  std::cout << std::endl;

  std::string base_name = argv[1];
  std::cout << "Base name: " << base_name << std::endl;

  // Load the index.
  if(argc == 2)
  {
    std::cout << std::endl;
    return testDocarray(base_name);
  }

  // Load the index and compress
  if(argc == 3)
  {
    std::string prefix = argv[2];
    std::cout << "Prefix: " << prefix << std::endl;
    std::cout << std::endl;
    return buildIndex(base_name, prefix);
  }

  usint block_size = atoi(argv[2]);
  std::cout << "Block size: " << block_size << std::endl;
  usint storing_factor = atoi(argv[3]);
  std::cout << "Storing factor: " << storing_factor << std::endl;
  std::cout << std::endl;

  RLCSA rlcsa(argv[1]);
  if(!rlcsa.isOk() || !rlcsa.supportsLocate())
  {
    std::cerr << "Error: Locate is not supported!" << std::endl;
    return 2;
  }
  rlcsa.printInfo();
  rlcsa.reportSize(true);
  if(block_size == 0 || storing_factor == 0) { return 0; }


  double start = readTimer();

  // Get the suffix array from RLCSA.
  usint size = rlcsa.getSize();
  uint docs = rlcsa.getNumberOfSequences();
  usint* documents = new usint[size];
  #pragma omp parallel for schedule(static)
  for(usint i = 0; i < size; i += MEGABYTE)
  {
    rlcsa.locate(pair_type(i, std::min(i + MEGABYTE, size - 1)), documents + i);
  }
  double locate = readTimer();
  std::cout << "Locate: " << (locate - start) << " seconds" << std::endl;

  // Get the LCP array.
  uint* lcp = new uint[size + 1]; lcp[size] = 0;
/*  #ifdef MULTITHREAD_SUPPORT
  usint threads = omp_get_max_threads();
  PLCPVector* plcpvec = rlcsa.buildPLCP(16, threads);
  std::cout << "Total: " << plcpvec->getNumberOfItems() << " / " << plcpvec->getSize() << std::endl;
  PLCPVector::Iterator* iters[threads];
  for(usint i = 0; i < threads; i++) { iters[i] = new PLCPVector::Iterator(*plcpvec); }
  #pragma omp parallel for schedule(static, MEGABYTE)
  for(usint i = 0; i < size; i++)
  {
    lcp[i] = iters[omp_get_thread_num()]->select(documents[i]) - 2 * documents[i];
  }
  for(usint i = 0; i < threads; i++) { delete iters[i]; iters[i] = 0; }
  #else*/
  PLCPVector* plcpvec = rlcsa.buildPLCP(16);
  PLCPVector::Iterator iter(*plcpvec);
  for(usint i = 0; i < size; i++)
  {
    lcp[i] = iter.select(documents[i]) - 2 * documents[i];
  }
//  #endif
  delete plcpvec;
  double lcparray = readTimer();
  std::cout << "LCP: " << (lcparray - locate) << " seconds" << std::endl;

  // Convert SA to document array.
  #pragma omp parallel for schedule(static)
  for(usint i = 0; i < size; i += MEGABYTE)
  {
    rlcsa.getSequenceForPosition(documents + i, std::min(MEGABYTE, size - i));
  }
  // Change document array to be 1-based.
  #pragma omp parallel for schedule(static, MEGABYTE)
  for(usint i = 0; i < size; i++) { documents[i]++; }
  double find = readTimer();
  std::cout << "Documents: " << (find - lcparray) << " seconds" << std::endl;

  // Build a truncated suffix tree.
  // A node with at most block_size suffixes should not have any children.
  std::stack<STNode*> nodestack; nodestack.push(new STNode(0, pair_type(0, 0)));
  STNode* prev = 0; STNode* root = 0;
  for(usint i = 1; i <= size; i++)
  {
    usint left = i - 1;
    while(lcp[i] < nodestack.top()->string_depth)
    {
      nodestack.top()->range.second = i - 1;
      prev = nodestack.top(); nodestack.pop();
      if(length(prev->range) <= block_size) { prev->deleteChildren(); }
      root = prev;  // Last processed node.
      left = prev->range.first;
      if(lcp[i] <= nodestack.top()->string_depth) { nodestack.top()->addChild(prev); prev = 0; }
    }
    if(lcp[i] > nodestack.top()->string_depth)
    {
      STNode* curr = new STNode(lcp[i], pair_type(left, left));
      if(prev != 0) { curr->addChild(prev); prev = 0; }
      nodestack.push(curr);
    }
  }
  while(root->parent != 0) { root = root->parent; }  // Find the actual root.
  root->range.second = size - 1; root->containsAllDocuments();
  delete[] lcp; lcp = 0;
  uint st_nodes = 0, leaf_nodes = 0;
  root->addLeaves();
  root->verifyTree();
  root->determineSize(st_nodes, leaf_nodes);
  double st = readTimer();
  std::cout << "Suffix tree: " << (st - find) << " seconds" << std::endl;
  std::cout << "Total " << size << " positions, " << docs << " documents" << std::endl;
  std::cout << "Truncated suffix tree has " << st_nodes << " nodes" << std::endl;
  std::cout << std::endl;


  // Start processing.
  uint tree_leaves = 0, tree_nodes = leaf_nodes, graph_nodes = 0, edges = 0;
  std::string graph_name = base_name + ".graph";
  std::ofstream output(graph_name.c_str(), std::ios_base::binary);
  if(!output)
  {
    std::cerr << "Error: Cannot open output file " << graph_name << "!" << std::endl;
    delete[] documents;
    return 3;
  }
  std::string singleton_name = base_name + ".singletons";
  std::ofstream singletons(singleton_name.c_str(), std::ios_base::binary);
  if(!singletons)
  {
    std::cerr << "Error: Cannot open output file " << singleton_name << "!" << std::endl;
    delete[] documents;
    output.close();
    return 3;
  }
  output.write((char*)&tree_nodes, sizeof(tree_nodes)); // Placeholder for nodes/subsets.
  output.write((char*)&edges, sizeof(edges)); // Placeholder for edges.

  // For each suffix tree node, produce the corresponding subset if necessary.
  double sets = readTimer();
  while(!nodestack.empty()) { nodestack.pop(); }
  for(prev = root; prev != 0; prev = prev->child) { nodestack.push(prev); }
  while(nodestack.top() != root)
  {
    STNode* curr = nodestack.top(); nodestack.pop();
    for(STNode* temp = curr->sibling; temp != 0; temp = temp->child) { nodestack.push(temp); }
    if(curr->contains_all)
    {
      curr->id = tree_nodes; tree_nodes++;
      continue;
    }

    curr->computeStoredDocuments(documents);
    if(curr->docs->size() >= docs) { curr->containsAllDocuments(); }

    if(curr->child == 0 || curr->contains_all || curr->stored_documents > storing_factor * curr->docs->size())
    {
      curr->storeThisSet();
      int curr_node = -1 * docs;
      if(curr->child == 0) { curr->id = tree_leaves; tree_leaves++; curr_node -= tree_leaves; }
      else                 { curr->id = tree_nodes; tree_nodes++; curr_node -= tree_nodes; }
      if(!(curr->contains_all))
      {
        // Store singletons in a separate file. The presence of singletons greatly slows down the
        // search for bicliques.
        if(curr->docs->size() == 1)
        {
          singletons << (-curr_node) << ": " << curr->docs->at(0) << std::endl;
        }
        else
        {
          output.write((char*)&curr_node, sizeof(curr_node));
          for(std::vector<uint>::iterator iter = curr->docs->begin(); iter != curr->docs->end(); ++iter)
          {
            uint temp = *iter;
            output.write((char*)&temp, sizeof(temp));
          }
          graph_nodes++;
          edges += curr->docs->size();
        }
      }
    }
    else
    {
      curr->remove();
      delete curr;
    }
  }
  root->id = tree_nodes; tree_nodes++;
  double block_stop = readTimer();
  std::cout << "Blocks: " << (block_stop - sets) << " seconds" << std::endl;
  std::cout << std::endl;

  // Write the number of nodes & edges.
  output.seekp(0, std::ios::beg);
  output.write((char*)&graph_nodes, sizeof(graph_nodes));
  output.write((char*)&edges, sizeof(edges));
  std::cout << "Graph has " << graph_nodes << " nodes, " << edges << " edges" << std::endl;
  std::cout << std::endl;
  output.close();
  singletons.close();
  delete[] documents;

  // Write the tree structure.
  DocArray docarray(root, rlcsa);
  if(docarray.isOk())
  {
    std::cout << "Final tree has " << docarray.getNumberOfNodes() << " nodes, " << tree_leaves << " leaves" << std::endl;
    std::cout << std::endl;
    docarray.reportSize(true);
    docarray.writeTo(base_name);
  }

  delete root;
  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe18, %rsp            # imm = 0xE18
movq %rsi, %rbx
movl %edi, %ebp
movq 0x1fdd7(%rip), %rdi     # 0x23fd0
leaq 0x13eaa(%rip), %rsi     # 0x180aa
callq 0x3210
movq %rax, %rdi
callq 0x3100
cmpl $0x1, %ebp
jg 0x42c7
pushq $0x1
popq %r14
movq 0x1fdaf(%rip), %rbx     # 0x23fd0
leaq 0x13e9b(%rip), %rsi     # 0x180c3
movq %rbx, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
leaq 0x13e8b(%rip), %rsi     # 0x180ca
movq %rbx, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
leaq 0x13ea6(%rip), %rsi     # 0x180fc
movq %rbx, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
leaq 0x13ec4(%rip), %rsi     # 0x18131
movq %rbx, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
leaq 0x13ecc(%rip), %rsi     # 0x18150
movq %rbx, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
leaq 0x13ee3(%rip), %rsi     # 0x1817e
movq %rbx, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
leaq 0x13ee4(%rip), %rsi     # 0x18196
movq %rbx, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
jmp 0x4568
movq 0x1fd02(%rip), %r14     # 0x23fd0
movq %r14, %rdi
callq 0x3100
movq 0x8(%rbx), %rsi
leaq 0x70(%rsp), %rdi
leaq 0x5e8(%rsp), %rdx
callq 0x5308
leaq 0x13ec0(%rip), %rsi     # 0x181b3
movq %r14, %rdi
callq 0x3210
leaq 0x70(%rsp), %rsi
movq %rax, %rdi
callq 0x3200
movq %rax, %rdi
callq 0x3100
cmpl $0x3, %ebp
je 0x433c
cmpl $0x2, %ebp
jne 0x43b3
movq 0x1fcab(%rip), %rdi     # 0x23fd0
callq 0x3100
leaq 0x70(%rsp), %rdi
callq 0x5179
movl %eax, %r14d
jmp 0x455e
movq 0x10(%rbx), %rsi
leaq 0x5e8(%rsp), %rdi
leaq 0x170(%rsp), %rdx
callq 0x5308
movq 0x1fc74(%rip), %rdi     # 0x23fd0
leaq 0x13e5c(%rip), %rsi     # 0x181bf
callq 0x3210
leaq 0x5e8(%rsp), %rsi
movq %rax, %rdi
callq 0x3200
movq %rax, %rdi
callq 0x3100
movq 0x1fc49(%rip), %rdi     # 0x23fd0
callq 0x3100
leaq 0x70(%rsp), %rdi
leaq 0x5e8(%rsp), %rsi
callq 0x522f
movl %eax, %r14d
leaq 0x5e8(%rsp), %rdi
callq 0x34a8
jmp 0x455e
movq 0x10(%rbx), %rdi
callq 0x3380
movl %eax, 0x18(%rsp)
movq 0x1fc09(%rip), %rdi     # 0x23fd0
leaq 0x13dfa(%rip), %rsi     # 0x181c8
callq 0x3210
movl 0x18(%rsp), %esi
movq %rax, %rdi
callq 0x3160
movq %rax, %rdi
callq 0x3100
movq 0x18(%rbx), %rdi
callq 0x3380
movl %eax, %r14d
movq 0x1fbd6(%rip), %rdi     # 0x23fd0
leaq 0x13dd4(%rip), %rsi     # 0x181d5
callq 0x3210
movl %r14d, %r12d
movq %rax, %rdi
movq %r12, %rsi
callq 0x3160
movq %rax, %rdi
callq 0x3100
movq 0x1fbad(%rip), %rdi     # 0x23fd0
callq 0x3100
movq 0x8(%rbx), %rsi
leaq 0x170(%rsp), %rdi
leaq 0x3e8(%rsp), %rdx
callq 0x5308
leaq 0x5e8(%rsp), %rdi
leaq 0x170(%rsp), %rsi
xorl %edx, %edx
callq 0x5a90
leaq 0x170(%rsp), %rdi
callq 0x34a8
cmpb $0x1, 0x5e8(%rsp)
jne 0x4532
cmpb $0x0, 0xe00(%rsp)
je 0x4532
leaq 0x5e8(%rsp), %rdi
callq 0x869c
leaq 0x5e8(%rsp), %rdi
pushq $0x1
popq %rsi
callq 0x84d8
cmpl $0x0, 0x18(%rsp)
sete %al
testl %r14d, %r14d
sete %cl
xorl %r14d, %r14d
orb %al, %cl
jne 0x4551
callq 0x15c4c
movsd %xmm0, 0x10(%rsp)
movl 0x5ec(%rsp), %ebp
movl 0xe08(%rsp), %eax
movq %rax, 0x48(%rsp)
leaq (,%rbp,4), %rdi
callq 0x3030
movq %rax, %r13
leal -0x1(%rbp), %r15d
movl $0x100000, %ebx         # imm = 0x100000
leaq 0x5e8(%rsp), %r14
leal -0x100000(%rbx), %eax
cmpl %ebp, %eax
jae 0x457d
cmpl %ebx, %r15d
movl %ebx, %esi
cmovbl %r15d, %esi
movl %eax, %eax
leaq (,%rax,4), %rdx
addq %r13, %rdx
shlq $0x20, %rsi
orq %rax, %rsi
addl $0x100000, %ebx         # imm = 0x100000
movq %r14, %rdi
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x7624
jmp 0x44f6
movq 0x1fab7(%rip), %rdi     # 0x23ff0
leaq 0x13ca6(%rip), %rsi     # 0x181e6
callq 0x3210
movq %rax, %rdi
callq 0x3100
pushq $0x2
popq %r14
leaq 0x5e8(%rsp), %rdi
callq 0x6d12
leaq 0x70(%rsp), %rdi
callq 0x34a8
movl %r14d, %eax
addq $0xe18, %rsp            # imm = 0xE18
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %r15d, 0x50(%rsp)
callq 0x15c4c
movsd %xmm0, 0x30(%rsp)
movq 0x1fa3c(%rip), %rdi     # 0x23fd0
leaq 0x13c6b(%rip), %rsi     # 0x18206
callq 0x3210
movsd 0x30(%rsp), %xmm0
subsd 0x10(%rsp), %xmm0
movq %rax, %rdi
callq 0x33b0
leaq 0x13c54(%rip), %rsi     # 0x1820f
movq %rax, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
leal 0x1(%rbp), %edi
shlq $0x2, %rdi
callq 0x3030
movq %rax, %r15
andl $0x0, (%rax,%rbp,4)
leaq 0x5e8(%rsp), %rdi
pushq $0x10
popq %rsi
callq 0x87d0
movq %rax, %r14
movq %r12, 0x58(%rsp)
leaq 0x370(%rsp), %rdi
movq %rax, %rsi
callq 0x14088
xorl %r12d, %r12d
leaq 0x370(%rsp), %rbx
cmpq %r12, %rbp
je 0x4635
movl (%r13,%r12,4), %esi
movq %rbx, %rdi
callq 0x14180
movl (%r13,%r12,4), %ecx
addl %ecx, %ecx
subl %ecx, %eax
movl %eax, (%r15,%r12,4)
incq %r12
jmp 0x4611
movq %rbp, 0x10(%rsp)
movq %r13, 0x38(%rsp)
movq %r14, %rdi
callq 0x14076
pushq $0x48
popq %rsi
movq %r14, %rdi
callq 0x3240
callq 0x15c4c
movsd %xmm0, 0x68(%rsp)
movq 0x1f96c(%rip), %rdi     # 0x23fd0
leaq 0x13bad(%rip), %rsi     # 0x18218
callq 0x3210
movsd 0x68(%rsp), %xmm0
subsd 0x30(%rsp), %xmm0
movq %rax, %rdi
callq 0x33b0
leaq 0x13b84(%rip), %rsi     # 0x1820f
movq %rax, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
xorl %ebp, %ebp
movl $0x100000, %r14d        # imm = 0x100000
leaq 0x5e8(%rsp), %rbx
movq 0x10(%rsp), %rax
movl %eax, %r12d
cmpl 0x10(%rsp), %ebp
jae 0x46e7
movl %ebp, %eax
movq 0x38(%rsp), %rcx
leaq (%rcx,%rax,4), %rsi
cmpl %r14d, %r12d
movl $0x100000, %edx         # imm = 0x100000
cmovbl %r12d, %edx
movq %rbx, %rdi
callq 0x8138
addl $0x100000, %ebp         # imm = 0x100000
addl $0xfff00000, %r12d      # imm = 0xFFF00000
jmp 0x46b3
xorl %eax, %eax
movq 0x38(%rsp), %rbp
cmpq %rax, 0x10(%rsp)
je 0x46fe
incl (%rbp,%rax,4)
incq %rax
jmp 0x46ee
callq 0x15c4c
movsd %xmm0, 0x60(%rsp)
movq 0x1f8c0(%rip), %rdi     # 0x23fd0
leaq 0x13b07(%rip), %rsi     # 0x1821e
callq 0x3210
movsd 0x60(%rsp), %xmm0
subsd 0x68(%rsp), %xmm0
movq %rax, %rdi
callq 0x33b0
leaq 0x13ad8(%rip), %rsi     # 0x1820f
movq %rax, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
leaq 0x90(%rsp), %rdi
callq 0x53d2
pushq $0x48
popq %rdi
callq 0x3230
movq %rax, %rbx
movq %rax, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0xe8a8
leaq 0x170(%rsp), %rsi
movq %rbx, (%rsi)
leaq 0x90(%rsp), %rdi
callq 0x571e
andq $0x0, 0x20(%rsp)
xorl %r12d, %r12d
pushq $0x1
popq %rax
cmpl 0x10(%rsp), %eax
ja 0x48df
leal -0x1(%rax), %ebx
movq %rax, 0x30(%rsp)
movl %eax, %ebp
movl %ebx, %r14d
movl (%r15,%rbp,4), %r13d
movq 0xc0(%rsp), %rax
cmpq 0xc8(%rsp), %rax
je 0x47c2
movq -0x8(%rax), %rax
jmp 0x47d5
movq 0xd8(%rsp), %rax
movq -0x8(%rax), %rax
movq 0x1f8(%rax), %rax
movl (%rax), %ecx
cmpl %ecx, %r13d
jae 0x486d
movl %ebx, 0x8(%rax)
movq %rax, 0x20(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x597e
movq 0x20(%rsp), %r12
movq 0x4(%r12), %r14
movq %r14, %rax
shrq $0x20, %rax
subl %r14d, %eax
incl %eax
cmpl 0x18(%rsp), %eax
ja 0x4823
movq %r12, %rdi
callq 0xe974
movq 0x20(%rsp), %r12
movl 0x4(%r12), %r14d
movl (%r15,%rbp,4), %eax
movq 0xc0(%rsp), %rcx
cmpq 0xc8(%rsp), %rcx
je 0x483f
movq -0x8(%rcx), %rdi
jmp 0x4852
movq 0xd8(%rsp), %rcx
movq -0x8(%rcx), %rcx
movq 0x1f8(%rcx), %rdi
cmpl (%rdi), %eax
ja 0x47a6
movq %r12, %rsi
callq 0xe948
andq $0x0, 0x20(%rsp)
jmp 0x47a6
cmpl %ecx, %r13d
movq 0x38(%rsp), %rbp
jbe 0x48d3
pushq $0x48
popq %rdi
callq 0x3230
movq %rax, %rbx
movl %r14d, %edx
movabsq $0x100000001, %rax      # imm = 0x100000001
imulq %rax, %rdx
movq %rbx, %rdi
movl %r13d, %esi
callq 0xe8a8
movq %rbx, 0x170(%rsp)
movq 0x20(%rsp), %rsi
testq %rsi, %rsi
je 0x48be
movq %rbx, %rdi
callq 0xe948
andq $0x0, 0x20(%rsp)
leaq 0x90(%rsp), %rdi
leaq 0x170(%rsp), %rsi
callq 0x59d4
movq 0x30(%rsp), %rax
incl %eax
jmp 0x478f
movq %r12, %r14
movq 0x10(%r12), %r12
testq %r12, %r12
jne 0x48df
movl 0x50(%rsp), %eax
movl %eax, 0x8(%r14)
movq %r14, %rdi
callq 0xeec2
movq %r15, %rdi
callq 0x32b0
andl $0x0, 0x44(%rsp)
andl $0x0, 0x40(%rsp)
movq %r14, %rdi
callq 0xe9a4
movq 0x58(%rsp), %r12
movq %r14, %rdi
callq 0xea7c
leaq 0x44(%rsp), %rsi
leaq 0x40(%rsp), %rdx
movq %r14, %rdi
callq 0xed9a
callq 0x15c4c
movsd %xmm0, 0x18(%rsp)
movq 0x1f689(%rip), %rdi     # 0x23fd0
leaq 0x138dc(%rip), %rsi     # 0x1822a
callq 0x3210
movsd 0x18(%rsp), %xmm0
subsd 0x60(%rsp), %xmm0
movq %rax, %rdi
callq 0x33b0
leaq 0x138a1(%rip), %rsi     # 0x1820f
movq %rax, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
movq 0x1f64b(%rip), %rdi     # 0x23fd0
leaq 0x138ac(%rip), %rsi     # 0x18238
callq 0x3210
movq %rax, %rdi
movq 0x10(%rsp), %rsi
callq 0x3160
leaq 0x1389a(%rip), %rsi     # 0x1823f
movq %rax, %rdi
callq 0x3210
movq %rax, %rdi
movq 0x48(%rsp), %rsi
callq 0x3160
leaq 0x1388b(%rip), %rsi     # 0x1824c
movq %rax, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
movq 0x1f5f8(%rip), %rdi     # 0x23fd0
leaq 0x13878(%rip), %rsi     # 0x18257
callq 0x3210
movl 0x44(%rsp), %esi
movq %rax, %rdi
callq 0x3160
leaq 0x1387b(%rip), %rsi     # 0x18272
movq %rax, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
movq 0x1f5c2(%rip), %rdi     # 0x23fd0
callq 0x3100
movl 0x40(%rsp), %eax
andl $0x0, 0x2c(%rsp)
movl %eax, 0xc(%rsp)
andl $0x0, 0x28(%rsp)
leaq 0x1384d(%rip), %rdx     # 0x18279
leaq 0x100(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x53ed
movq 0x100(%rsp), %rsi
leaq 0x170(%rsp), %rdi
pushq $0x4
popq %rdx
callq 0x3270
movq 0x170(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x190(%rsp,%rax)
je 0x4ab7
movq 0x1f57d(%rip), %rdi     # 0x23ff0
leaq 0x13806(%rip), %rsi     # 0x18280
callq 0x3210
leaq 0x100(%rsp), %rsi
movq %rax, %rdi
callq 0x3200
leaq 0x13de2(%rip), %rsi     # 0x18878
movq %rax, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
movq %rbp, %rdi
callq 0x32b0
pushq $0x3
popq %r14
jmp 0x5006
leaq 0x137e2(%rip), %rdx     # 0x182a0
leaq 0xe0(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x53ed
movq 0xe0(%rsp), %rsi
leaq 0x3e8(%rsp), %rdi
pushq $0x4
popq %rdx
callq 0x3270
movq 0x3e8(%rsp), %rax
movq -0x18(%rax), %rax
testb $0x5, 0x408(%rsp,%rax)
je 0x4b56
movq 0x1f4eb(%rip), %rdi     # 0x23ff0
leaq 0x13774(%rip), %rsi     # 0x18280
callq 0x3210
leaq 0xe0(%rsp), %rsi
movq %rax, %rdi
callq 0x3200
leaq 0x13d50(%rip), %rsi     # 0x18878
movq %rax, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
movq %rbp, %rdi
callq 0x32b0
leaq 0x170(%rsp), %rdi
callq 0x3310
pushq $0x3
popq %r14
jmp 0x4fec
leaq 0x170(%rsp), %rdi
leaq 0xc(%rsp), %rsi
pushq $0x4
popq %rdx
callq 0x32d0
leaq 0x170(%rsp), %rdi
leaq 0x28(%rsp), %rsi
pushq $0x4
popq %rdx
callq 0x32d0
callq 0x15c4c
movsd %xmm0, 0x10(%rsp)
leaq 0x90(%rsp), %rbx
movq 0xc0(%rsp), %rax
cmpq 0xa0(%rsp), %rax
je 0x4baf
movq %rbx, %rdi
callq 0x597e
jmp 0x4b93
leaq 0x90(%rsp), %rbx
leaq 0x20(%rsp), %r15
movq %r14, %rax
movq %rax, 0x20(%rsp)
testq %rax, %rax
je 0x4bdf
movq %rbx, %rdi
movq %r15, %rsi
callq 0x59d4
movq 0x20(%rsp), %rax
movq 0x18(%rax), %rax
jmp 0x4bbf
movq $0x0, 0x18(%rsp)
leaq 0x90(%rsp), %r15
leaq 0x120(%rsp), %rbp
movq 0xc0(%rsp), %rax
cmpq 0xc8(%rsp), %rax
je 0x4c10
movq -0x8(%rax), %r13
jmp 0x4c23
movq 0xd8(%rsp), %rax
movq -0x8(%rax), %rax
movq 0x1f8(%rax), %r13
cmpq %r14, %r13
je 0x4df3
movq %r15, %rdi
callq 0x597e
leaq 0x20(%r13), %rax
movq (%rax), %rax
movq %rax, 0x120(%rsp)
testq %rax, %rax
je 0x4c61
movq %r15, %rdi
movq %rbp, %rsi
callq 0x59d4
movq 0x120(%rsp), %rax
addq $0x18, %rax
jmp 0x4c38
cmpb $0x0, 0x38(%r13)
je 0x4c78
movl 0xc(%rsp), %eax
movl %eax, 0x34(%r13)
incl %eax
movl %eax, 0xc(%rsp)
jmp 0x4bf8
movq %r13, %rdi
movq 0x38(%rsp), %rsi
callq 0xedd2
movq 0x40(%r13), %rax
movq 0x8(%rax), %rcx
subq (%rax), %rcx
sarq $0x2, %rcx
cmpq 0x48(%rsp), %rcx
jb 0x4ca3
movq %r13, %rdi
callq 0xeec2
cmpq $0x0, 0x18(%r13)
je 0x4ced
cmpb $0x0, 0x38(%r13)
jne 0x4ced
movq 0x40(%r13), %rax
movq 0x8(%rax), %rcx
subq (%rax), %rcx
movl 0x30(%r13), %eax
sarq $0x2, %rcx
imulq %r12, %rcx
cmpq %rax, %rcx
jb 0x4ced
movq %r13, %rdi
callq 0xed2e
movq %r13, %rdi
callq 0xe8c4
movq %r13, %rdi
pushq $0x48
popq %rsi
callq 0x3240
jmp 0x4bf8
movq %r13, %rdi
callq 0xef10
cmpq $0x0, 0x18(%r13)
je 0x4d09
movl 0xc(%rsp), %esi
leal 0x1(%rsi), %eax
movl %eax, 0xc(%rsp)
jmp 0x4d17
movq 0x18(%rsp), %rax
movl %eax, %esi
incl %eax
movq %rax, 0x18(%rsp)
movl %esi, 0x34(%r13)
notl %esi
subl 0x48(%rsp), %esi
movl %esi, 0x120(%rsp)
cmpb $0x0, 0x38(%r13)
jne 0x4bf8
movq 0x40(%r13), %rax
movq 0x8(%rax), %rcx
subq (%rax), %rcx
cmpq $0x4, %rcx
jne 0x4d87
negl %esi
leaq 0x3e8(%rsp), %rdi
callq 0x3400
movq %rax, %rdi
leaq 0x134be(%rip), %rsi     # 0x1821b
callq 0x3210
movq %rax, %rbx
movq 0x40(%r13), %rdi
xorl %esi, %esi
callq 0x5426
movl (%rax), %esi
movq %rbx, %rdi
callq 0x3160
movq %rax, %rdi
callq 0x3100
jmp 0x4bf8
leaq 0x170(%rsp), %rdi
movq %rbp, %rsi
pushq $0x4
popq %rdx
callq 0x32d0
movq 0x40(%r13), %rax
movq (%rax), %rbx
movq %rbx, %r12
negq %r12
cmpq 0x8(%rax), %rbx
je 0x4dd6
movl (%rbx), %eax
movl %eax, 0x54(%rsp)
leaq 0x170(%rsp), %rdi
leaq 0x54(%rsp), %rsi
pushq $0x4
popq %rdx
callq 0x32d0
addq $0x4, %rbx
movq 0x40(%r13), %rax
addq $-0x4, %r12
jmp 0x4da7
incl 0x2c(%rsp)
addq (%rax), %r12
negq %r12
shrq $0x2, %r12
addl %r12d, 0x28(%rsp)
movq 0x58(%rsp), %r12
jmp 0x4bf8
movl 0xc(%rsp), %eax
movl %eax, 0x34(%r14)
incl %eax
movl %eax, 0xc(%rsp)
callq 0x15c4c
movsd %xmm0, 0x30(%rsp)
movq 0x1f1bd(%rip), %rdi     # 0x23fd0
leaq 0x13492(%rip), %rsi     # 0x182ac
callq 0x3210
movsd 0x30(%rsp), %xmm0
subsd 0x10(%rsp), %xmm0
movq %rax, %rdi
callq 0x33b0
leaq 0x133d5(%rip), %rsi     # 0x1820f
movq %rax, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
movq 0x1f17f(%rip), %rdi     # 0x23fd0
callq 0x3100
leaq 0x170(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x3220
leaq 0x170(%rsp), %rdi
leaq 0x2c(%rsp), %rsi
pushq $0x4
popq %rdx
callq 0x32d0
leaq 0x170(%rsp), %rdi
leaq 0x28(%rsp), %rsi
pushq $0x4
popq %rdx
callq 0x32d0
movq 0x1f138(%rip), %rdi     # 0x23fd0
leaq 0x13416(%rip), %rsi     # 0x182b5
callq 0x3210
movl 0x2c(%rsp), %esi
movq %rax, %rdi
callq 0x3160
leaq 0x13409(%rip), %rsi     # 0x182c0
movq %rax, %rdi
callq 0x3210
movl 0x28(%rsp), %esi
movq %rax, %rdi
callq 0x3160
leaq 0x133f7(%rip), %rsi     # 0x182c9
movq %rax, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
movq 0x1f0e7(%rip), %rdi     # 0x23fd0
callq 0x3100
leaq 0x170(%rsp), %rdi
callq 0x3310
leaq 0x3e8(%rsp), %rdi
callq 0x3310
movq 0x38(%rsp), %rdi
callq 0x32b0
leaq 0x120(%rsp), %rdi
leaq 0x5e8(%rsp), %rdx
movq %r14, %rsi
callq 0xf0e6
cmpb $0x1, 0x168(%rsp)
jne 0x4fc9
movq 0x1f091(%rip), %rdi     # 0x23fd0
leaq 0x1338a(%rip), %rsi     # 0x182d0
callq 0x3210
movq 0x128(%rsp), %rcx
movq 0x130(%rsp), %rdx
movl 0x4(%rdx), %esi
addl 0x4(%rcx), %esi
movq %rax, %rdi
callq 0x3160
leaq 0x13350(%rip), %rsi     # 0x182c0
movq %rax, %rdi
callq 0x3210
movl 0x18(%rsp), %esi
movq %rax, %rdi
callq 0x3160
leaq 0x13355(%rip), %rsi     # 0x182e0
movq %rax, %rdi
callq 0x3210
movq %rax, %rdi
callq 0x3100
movq 0x1f02e(%rip), %rdi     # 0x23fd0
callq 0x3100
leaq 0x120(%rsp), %rdi
pushq $0x1
popq %rsi
callq 0x10a4c
leaq 0x120(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x108f2
movq %r14, %rdi
callq 0xe8c4
pushq $0x48
popq %rsi
movq %r14, %rdi
callq 0x3240
leaq 0x120(%rsp), %rdi
callq 0xf7e8
xorl %r14d, %r14d
leaq 0x3e8(%rsp), %rdi
callq 0x3330
leaq 0xe0(%rsp), %rdi
callq 0x34a8
leaq 0x170(%rsp), %rdi
callq 0x3330
leaq 0x100(%rsp), %rdi
callq 0x34a8
leaq 0x90(%rsp), %rdi
callq 0x5452
leaq 0x370(%rsp), %rdi
callq 0x1408e
jmp 0x4551
jmp 0x5104
jmp 0x5104
jmp 0x5104
jmp 0x5104
movq %rax, %r14
jmp 0x5114
jmp 0x50a0
movq %rax, %r14
leaq 0x120(%rsp), %rdi
callq 0xf7e8
jmp 0x5107
movq %rax, %r14
jmp 0x512e
jmp 0x513d
jmp 0x513d
jmp 0x513d
jmp 0x50c7
jmp 0x513d
jmp 0x50df
jmp 0x50e4
jmp 0x50e4
jmp 0x50e4
jmp 0x50e4
jmp 0x50e4
jmp 0x5104
jmp 0x5104
movq %rax, %r14
jmp 0x5121
jmp 0x5104
jmp 0x513d
jmp 0x5104
jmp 0x50df
jmp 0x50df
jmp 0x50e4
jmp 0x5104
movq %rax, %r14
leaq 0x170(%rsp), %rdi
jmp 0x50f6
jmp 0x50ff
jmp 0x50ff
movq %rax, %r14
pushq $0x48
popq %rsi
movq %rbx, %rdi
callq 0x3240
jmp 0x5140
jmp 0x513d
jmp 0x50e4
jmp 0x50ff
jmp 0x50df
movq %rax, %r14
jmp 0x514d
movq %rax, %r14
jmp 0x515a
jmp 0x50ff
movq %rax, %r14
leaq 0x5e8(%rsp), %rdi
callq 0x34a8
jmp 0x5167
jmp 0x513d
movq %rax, %r14
jmp 0x5167
movq %rax, %r14
leaq 0x3e8(%rsp), %rdi
callq 0x3330
leaq 0xe0(%rsp), %rdi
callq 0x34a8
leaq 0x170(%rsp), %rdi
callq 0x3330
leaq 0x100(%rsp), %rdi
callq 0x34a8
jmp 0x5140
movq %rax, %r14
leaq 0x90(%rsp), %rdi
callq 0x5452
leaq 0x370(%rsp), %rdi
callq 0x1408e
leaq 0x5e8(%rsp), %rdi
callq 0x6d12
leaq 0x70(%rsp), %rdi
callq 0x34a8
movq %r14, %rdi
callq 0x3430