// File: /workspace/github_cpp_makefile_star2_O2/adamnovak[P]rlcsa/sampler.cpp
// Function: CSA::WeightedSampler::minimumWeightPath(bool, unsigned int)
uint
WeightedSampler::minimumWeightPath(bool shortest, uint force)
{
  if(force == 0) { force = this->nodes; }
  std::vector<uint> end_points;
  std::vector<pair_type> partial_results;
  for(uint i = 0; i < this->nodes - 1; i += force)
  {
    end_points.push_back(i);
  }
  end_points.push_back(this->nodes - 1);
  uint parts = end_points.size() - 1;
  for(uint i = 0; i < end_points.size(); i++)
  {
    this->path_weights[end_points[i]] = 0;
    this->predecessors[end_points[i]] = 0;
    partial_results.push_back(pair_type(0, 0));
  }

  #pragma omp parallel for schedule(static)
  for(uint part = 0; part < parts; part++)
  {
    std::deque<node_type> active_nodes;
    active_nodes.push_back(node_type(end_points[part], 0));

    for(uint i = end_points[part] + 1; i < end_points[part + 1]; i++)
    {
      node_type current = this->link(active_nodes, i, shortest);

      // Retire the active nodes that are before the linked predecessor.
      while(active_nodes.front().first < this->predecessors[i])
      {
        active_nodes.pop_front();
      }

      // Retire the first active nodes, if the following ones are strictly better.
      while(active_nodes.size() > 1 &&
            this->isStrictlyBetter(active_nodes[1].first, active_nodes[0].first, i + 1))
      {
        active_nodes.pop_front();
      }

      // Retire the last active nodes, if the preceding node or the current node is always
      // strictly better.
      while(active_nodes.size() > 1 &&
            this->bridge(active_nodes[active_nodes.size() - 2].first, active_nodes.back().first, i))
      {
        active_nodes.pop_back();
      }

      // Add the current node to active nodes, if it is at least as good as the active nodes
      // for some future node.
      if(this->isAsGood(i, active_nodes.back().first))
      {
        active_nodes.push_back(current);
      }
    }

    partial_results[part + 1] = this->finalLink(active_nodes, end_points[part + 1], shortest);
  }

  for(uint i = 1; i < partial_results.size(); i++)
  {
    partial_results[i].first += partial_results[i - 1].first;
    partial_results[i].second += partial_results[i - 1].second;
  }
  this->path_weights[this->nodes - 1] = partial_results[parts].second;

  return partial_results[parts].first;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movl %edx, %r14d
movl %esi, %ebp
movq %rdi, %rbx
testl %edx, %edx
movl 0x48(%rdi), %eax
cmovel %eax, %r14d
leaq 0x10(%rsp), %r15
andq $0x0, 0x10(%r15)
pxor %xmm0, %xmm0
andq $0x0, 0x40(%rsp)
movdqa %xmm0, (%r15)
movdqa %xmm0, 0x30(%rsp)
xorl %ecx, %ecx
leaq 0x58(%rsp), %r12
movl %ecx, 0x58(%rsp)
decl %eax
cmpl %eax, %ecx
jae 0xbd51
movq %r15, %rdi
movq %r12, %rsi
callq 0x8a36
movl 0x58(%rsp), %ecx
addl %r14d, %ecx
movl 0x48(%rbx), %eax
jmp 0xbd30
leaq 0x58(%rsp), %rsi
movl %eax, (%rsi)
leaq 0x10(%rsp), %rdi
callq 0xc968
movq 0x10(%rsp), %rax
movq 0x18(%rsp), %rcx
movq %rcx, %rdx
subq %rax, %rdx
shrq $0x2, %rdx
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
addq %rdx, %r12
xorl %r13d, %r13d
leaq 0x30(%rsp), %r14
leaq 0x58(%rsp), %r15
movl %r13d, %r13d
subq %rax, %rcx
sarq $0x2, %rcx
cmpq %r13, %rcx
jbe 0xbdd3
movq 0x28(%rbx), %rcx
movl (%rax,%r13,4), %edx
andl $0x0, (%rcx,%rdx,4)
movq 0x30(%rbx), %rcx
movl (%rax,%r13,4), %eax
andl $0x0, (%rcx,%rax,4)
andq $0x0, 0x58(%rsp)
movq %r14, %rdi
movq %r15, %rsi
callq 0xac2e
incl %r13d
movq 0x10(%rsp), %rax
movq 0x18(%rsp), %rcx
jmp 0xbd8c
leaq 0x68(%rsp), %r14
movl %r12d, %eax
movq %rax, 0x28(%rsp)
xorl %r13d, %r13d
leaq 0x58(%rsp), %r15
movzbl %bpl, %eax
movl %eax, 0x4(%rsp)
cmpq 0x28(%rsp), %r13
je 0xbfa5
movq %r15, %rdi
callq 0xc772
movq 0x10(%rsp), %rax
movl (%rax,%r13,4), %eax
movl %eax, 0x8(%rsp)
andl $0x0, 0xc(%rsp)
movq %r15, %rdi
leaq 0x8(%rsp), %rsi
callq 0xca8c
movq 0x10(%rsp), %rax
movl (%rax,%r13,4), %ebp
incq %r13
movq %r13, 0x50(%rsp)
leal 0x1(%rbp), %r12d
movl (%rax,%r13,4), %edx
movq %rbx, %rdi
movq %r15, %rsi
cmpl %edx, %r12d
jae 0xbf86
movl %r12d, %edx
movl 0x4(%rsp), %ecx
callq 0xc0da
movq %rax, 0x8(%rsp)
movl %r12d, %r13d
movq 0x68(%rsp), %rax
movl (%rax), %eax
movq 0x30(%rbx), %rcx
cmpl (%rcx,%r13,4), %eax
jae 0xbe79
movq %r15, %rdi
callq 0xc70a
jmp 0xbe5e
addl $0x2, %ebp
movq %r15, %rdi
callq 0xc728
cmpq $0x2, %rax
jb 0xbec7
movq %r14, %rdi
pushq $0x1
popq %rsi
callq 0xcd14
movl (%rax), %r13d
movq %r14, %rdi
xorl %esi, %esi
callq 0xcd14
movl (%rax), %edx
movq %rbx, %rdi
movl %r13d, %esi
movl %ebp, %ecx
callq 0xc1b2
testb %al, %al
je 0xbec7
movq %r15, %rdi
callq 0xc70a
jmp 0xbe7c
movq %r15, %rdi
callq 0xc738
movq %r15, %rdi
callq 0xc728
cmpq $0x1, %rax
jbe 0xbf2b
movq %r15, %rdi
callq 0xc728
leaq -0x2(%rax), %rsi
movq %r14, %rdi
callq 0xcd14
movq 0x88(%rsp), %r13
movq 0x90(%rsp), %rbp
movq %r13, %rcx
cmpq %rbp, %r13
jne 0xbf15
movq 0xa0(%rsp), %rcx
movq -0x8(%rcx), %rcx
movl $0x200, %edx            # imm = 0x200
addq %rdx, %rcx
movl (%rax), %esi
movl -0x8(%rcx), %edx
movq %rbx, %rdi
movl %r12d, %ecx
callq 0xc1e8
testb %al, %al
jne 0xbebf
jmp 0xbf3b
movq 0x88(%rsp), %r13
movq 0x90(%rsp), %rbp
cmpq %rbp, %r13
jne 0xbf54
movq 0xa0(%rsp), %rax
movq -0x8(%rax), %r13
movl $0x200, %eax            # imm = 0x200
addq %rax, %r13
movl -0x8(%r13), %edx
movq %rbx, %rdi
movl %r12d, %esi
callq 0xc27c
testb %al, %al
je 0xbf74
movq %r15, %rdi
leaq 0x8(%rsp), %rsi
callq 0xc750
movq 0x10(%rsp), %rax
movl %r12d, %ebp
movq 0x50(%rsp), %r13
jmp 0xbe33
movl 0x4(%rsp), %ecx
callq 0xc2fa
movq 0x30(%rsp), %rcx
movq %rax, (%rcx,%r13,8)
movq %r15, %rdi
callq 0xca5e
jmp 0xbdf0
movq 0x30(%rsp), %rax
movq 0x38(%rsp), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
xorl %edx, %edx
leal 0x1(%rdx), %esi
cmpq %rsi, %rcx
jbe 0xbfd8
movq (%rax,%rdx,8), %xmm0
movq (%rax,%rsi,8), %xmm1
paddd %xmm0, %xmm1
movq %xmm1, (%rax,%rsi,8)
incq %rdx
jmp 0xbfb8
movq 0x28(%rsp), %rdi
movl 0x4(%rax,%rdi,8), %ecx
movq 0x28(%rbx), %rdx
movl 0x48(%rbx), %esi
decl %esi
movl %ecx, (%rdx,%rsi,4)
movl (%rax,%rdi,8), %ebx
leaq 0x30(%rsp), %rdi
callq 0xb30c
leaq 0x10(%rsp), %rdi
callq 0xc94a
movl %ebx, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0xc020
jmp 0xc020
jmp 0xc025
jmp 0xc020
movq %rax, %rbx
jmp 0xc032
movq %rax, %rbx
leaq 0x58(%rsp), %rdi
callq 0xca5e
leaq 0x30(%rsp), %rdi
callq 0xb30c
leaq 0x10(%rsp), %rdi
callq 0xc94a
movq %rbx, %rdi
callq 0x3410