// File: Altius[P]hotspot2/src/hotspot2_part1.cpp
// Function: BackgroundRegionManager::getPvalue(unsigned int const&)
long double BackgroundRegionManager::getPvalue(const unsigned int& k)
{
  if (k < m_distn.size()) // Yes, m_distn.size(), not m_sampledDataDistnSize
    return m_distn[k].pval;

  // k is greater than all count values in the distribution, so we need to add bin(s) for it.
  // This can only happen if the user has specified a sampling interval
  // and k happens to have not been sampled.

  if (NULL == m_pmf || m_pmfParams.empty())
    {
      cerr << "Coding error:  BRM::getPvalue(" << k << ") was called when m_pmf == NULL and/or m_pmfParams.empty() == true." << endl;
      exit(1);
    }

  StatsForCount sc;
  sc.numOccs = 0;
  sc.pmf = sc.pval = -1.;
  sc.MAxN = -1;

  const int prev_max_k(static_cast<int>(m_distn.size()) - 1), MAlenOver2(m_MAlength / 2); // Yes, m_distn.size(), not m_sampledDataDistnSize.
  int kk = prev_max_k;
  long double curPMF(m_distn[kk].pmf);
  while (k >= m_distn.size()) // Yes, k, not kk.  We're growing the vector until k fits into its highest bin.
    {
      curPMF = m_pmf(++kk, curPMF, m_pmfParams);
      sc.pmf = curPMF;
      m_distn.push_back(sc);
      if (kk >= m_MAlength)
        m_distn[kk - MAlenOver2].MAxN = m_distn[kk - MAlenOver2 - 1].MAxN - m_distn[kk - m_MAlength].numOccs + m_distn[kk].numOccs;
      else
        {
          if (m_MAlength - 1 == kk)
            {
              int sum(0);
              for (int j = 0; j <= kk; j++)
                sum += m_distn[j].numOccs;
              m_distn[MAlenOver2].MAxN = sum;
            }
        }
    }
  // Compute the P-value.  See comments in method computeStats() for further info.
  // kk == k at this point.
  long double sum(1.), prevTerm(1.), curTerm;
  const long double SMALL_VALUE(5.0e-7); // restrict the correctness of the final P-value to ~5 significant digits
  while ((curTerm = m_pmf(++kk, prevTerm, m_pmfParams)) > SMALL_VALUE)
    {
      sum += curTerm;
      prevTerm = curTerm;
    }
  m_distn[k].pval = m_distn[k].pmf * sum;
  //  if (m_distn[k].pval < numeric_limits<double>::min())
  //    m_distn[k].pval = numeric_limits<double>::min();
  // Fill in P-values for any bins that were added between prev_max_k and k.
  kk = k;
  while (kk > prev_max_k + 1)
    {
      m_distn[kk - 1].pval = m_distn[kk - 1].pmf + m_distn[kk].pval;
      //      if (m_distn[k].pval < numeric_limits<double>::min())
      //	m_distn[k].pval = numeric_limits<double>::min();
      kk--;
    }

  return m_distn[k].pval;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x140, %rsp            # imm = 0x140
movq %rdi, -0x18(%rbp)
movq %rsi, -0x20(%rbp)
movq -0x18(%rbp), %rdi
movq %rdi, -0xe0(%rbp)
movq -0x20(%rbp), %rax
movl (%rax), %eax
movq %rax, -0xd8(%rbp)
addq $0x50, %rdi
callq 0xa930
movq %rax, %rcx
movq -0xd8(%rbp), %rax
cmpq %rcx, %rax
jae 0x58d6
movq -0xe0(%rbp), %rdi
addq $0x50, %rdi
movq -0x20(%rbp), %rax
movl (%rax), %eax
movl %eax, %esi
callq 0xa950
fldt 0x20(%rax)
fstpt -0x10(%rbp)
jmp 0x5ce7
movq -0xe0(%rbp), %rcx
xorl %eax, %eax
cmpq 0x168(%rcx), %rax
je 0x5901
movq -0xe0(%rbp), %rdi
addq $0x170, %rdi            # imm = 0x170
callq 0xa370
testb $0x1, %al
jne 0x5901
jmp 0x594a
movq 0x156e8(%rip), %rdi     # 0x1aff0
leaq 0xdc7b(%rip), %rsi      # 0x1358a
callq 0x3240
movq %rax, %rdi
movq -0x20(%rbp), %rax
movl (%rax), %esi
callq 0x3360
movq %rax, %rdi
leaq 0xdc7d(%rip), %rsi      # 0x135a9
callq 0x3240
movq %rax, %rdi
movq 0x1566d(%rip), %rsi     # 0x1afa8
callq 0x3280
movl $0x1, %edi
callq 0x3330
movq -0xe0(%rbp), %rdi
movl $0x0, -0x60(%rbp)
fld1
fchs
fld %st(0)
fstpt -0x40(%rbp)
fstpt -0x50(%rbp)
movl $0xffffffff, -0x30(%rbp) # imm = 0xFFFFFFFF
addq $0x50, %rdi
movq %rdi, -0xe8(%rbp)
callq 0xa930
movq -0xe8(%rbp), %rdi
movq %rax, %rcx
movq -0xe0(%rbp), %rax
decl %ecx
movl %ecx, -0x64(%rbp)
movl 0x3c(%rax), %eax
movl %eax, %ecx
shrl $0x1f, %ecx
addl %ecx, %eax
sarl %eax
movl %eax, -0x68(%rbp)
movl -0x64(%rbp), %eax
movl %eax, -0x6c(%rbp)
movslq -0x6c(%rbp), %rsi
callq 0xa950
fldt 0x10(%rax)
fstpt -0x80(%rbp)
movq -0xe0(%rbp), %rdi
movq -0x20(%rbp), %rax
movl (%rax), %eax
movq %rax, -0xf0(%rbp)
addq $0x50, %rdi
callq 0xa930
movq %rax, %rcx
movq -0xf0(%rbp), %rax
cmpq %rcx, %rax
jb 0x5b71
movq -0xe0(%rbp), %rdx
movq 0x168(%rdx), %rax
movl -0x6c(%rbp), %ecx
incl %ecx
movl %ecx, -0x6c(%rbp)
addq $0x170, %rdx            # imm = 0x170
leaq -0x6c(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq *%rax
movq -0xe0(%rbp), %rdi
fstpt -0x80(%rbp)
fldt -0x80(%rbp)
fstpt -0x50(%rbp)
addq $0x50, %rdi
leaq -0x60(%rbp), %rsi
callq 0xa970
movq -0xe0(%rbp), %rcx
movl -0x6c(%rbp), %eax
cmpl 0x3c(%rcx), %eax
jl 0x5ada
movq -0xe0(%rbp), %rdi
addq $0x50, %rdi
movl -0x6c(%rbp), %eax
subl -0x68(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0xa950
movq -0xe0(%rbp), %rcx
movl 0x30(%rax), %eax
movl %eax, -0xfc(%rbp)
movq %rcx, %rdi
addq $0x50, %rdi
movl -0x6c(%rbp), %eax
subl 0x3c(%rcx), %eax
movslq %eax, %rsi
callq 0xa950
movq -0xe0(%rbp), %rdi
movq %rax, %rcx
movl -0xfc(%rbp), %eax
subl (%rcx), %eax
movl %eax, -0xf8(%rbp)
addq $0x50, %rdi
movslq -0x6c(%rbp), %rsi
callq 0xa950
movq -0xe0(%rbp), %rdi
movq %rax, %rcx
movl -0xf8(%rbp), %eax
addl (%rcx), %eax
movl %eax, -0xf4(%rbp)
addq $0x50, %rdi
movl -0x6c(%rbp), %eax
subl -0x68(%rbp), %eax
movslq %eax, %rsi
callq 0xa950
movl -0xf4(%rbp), %ecx
movl %ecx, 0x30(%rax)
jmp 0x5b6c
movq -0xe0(%rbp), %rax
movl 0x3c(%rax), %eax
subl $0x1, %eax
cmpl -0x6c(%rbp), %eax
jne 0x5b6a
movl $0x0, -0x84(%rbp)
movl $0x0, -0x88(%rbp)
movl -0x88(%rbp), %eax
cmpl -0x6c(%rbp), %eax
jg 0x5b41
movq -0xe0(%rbp), %rdi
addq $0x50, %rdi
movslq -0x88(%rbp), %rsi
callq 0xa950
movl (%rax), %eax
addl -0x84(%rbp), %eax
movl %eax, -0x84(%rbp)
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0x5b00
movq -0xe0(%rbp), %rdi
movl -0x84(%rbp), %eax
movl %eax, -0x100(%rbp)
addq $0x50, %rdi
movslq -0x68(%rbp), %rsi
callq 0xa950
movl -0x100(%rbp), %ecx
movl %ecx, 0x30(%rax)
jmp 0x5b6c
jmp 0x59b5
fld1
fld %st(0)
fstpt -0xa0(%rbp)
fstpt -0xb0(%rbp)
fldl 0xd4a1(%rip)            # 0x13028
fstpt -0xd0(%rbp)
movq -0xe0(%rbp), %rdx
movq 0x168(%rdx), %rax
movl -0x6c(%rbp), %ecx
incl %ecx
movl %ecx, -0x6c(%rbp)
addq $0x170, %rdx            # imm = 0x170
leaq -0x6c(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq *%rax
fld %st(0)
fstp %st(0)
fld %st(0)
fstpt -0xc0(%rbp)
fldl 0xd45f(%rip)            # 0x13028
fxch %st(1)
fucompi %st(1), %st
fstp %st(0)
jbe 0x5bf5
jmp 0x5bd3
fldt -0xc0(%rbp)
fldt -0xa0(%rbp)
faddp %st, %st(1)
fstpt -0xa0(%rbp)
fldt -0xc0(%rbp)
fstpt -0xb0(%rbp)
jmp 0x5b8d
movq -0xe0(%rbp), %rdi
addq $0x50, %rdi
movq %rdi, -0x118(%rbp)
movq -0x20(%rbp), %rax
movl (%rax), %eax
movl %eax, %esi
callq 0xa950
movq -0x118(%rbp), %rdi
fldt 0x10(%rax)
fldt -0xa0(%rbp)
fmulp %st, %st(1)
fstpt -0x10c(%rbp)
movq -0x20(%rbp), %rax
movl (%rax), %eax
movl %eax, %esi
callq 0xa950
fldt -0x10c(%rbp)
fstpt 0x20(%rax)
movq -0x20(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
movl -0x64(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jle 0x5cc9
movq -0xe0(%rbp), %rdi
addq $0x50, %rdi
movq %rdi, -0x130(%rbp)
movl -0x6c(%rbp), %eax
decl %eax
movslq %eax, %rsi
callq 0xa950
movq -0x130(%rbp), %rdi
fldt 0x10(%rax)
fstpt -0x13c(%rbp)
movslq -0x6c(%rbp), %rsi
callq 0xa950
fldt -0x13c(%rbp)
movq -0x130(%rbp), %rdi
fldt 0x20(%rax)
faddp %st, %st(1)
fstpt -0x124(%rbp)
movl -0x6c(%rbp), %eax
decl %eax
movslq %eax, %rsi
callq 0xa950
fldt -0x124(%rbp)
fstpt 0x20(%rax)
movl -0x6c(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x5c4b
movq -0xe0(%rbp), %rdi
addq $0x50, %rdi
movq -0x20(%rbp), %rax
movl (%rax), %eax
movl %eax, %esi
callq 0xa950
fldt 0x20(%rax)
fstpt -0x10(%rbp)
fldt -0x10(%rbp)
addq $0x140, %rsp            # imm = 0x140
popq %rbp
retq
nopw %cs:(%rax,%rax)