// File: Altius[P]hotspot2/src/hotspot2_part2.cpp
// Function: buildFDRmapping(std::basic_ifstream<char, std::char_traits<char>>&, std::vector<std::pair<int, long double>, std::allocator<std::pair<int, long double>>>&)
bool buildFDRmapping(ifstream& ifs, vector<pair<int, long double> >& p_to_q)
{
  const int BUFSIZE(100);
  char buf[BUFSIZE], *p;
  long numPvalues(0);
  map<int, int> tempMap;
  map<int, int>::iterator it;
  pair<int, int> negLog10PscaledAndNumOccs;
  int linenum(0), fieldnum;

  while (ifs.getline(buf,BUFSIZE))
    {
      linenum++;
      fieldnum = 1;
      if (!(p = strtok(buf, "\t")) || !*p)
	{
	MissingField:
	  cerr << "Error:  Failed to find field " << fieldnum
	       << " on line " << linenum << " of the file of P-values."
	       << endl << endl;
	  return false;
	}
      negLog10PscaledAndNumOccs.first = atoi(p);
      fieldnum++;
      if (!(p = strtok(NULL, "\t")))
	goto MissingField;
      negLog10PscaledAndNumOccs.second = atoi(p);
      
      it = tempMap.lower_bound(negLog10PscaledAndNumOccs.first); // >=
      if (tempMap.end() == it)
	{
	  // no lower bound found in the map; every map element is smaller, or the map is empty
	  if (!tempMap.empty())
	    tempMap.insert(--it, negLog10PscaledAndNumOccs);
	  else
	    tempMap.insert(negLog10PscaledAndNumOccs);
	}
      else
	{
	  if (it->first == negLog10PscaledAndNumOccs.first)
	    it->second += negLog10PscaledAndNumOccs.second;
	  else
	    {
	      if (it != tempMap.begin())
		it--;
	      tempMap.insert(it, negLog10PscaledAndNumOccs);
	    }
	}
      numPvalues += negLog10PscaledAndNumOccs.second;
    }

  if (0 == numPvalues)
    {
      cerr << "Error:  Received an empty file of P-values." << endl << endl;
      return false;
    }

  p_to_q.resize(tempMap.size()); // assume one entry per map entry; final size will almost surely be a bit smaller
  
  it = tempMap.end();
  it--;
  int i = 0, numThisExtremeOrMoreExtreme(0);
  const long double N(static_cast<double>(numPvalues));
  long double prevFDR(-1.), FDR;
  while (it != tempMap.begin())
    {
      p_to_q[i].first = it->first;
      numThisExtremeOrMoreExtreme += it->second;
      FDR = pow(10., -it->first/CHANGE_OF_SCALE) * N / static_cast<long double>(numThisExtremeOrMoreExtreme);
      //      if (FDR < numeric_limits<double>::min())
      //	FDR = numeric_limits<double>::min();
      if (FDR < prevFDR)
	FDR = prevFDR;
      if (FDR > 0.999)
	{
	  p_to_q[i++].second = 1.;
	  p_to_q.resize(i);
	  break;
	}
      p_to_q[i].second = FDR;
      prevFDR = FDR;
      i++;
      it--;
    }

  // It's extremely unlikely, but possible that only the smallest -log10(p) has B-H FDR = 1.
  if (i > 0 && p_to_q[i-1].second < 1.)
    {
      p_to_q[i].first = tempMap.begin()->first;
      p_to_q[i].second = 1.;
    }

  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x270, %rsp            # imm = 0x270
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl $0x64, -0x1c(%rbp)
movq $0x0, -0x90(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x4af0
leaq -0xc8(%rbp), %rdi
callq 0x4b10
leaq -0xd0(%rbp), %rdi
callq 0x4b30
jmp 0x25eb
movl $0x0, -0xe0(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x80(%rbp), %rsi
movl $0x64, %edx
callq 0x2090
movq %rax, -0x1b0(%rbp)
jmp 0x2610
movq -0x1b0(%rbp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x22b0
movb %al, -0x1b1(%rbp)
jmp 0x262e
movb -0x1b1(%rbp), %al
testb $0x1, %al
jne 0x263d
jmp 0x29b1
movl -0xe0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe0(%rbp)
movl $0x1, -0xe4(%rbp)
leaq -0x80(%rbp), %rdi
leaq 0x8cd2(%rip), %rsi      # 0xb333
callq 0x2310
movq %rax, -0x88(%rbp)
cmpq $0x0, %rax
je 0x2683
movq -0x88(%rbp), %rax
cmpb $0x0, (%rax)
jne 0x2776
jmp 0x2685
movq 0xe964(%rip), %rdi      # 0x10ff0
leaq 0x8985(%rip), %rsi      # 0xb018
callq 0x21e0
movq %rax, -0x1c0(%rbp)
jmp 0x26a1
movq -0x1c0(%rbp), %rdi
movl -0xe4(%rbp), %esi
callq 0x2370
movq %rax, -0x1c8(%rbp)
jmp 0x26bc
movq -0x1c8(%rbp), %rdi
leaq 0x896c(%rip), %rsi      # 0xb036
callq 0x21e0
movq %rax, -0x1d0(%rbp)
jmp 0x26d8
movq -0x1d0(%rbp), %rdi
movl -0xe0(%rbp), %esi
callq 0x2370
movq %rax, -0x1d8(%rbp)
jmp 0x26f3
movq -0x1d8(%rbp), %rdi
leaq 0x893f(%rip), %rsi      # 0xb040
callq 0x21e0
movq %rax, -0x1e0(%rbp)
jmp 0x270f
movq -0x1e0(%rbp), %rdi
movq 0xe88b(%rip), %rsi      # 0x10fa8
callq 0x2220
movq %rax, -0x1e8(%rbp)
jmp 0x272b
movq -0x1e8(%rbp), %rdi
movq 0xe86f(%rip), %rsi      # 0x10fa8
callq 0x2220
jmp 0x2740
movb $0x0, -0x1(%rbp)
movl $0x1, -0xe8(%rbp)
jmp 0x2ce9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xd8(%rbp)
movl %eax, -0xdc(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x4e90
jmp 0x2d03
movq -0x88(%rbp), %rdi
callq 0x2300
movl %eax, -0xd0(%rbp)
movl -0xe4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe4(%rbp)
xorl %eax, %eax
movl %eax, %edi
leaq 0x8b91(%rip), %rsi      # 0xb333
callq 0x2310
movq %rax, -0x88(%rbp)
cmpq $0x0, %rax
jne 0x27b9
jmp 0x2685
movq -0x88(%rbp), %rdi
callq 0x2300
movl %eax, -0xcc(%rbp)
leaq -0xc0(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x4b50
movq %rax, -0x1f0(%rbp)
jmp 0x27e7
movq -0x1f0(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0xf0(%rbp), %rax
movq %rax, -0xc8(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x4bb0
movq %rax, -0xf8(%rbp)
leaq -0xf8(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x4b80
testb $0x1, %al
jne 0x2832
jmp 0x28d1
leaq -0xc0(%rbp), %rdi
callq 0x4be0
testb $0x1, %al
jne 0x2890
leaq -0xc8(%rbp), %rdi
callq 0x4c40
movq %rax, %rsi
leaq -0x100(%rbp), %rdi
callq 0x4c70
movq -0x100(%rbp), %rsi
leaq -0xc0(%rbp), %rdi
leaq -0xd0(%rbp), %rdx
callq 0x4c00
movq %rax, -0x1f8(%rbp)
jmp 0x2880
movq -0x1f8(%rbp), %rax
movq %rax, -0x108(%rbp)
jmp 0x28cc
leaq -0xc0(%rbp), %rdi
leaq -0xd0(%rbp), %rsi
callq 0x4c90
movb %dl, -0x201(%rbp)
movq %rax, -0x200(%rbp)
jmp 0x28b2
movb -0x201(%rbp), %al
movq -0x200(%rbp), %rcx
movq %rcx, -0x118(%rbp)
movb %al, -0x110(%rbp)
jmp 0x2997
leaq -0xc8(%rbp), %rdi
callq 0x4cd0
movl (%rax), %eax
cmpl -0xd0(%rbp), %eax
jne 0x2910
movl -0xcc(%rbp), %eax
movl %eax, -0x208(%rbp)
leaq -0xc8(%rbp), %rdi
callq 0x4cd0
movl -0x208(%rbp), %ecx
addl 0x4(%rax), %ecx
movl %ecx, 0x4(%rax)
jmp 0x2995
leaq -0xc0(%rbp), %rdi
callq 0x4d20
movq %rax, -0x120(%rbp)
leaq -0xc8(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x4cf0
testb $0x1, %al
jne 0x293c
jmp 0x2951
leaq -0xc8(%rbp), %rdi
xorl %esi, %esi
callq 0x4d50
movq %rax, -0x128(%rbp)
leaq -0x130(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x4c70
movq -0x130(%rbp), %rsi
leaq -0xc0(%rbp), %rdi
leaq -0xd0(%rbp), %rdx
callq 0x4c00
movq %rax, -0x210(%rbp)
jmp 0x2987
movq -0x210(%rbp), %rax
movq %rax, -0x138(%rbp)
jmp 0x2997
movslq -0xcc(%rbp), %rax
addq -0x90(%rbp), %rax
movq %rax, -0x90(%rbp)
jmp 0x25f5
xorl %eax, %eax
cmpq -0x90(%rbp), %rax
jne 0x2a1c
movq 0xe62d(%rip), %rdi      # 0x10ff0
leaq 0x8690(%rip), %rsi      # 0xb05a
callq 0x21e0
movq %rax, -0x218(%rbp)
jmp 0x29d8
movq -0x218(%rbp), %rdi
movq 0xe5c2(%rip), %rsi      # 0x10fa8
callq 0x2220
movq %rax, -0x220(%rbp)
jmp 0x29f4
movq -0x220(%rbp), %rdi
movq 0xe5a6(%rip), %rsi      # 0x10fa8
callq 0x2220
jmp 0x2a09
movb $0x0, -0x1(%rbp)
movl $0x1, -0xe8(%rbp)
jmp 0x2ce9
movq -0x18(%rbp), %rax
movq %rax, -0x228(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x4e20
movq -0x228(%rbp), %rdi
movq %rax, %rsi
callq 0x4d90
jmp 0x2a44
leaq -0xc0(%rbp), %rdi
callq 0x4bb0
movq %rax, -0x140(%rbp)
movq -0x140(%rbp), %rax
movq %rax, -0xc8(%rbp)
leaq -0xc8(%rbp), %rdi
xorl %esi, %esi
callq 0x4d50
movq %rax, -0x148(%rbp)
movl $0x0, -0x14c(%rbp)
movl $0x0, -0x150(%rbp)
cvtsi2sdq -0x90(%rbp), %xmm0
movsd %xmm0, -0x1a0(%rbp)
fldl -0x1a0(%rbp)
fstpt -0x160(%rbp)
fld1
fchs
fstpt -0x170(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x4d20
movq %rax, -0x188(%rbp)
leaq -0xc8(%rbp), %rdi
leaq -0x188(%rbp), %rsi
callq 0x4cf0
testb $0x1, %al
jne 0x2ae4
jmp 0x2c5d
leaq -0xc8(%rbp), %rdi
movq %rdi, -0x240(%rbp)
callq 0x4cd0
movl (%rax), %eax
movl %eax, -0x244(%rbp)
movq -0x18(%rbp), %rdi
movslq -0x14c(%rbp), %rsi
callq 0x4e40
movl -0x244(%rbp), %ecx
movq -0x240(%rbp), %rdi
movl %ecx, (%rax)
callq 0x4cd0
movq -0x240(%rbp), %rdi
movl 0x4(%rax), %ecx
movl -0x150(%rbp), %eax
addl %ecx, %eax
movl %eax, -0x150(%rbp)
callq 0x4cd0
movl (%rax), %eax
negl %eax
movl %eax, -0x1a4(%rbp)
fildl -0x1a4(%rbp)
flds 0x84ae(%rip)            # 0xb004
fdivrp %st, %st(1)
movq %rsp, %rax
fstpt (%rax)
movsd 0x84a3(%rip), %xmm0     # 0xb008
callq 0x4e60
fstpt -0x234(%rbp)
jmp 0x2b72
fldt -0x234(%rbp)
fldt -0x160(%rbp)
fmulp %st, %st(1)
movl -0x150(%rbp), %eax
movl %eax, -0x1a8(%rbp)
fildl -0x1a8(%rbp)
fdivrp %st, %st(1)
fstpt -0x180(%rbp)
fldt -0x180(%rbp)
fldt -0x170(%rbp)
fucompi %st(1), %st
fstp %st(0)
jbe 0x2bba
jmp 0x2bae
fldt -0x170(%rbp)
fstpt -0x180(%rbp)
fldt -0x180(%rbp)
fldl 0x844a(%rip)            # 0xb010
fxch %st(1)
fucompi %st(1), %st
fstp %st(0)
jbe 0x2c03
jmp 0x2bd0
movq -0x18(%rbp), %rdi
movslq -0x14c(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x14c(%rbp)
callq 0x4e40
fld1
fstpt 0x10(%rax)
movq -0x18(%rbp), %rdi
movslq -0x14c(%rbp), %rsi
callq 0x4d90
jmp 0x2c01
jmp 0x2c5d
fldt -0x180(%rbp)
fstpt -0x250(%rbp)
movq -0x18(%rbp), %rdi
movslq -0x14c(%rbp), %rsi
callq 0x4e40
fldt -0x250(%rbp)
fstpt 0x10(%rax)
fldt -0x180(%rbp)
fstpt -0x170(%rbp)
movl -0x14c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14c(%rbp)
leaq -0xc8(%rbp), %rdi
xorl %esi, %esi
callq 0x4d50
movq %rax, -0x190(%rbp)
jmp 0x2ab5
cmpl $0x0, -0x14c(%rbp)
jle 0x2cdb
movq -0x18(%rbp), %rdi
movl -0x14c(%rbp), %eax
decl %eax
movslq %eax, %rsi
callq 0x4e40
fldt 0x10(%rax)
fld1
fucompi %st(1), %st
fstp %st(0)
jbe 0x2cdb
jmp 0x2c87
leaq -0xc0(%rbp), %rdi
callq 0x4d20
movq %rax, -0x198(%rbp)
leaq -0x198(%rbp), %rdi
callq 0x4cd0
movl (%rax), %eax
movl %eax, -0x254(%rbp)
movq -0x18(%rbp), %rdi
movslq -0x14c(%rbp), %rsi
callq 0x4e40
movl -0x254(%rbp), %ecx
movl %ecx, (%rax)
movq -0x18(%rbp), %rdi
movslq -0x14c(%rbp), %rsi
callq 0x4e40
fld1
fstpt 0x10(%rax)
movb $0x1, -0x1(%rbp)
movl $0x1, -0xe8(%rbp)
leaq -0xc0(%rbp), %rdi
callq 0x4e90
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x270, %rsp            # imm = 0x270
popq %rbp
retq
movq -0xd8(%rbp), %rdi
callq 0x2380
nop