// File: 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
movq %rsp, %rbp
subq $0x170, %rsp            # imm = 0x170
movb %sil, %al
movq %rdi, -0x8(%rbp)
andb $0x1, %al
movb %al, -0x9(%rbp)
movl %edx, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xf8(%rbp)
cmpl $0x0, -0x10(%rbp)
jne 0x18158
movq -0xf8(%rbp), %rax
movl 0x48(%rax), %eax
movl %eax, -0x10(%rbp)
leaq -0x28(%rbp), %rdi
callq 0xe3c0
leaq -0x40(%rbp), %rdi
callq 0x14dd0
movl $0x0, -0x44(%rbp)
movq -0xf8(%rbp), %rcx
movl -0x44(%rbp), %eax
movl 0x48(%rcx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jae 0x181b2
leaq -0x28(%rbp), %rdi
leaq -0x44(%rbp), %rsi
callq 0xe4c0
jmp 0x18194
jmp 0x18196
movl -0x10(%rbp), %eax
addl -0x44(%rbp), %eax
movl %eax, -0x44(%rbp)
jmp 0x18171
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x1873c
movq -0xf8(%rbp), %rax
movl 0x48(%rax), %eax
decl %eax
movl %eax, -0x58(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x19420
jmp 0x181d0
leaq -0x28(%rbp), %rdi
callq 0x10c20
subq $0x1, %rax
movl %eax, -0x5c(%rbp)
movl $0x0, -0x60(%rbp)
movl -0x60(%rbp), %eax
movq %rax, -0x100(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x10c20
movq %rax, %rcx
movq -0x100(%rbp), %rax
cmpq %rcx, %rax
jae 0x182bd
movq -0xf8(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x118(%rbp)
movl -0x60(%rbp), %eax
movl %eax, %esi
leaq -0x28(%rbp), %rdi
movq %rdi, -0x110(%rbp)
callq 0x19450
movq -0x118(%rbp), %rcx
movq -0x110(%rbp), %rdi
movq %rax, %rdx
movq -0xf8(%rbp), %rax
movl (%rdx), %edx
movl $0x0, (%rcx,%rdx,4)
movq 0x30(%rax), %rax
movq %rax, -0x108(%rbp)
movl -0x60(%rbp), %eax
movl %eax, %esi
callq 0x19450
movq %rax, %rcx
movq -0x108(%rbp), %rax
movl (%rcx), %ecx
movl $0x0, (%rax,%rcx,4)
movl $0x0, -0x6c(%rbp)
movl $0x0, -0x70(%rbp)
leaq -0x68(%rbp), %rdi
leaq -0x6c(%rbp), %rsi
leaq -0x70(%rbp), %rdx
callq 0xdef0
jmp 0x1829e
leaq -0x40(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x14df0
jmp 0x182ad
jmp 0x182af
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x181e7
movl $0x0, -0x74(%rbp)
movl -0x74(%rbp), %eax
cmpl -0x5c(%rbp), %eax
jae 0x18622
leaq -0xc8(%rbp), %rdi
callq 0x19470
jmp 0x182de
movl -0x74(%rbp), %eax
movl %eax, %esi
leaq -0x28(%rbp), %rdi
callq 0x19450
movq %rax, %rsi
movl $0x0, -0xd4(%rbp)
leaq -0xd0(%rbp), %rdi
leaq -0xd4(%rbp), %rdx
callq 0xe9d0
jmp 0x1830e
leaq -0xc8(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x19490
jmp 0x18323
movl -0x74(%rbp), %eax
movl %eax, %esi
leaq -0x28(%rbp), %rdi
callq 0x19450
movl (%rax), %eax
addl $0x1, %eax
movl %eax, -0xd8(%rbp)
movl -0xd8(%rbp), %eax
movl %eax, -0x11c(%rbp)
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, %eax
movl %eax, %esi
leaq -0x28(%rbp), %rdi
callq 0x19450
movq %rax, %rcx
movl -0x11c(%rbp), %eax
cmpl (%rcx), %eax
jae 0x185a3
movq -0xf8(%rbp), %rdi
movl -0xd8(%rbp), %edx
movzbl -0x9(%rbp), %ecx
andl $0x1, %ecx
leaq -0xc8(%rbp), %rsi
callq 0x18880
movq %rax, -0x128(%rbp)
jmp 0x18395
movq -0x128(%rbp), %rax
movq %rax, -0xe0(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x194c0
movq -0xf8(%rbp), %rcx
movl (%rax), %eax
movq 0x30(%rcx), %rcx
movl -0xd8(%rbp), %edx
cmpl (%rcx,%rdx,4), %eax
jae 0x183f2
leaq -0xc8(%rbp), %rdi
callq 0x194f0
jmp 0x183a3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x196c0
jmp 0x1873c
jmp 0x183f4
leaq -0xc8(%rbp), %rdi
callq 0x19560
movq %rax, %rcx
xorl %eax, %eax
cmpq $0x1, %rcx
movb %al, -0x129(%rbp)
jbe 0x18473
leaq -0xc8(%rbp), %rdi
movq %rdi, -0x138(%rbp)
movl $0x1, %esi
callq 0x19590
movq -0x138(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x130(%rbp)
xorl %eax, %eax
movl %eax, %esi
callq 0x19590
movq -0xf8(%rbp), %rdi
movl -0x130(%rbp), %esi
movl (%rax), %edx
movl -0xd8(%rbp), %ecx
incl %ecx
callq 0x189f0
movb %al, -0x12a(%rbp)
jmp 0x18465
movb -0x12a(%rbp), %al
movb %al, -0x129(%rbp)
jmp 0x18473
movb -0x129(%rbp), %al
testb $0x1, %al
jne 0x1847f
jmp 0x18490
leaq -0xc8(%rbp), %rdi
callq 0x194f0
jmp 0x183f4
jmp 0x18492
leaq -0xc8(%rbp), %rdi
callq 0x19560
movq %rax, %rcx
xorl %eax, %eax
cmpq $0x1, %rcx
movb %al, -0x139(%rbp)
jbe 0x18519
leaq -0xc8(%rbp), %rdi
movq %rdi, -0x148(%rbp)
callq 0x19560
movq -0x148(%rbp), %rdi
movq %rax, %rsi
addq $-0x2, %rsi
callq 0x19590
movq -0x148(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x140(%rbp)
callq 0x195c0
movq -0xf8(%rbp), %rdi
movl -0x140(%rbp), %esi
movl (%rax), %edx
movl -0xd8(%rbp), %ecx
callq 0x18a40
movb %al, -0x13a(%rbp)
jmp 0x1850b
movb -0x13a(%rbp), %al
movb %al, -0x139(%rbp)
jmp 0x18519
movb -0x139(%rbp), %al
testb $0x1, %al
jne 0x18525
jmp 0x18536
leaq -0xc8(%rbp), %rdi
callq 0x19600
jmp 0x18492
movl -0xd8(%rbp), %eax
movl %eax, -0x150(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x195c0
movq -0xf8(%rbp), %rdi
movl -0x150(%rbp), %esi
movl (%rax), %edx
callq 0x18b10
movb %al, -0x149(%rbp)
jmp 0x1856a
movb -0x149(%rbp), %al
testb $0x1, %al
jne 0x18576
jmp 0x1858d
leaq -0xc8(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x19660
jmp 0x1858b
jmp 0x1858d
jmp 0x1858f
movl -0xd8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd8(%rbp)
jmp 0x1833c
movl -0x74(%rbp), %eax
incl %eax
movl %eax, %esi
leaq -0x28(%rbp), %rdi
callq 0x19450
movq -0xf8(%rbp), %rdi
movl (%rax), %edx
movzbl -0x9(%rbp), %ecx
andl $0x1, %ecx
leaq -0xc8(%rbp), %rsi
callq 0x18c10
movq %rax, -0x158(%rbp)
jmp 0x185d8
movq -0x158(%rbp), %rax
movq %rax, -0xe8(%rbp)
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, %eax
movl %eax, %esi
leaq -0x40(%rbp), %rdi
callq 0x14e60
movq %rax, %rdi
leaq -0xe8(%rbp), %rsi
callq 0xdb70
leaq -0xc8(%rbp), %rdi
callq 0x196c0
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x182c4
movl $0x1, -0xec(%rbp)
movl -0xec(%rbp), %eax
movq %rax, -0x160(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x157f0
movq %rax, %rcx
movq -0x160(%rbp), %rax
cmpq %rcx, %rax
jae 0x186de
movl -0xec(%rbp), %eax
subl $0x1, %eax
movl %eax, %eax
movl %eax, %esi
leaq -0x40(%rbp), %rdi
callq 0x14e60
movl (%rax), %eax
movl %eax, -0x168(%rbp)
movl -0xec(%rbp), %eax
movl %eax, %esi
leaq -0x40(%rbp), %rdi
callq 0x14e60
movl -0x168(%rbp), %ecx
addl (%rax), %ecx
movl %ecx, (%rax)
movl -0xec(%rbp), %eax
subl $0x1, %eax
movl %eax, %eax
movl %eax, %esi
leaq -0x40(%rbp), %rdi
callq 0x14e60
movl 0x4(%rax), %eax
movl %eax, -0x164(%rbp)
movl -0xec(%rbp), %eax
movl %eax, %esi
leaq -0x40(%rbp), %rdi
callq 0x14e60
movl -0x164(%rbp), %ecx
addl 0x4(%rax), %ecx
movl %ecx, 0x4(%rax)
movl -0xec(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xec(%rbp)
jmp 0x1862c
movl -0x5c(%rbp), %eax
movl %eax, %esi
leaq -0x40(%rbp), %rdi
callq 0x14e60
movq -0xf8(%rbp), %rcx
movl 0x4(%rax), %edx
movq 0x28(%rcx), %rax
movl 0x48(%rcx), %ecx
subl $0x1, %ecx
movl %ecx, %ecx
movl %edx, (%rax,%rcx,4)
movl -0x5c(%rbp), %eax
movl %eax, %esi
leaq -0x40(%rbp), %rdi
callq 0x14e60
movl (%rax), %eax
movl %eax, -0x16c(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x14ec0
leaq -0x28(%rbp), %rdi
callq 0x19730
movl -0x16c(%rbp), %eax
addq $0x170, %rsp            # imm = 0x170
popq %rbp
retq
leaq -0x40(%rbp), %rdi
callq 0x14ec0
leaq -0x28(%rbp), %rdi
callq 0x19730
movq -0x50(%rbp), %rdi
callq 0x3530
nopw (%rax,%rax)