// File: millanek[P]Dsuite/KolmogorovSmirnovDist.cpp
// Function: Pomeranz(int, double)
static double Pomeranz (int n, double x)
{
   /* The Pomeranz algorithm to compute the KS distribution */
   const double EPS = 1.0e-15;
   const int ENO = 350;
   const double RENO = ldexp (1.0, ENO); /* for renormalization of V */
   int coreno;                    /* counter: how many renormalizations */
   const double t = n * x;
   double w, sum, minsum;
   int i, j, k, s;
   int r1, r2;                    /* Indices i and i-1 for V[i][] */
   int jlow, jup, klow, kup, kup0;
   double *A;
   double *Atflo;
   double *Atcei;
   double **V;
   double **H;                    /* = pow(w, j) / Factorial(j) */

   A = (double *) calloc ((size_t) (2 * n + 3), sizeof (double));
   Atflo = (double *) calloc ((size_t) (2 * n + 3), sizeof (double));
   Atcei = (double *) calloc ((size_t) (2 * n + 3), sizeof (double));
   V = (double **) CreateMatrixD (2, n + 2);
   H = (double **) CreateMatrixD (4, n + 2);

   CalcFloorCeil (n, t, A, Atflo, Atcei);

   for (j = 1; j <= n + 1; j++)
      V[0][j] = 0;
   for (j = 2; j <= n + 1; j++)
      V[1][j] = 0;
   V[1][1] = RENO;
   coreno = 1;

   /* Precompute H[][] = (A[j] - A[j-1]^k / k! for speed */
   H[0][0] = 1;
   w = 2.0 * A[2] / n;
   for (j = 1; j <= n + 1; j++)
      H[0][j] = w * H[0][j - 1] / j;

   H[1][0] = 1;
   w = (1.0 - 2.0 * A[2]) / n;
   for (j = 1; j <= n + 1; j++)
      H[1][j] = w * H[1][j - 1] / j;

   H[2][0] = 1;
   w = A[2] / n;
   for (j = 1; j <= n + 1; j++)
      H[2][j] = w * H[2][j - 1] / j;

   H[3][0] = 1;
   for (j = 1; j <= n + 1; j++)
      H[3][j] = 0;

   r1 = 0;
   r2 = 1;
   for (i = 2; i <= 2 * n + 2; i++) {
      jlow = 2 + Atflo[i];
      if (jlow < 1)
         jlow = 1;
      jup = Atcei[i];
      if (jup > n + 1)
         jup = n + 1;

      klow = 2 + Atflo[i - 1];
      if (klow < 1)
         klow = 1;
      kup0 = Atcei[i - 1];

      /* Find to which case it corresponds */
      w = (A[i] - A[i - 1]) / n;
      s = -1;
      for (j = 0; j < 4; j++) {
         if (fabs (w - H[j][1]) <= EPS) {
            s = j;
            break;
         }
      }
      /* assert (s >= 0, "Pomeranz: s < 0"); */

      minsum = RENO;
      r1 = (r1 + 1) & 1;          /* i - 1 */
      r2 = (r2 + 1) & 1;          /* i */

      for (j = jlow; j <= jup; j++) {
         kup = kup0;
         if (kup > j)
            kup = j;
         sum = 0;
         for (k = kup; k >= klow; k--)
            sum += V[r1][k] * H[s][j - k];
         V[r2][j] = sum;
         if (sum < minsum)
            minsum = sum;
      }

      if (minsum < 1.0e-280) {
         /* V is too small: renormalize to avoid underflow of probabilities */
         for (j = jlow; j <= jup; j++)
            V[r2][j] *= RENO;
         coreno++;                /* keep track of log of RENO */
      }
   }

   sum = V[r2][n + 1];
   free (A);
   free (Atflo);
   free (Atcei);
   DeleteMatrixD (H);
   DeleteMatrixD (V);
   w = getLogFactorial (n) - coreno * ENO * num_Ln2 + log (sum);
   if (w >= 0.)
      return 1.;
   return exp (w);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movl %edi, -0xc(%rbp)
movsd %xmm0, -0x18(%rbp)
movsd 0x7c95(%rip), %xmm0     # 0x8d710
movsd %xmm0, -0x20(%rbp)
movl $0x15e, -0x24(%rbp)     # imm = 0x15E
movsd 0x2a19(%rip), %xmm0     # 0x884a8
movl $0x15e, %edi            # imm = 0x15E
callq 0x88c0
movsd %xmm0, -0x30(%rbp)
cvtsi2sdl -0xc(%rbp), %xmm0
mulsd -0x18(%rbp), %xmm0
movsd %xmm0, -0x40(%rbp)
movl -0xc(%rbp), %eax
shll %eax
addl $0x3, %eax
movslq %eax, %rdi
movl $0x8, %esi
callq 0x83c0
movq %rax, -0x90(%rbp)
movl -0xc(%rbp), %eax
shll %eax
addl $0x3, %eax
movslq %eax, %rdi
movl $0x8, %esi
callq 0x83c0
movq %rax, -0x98(%rbp)
movl -0xc(%rbp), %eax
shll %eax
addl $0x3, %eax
movslq %eax, %rdi
movl $0x8, %esi
callq 0x83c0
movq %rax, -0xa0(%rbp)
movl -0xc(%rbp), %esi
addl $0x2, %esi
movl $0x2, %edi
callq 0x874a0
movq %rax, -0xa8(%rbp)
movl -0xc(%rbp), %esi
addl $0x2, %esi
movl $0x4, %edi
callq 0x874a0
movq %rax, -0xb0(%rbp)
movl -0xc(%rbp), %edi
movsd -0x40(%rbp), %xmm0
movq -0x90(%rbp), %rsi
movq -0x98(%rbp), %rdx
movq -0xa0(%rbp), %rcx
callq 0x87530
movl $0x1, -0x60(%rbp)
movl -0x60(%rbp), %eax
movl -0xc(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jg 0x85b86
movq -0xa8(%rbp), %rax
movq (%rax), %rax
movslq -0x60(%rbp), %rcx
xorps %xmm0, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x85b58
movl $0x2, -0x60(%rbp)
movl -0x60(%rbp), %eax
movl -0xc(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jg 0x85bbc
movq -0xa8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x60(%rbp), %rcx
xorps %xmm0, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x85b8d
movsd -0x30(%rbp), %xmm0
movq -0xa8(%rbp), %rax
movq 0x8(%rax), %rax
movsd %xmm0, 0x8(%rax)
movl $0x1, -0x34(%rbp)
movq -0xb0(%rbp), %rax
movq (%rax), %rax
movsd 0x28be(%rip), %xmm0     # 0x884a8
movsd %xmm0, (%rax)
movq -0x90(%rbp), %rax
movsd 0x28c3(%rip), %xmm0     # 0x884c0
mulsd 0x10(%rax), %xmm0
cvtsi2sdl -0xc(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movl $0x1, -0x60(%rbp)
movl -0x60(%rbp), %eax
movl -0xc(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jg 0x85c68
movsd -0x48(%rbp), %xmm0
movq -0xb0(%rbp), %rax
movq (%rax), %rax
movl -0x60(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
mulsd (%rax,%rcx,8), %xmm0
cvtsi2sdl -0x60(%rbp), %xmm1
divsd %xmm1, %xmm0
movq -0xb0(%rbp), %rax
movq (%rax), %rax
movslq -0x60(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x85c17
movq -0xb0(%rbp), %rax
movq 0x8(%rax), %rax
movsd 0x282d(%rip), %xmm0     # 0x884a8
movsd %xmm0, (%rax)
movq -0x90(%rbp), %rax
movsd 0x10(%rax), %xmm1
addsd %xmm1, %xmm1
movsd 0x2811(%rip), %xmm0     # 0x884a8
subsd %xmm1, %xmm0
cvtsi2sdl -0xc(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movl $0x1, -0x60(%rbp)
movl -0x60(%rbp), %eax
movl -0xc(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jg 0x85d03
movsd -0x48(%rbp), %xmm0
movq -0xb0(%rbp), %rax
movq 0x8(%rax), %rax
movl -0x60(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
mulsd (%rax,%rcx,8), %xmm0
cvtsi2sdl -0x60(%rbp), %xmm1
divsd %xmm1, %xmm0
movq -0xb0(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x60(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x85cb0
movq -0xb0(%rbp), %rax
movq 0x10(%rax), %rax
movsd 0x2792(%rip), %xmm0     # 0x884a8
movsd %xmm0, (%rax)
movq -0x90(%rbp), %rax
movsd 0x10(%rax), %xmm0
cvtsi2sdl -0xc(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movl $0x1, -0x60(%rbp)
movl -0x60(%rbp), %eax
movl -0xc(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jg 0x85d8e
movsd -0x48(%rbp), %xmm0
movq -0xb0(%rbp), %rax
movq 0x10(%rax), %rax
movl -0x60(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
mulsd (%rax,%rcx,8), %xmm0
cvtsi2sdl -0x60(%rbp), %xmm1
divsd %xmm1, %xmm0
movq -0xb0(%rbp), %rax
movq 0x10(%rax), %rax
movslq -0x60(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x85d3b
movq -0xb0(%rbp), %rax
movq 0x18(%rax), %rax
movsd 0x2707(%rip), %xmm0     # 0x884a8
movsd %xmm0, (%rax)
movl $0x1, -0x60(%rbp)
movl -0x60(%rbp), %eax
movl -0xc(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jg 0x85ddb
movq -0xb0(%rbp), %rax
movq 0x18(%rax), %rax
movslq -0x60(%rbp), %rcx
xorps %xmm0, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x85dac
movl $0x0, -0x6c(%rbp)
movl $0x1, -0x70(%rbp)
movl $0x2, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
movl -0xc(%rbp), %ecx
shll %ecx
addl $0x2, %ecx
cmpl %ecx, %eax
jg 0x8608f
movq -0x98(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movsd 0x26aa(%rip), %xmm0     # 0x884c0
addsd (%rax,%rcx,8), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x74(%rbp)
cmpl $0x1, -0x74(%rbp)
jge 0x85e2f
movl $0x1, -0x74(%rbp)
movq -0xa0(%rbp), %rax
movslq -0x5c(%rbp), %rcx
cvttsd2si (%rax,%rcx,8), %eax
movl %eax, -0x78(%rbp)
movl -0x78(%rbp), %eax
movl -0xc(%rbp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jle 0x85e58
movl -0xc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x78(%rbp)
movq -0x98(%rbp), %rax
movl -0x5c(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movsd 0x2650(%rip), %xmm0     # 0x884c0
addsd (%rax,%rcx,8), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x7c(%rbp)
cmpl $0x1, -0x7c(%rbp)
jge 0x85e89
movl $0x1, -0x7c(%rbp)
movq -0xa0(%rbp), %rax
movl -0x5c(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
cvttsd2si (%rax,%rcx,8), %eax
movl %eax, -0x84(%rbp)
movq -0x90(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x90(%rbp), %rax
movl -0x5c(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
subsd (%rax,%rcx,8), %xmm0
cvtsi2sdl -0xc(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movl $0xffffffff, -0x68(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x60(%rbp)
cmpl $0x4, -0x60(%rbp)
jge 0x85f32
movsd -0x48(%rbp), %xmm1
movq -0xb0(%rbp), %rax
movslq -0x60(%rbp), %rcx
movq (%rax,%rcx,8), %rax
subsd 0x8(%rax), %xmm1
movaps 0x34c5(%rip), %xmm0     # 0x893d0
pand %xmm0, %xmm1
movsd 0x77f9(%rip), %xmm0     # 0x8d710
ucomisd %xmm1, %xmm0
jb 0x85f25
movl -0x60(%rbp), %eax
movl %eax, -0x68(%rbp)
jmp 0x85f32
jmp 0x85f27
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x85ee5
movsd -0x30(%rbp), %xmm0
movsd %xmm0, -0x58(%rbp)
movl -0x6c(%rbp), %eax
addl $0x1, %eax
andl $0x1, %eax
movl %eax, -0x6c(%rbp)
movl -0x70(%rbp), %eax
addl $0x1, %eax
andl $0x1, %eax
movl %eax, -0x70(%rbp)
movl -0x74(%rbp), %eax
movl %eax, -0x60(%rbp)
movl -0x60(%rbp), %eax
cmpl -0x78(%rbp), %eax
jg 0x8602c
movl -0x84(%rbp), %eax
movl %eax, -0x80(%rbp)
movl -0x80(%rbp), %eax
cmpl -0x60(%rbp), %eax
jle 0x85f7d
movl -0x60(%rbp), %eax
movl %eax, -0x80(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x50(%rbp)
movl -0x80(%rbp), %eax
movl %eax, -0x64(%rbp)
movl -0x64(%rbp), %eax
cmpl -0x7c(%rbp), %eax
jl 0x85fe5
movq -0xa8(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x64(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0xb0(%rbp), %rax
movslq -0x68(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movl -0x60(%rbp), %ecx
subl -0x64(%rbp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm2
movsd -0x50(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x50(%rbp)
movl -0x64(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x85f8b
movsd -0x50(%rbp), %xmm0
movq -0xa8(%rbp), %rax
movslq -0x70(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x60(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movsd -0x50(%rbp), %xmm1
movsd -0x58(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x8601c
movsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x58(%rbp)
jmp 0x8601e
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x85f5a
movsd 0x76ec(%rip), %xmm0     # 0x8d720
ucomisd -0x58(%rbp), %xmm0
jbe 0x8607f
movl -0x74(%rbp), %eax
movl %eax, -0x60(%rbp)
movl -0x60(%rbp), %eax
cmpl -0x78(%rbp), %eax
jg 0x86076
movsd -0x30(%rbp), %xmm0
movq -0xa8(%rbp), %rax
movslq -0x70(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movslq -0x60(%rbp), %rcx
mulsd (%rax,%rcx,8), %xmm0
movsd %xmm0, (%rax,%rcx,8)
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x86041
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x86081
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x85df0
movq -0xa8(%rbp), %rax
movslq -0x70(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movl -0xc(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, -0x50(%rbp)
movq -0x90(%rbp), %rdi
callq 0x86d0
movq -0x98(%rbp), %rdi
callq 0x86d0
movq -0xa0(%rbp), %rdi
callq 0x86d0
movq -0xb0(%rbp), %rdi
callq 0x87920
movq -0xa8(%rbp), %rdi
callq 0x87920
movl -0xc(%rbp), %edi
callq 0x87370
movaps %xmm0, %xmm1
imull $0x15e, -0x34(%rbp), %eax # imm = 0x15E
cvtsi2sd %eax, %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
movsd 0x75f6(%rip), %xmm2     # 0x8d718
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0xb8(%rbp)
movsd -0x50(%rbp), %xmm0
callq 0x8490
movaps %xmm0, %xmm1
movsd -0xb8(%rbp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
movsd -0x48(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jb 0x8616d
movsd 0x2342(%rip), %xmm0     # 0x884a8
movsd %xmm0, -0x8(%rbp)
jmp 0x8617c
movsd -0x48(%rbp), %xmm0
callq 0x8a70
movsd %xmm0, -0x8(%rbp)
movsd -0x8(%rbp), %xmm0
addq $0xc0, %rsp
popq %rbp
retq
nopw (%rax,%rax)