// File: millanek[P]Dsuite/kstest.cpp
// Function: ks_test(std::__cxx11::list<long, std::allocator<long>>, std::__cxx11::list<long, std::allocator<long>>, std::ostream&, bool)
double ks_test (std::list<int64_t> sample1, std::list<int64_t> sample2,
        std::ostream& outfile, bool printDebug) {

  unsigned int n1, n2, n_approx;
    // sample sizes
  float d;
    // the value of Kolmogorov's statistic
    // for the particular values of sample1 and sample2
  int D, Dmin, Dmax, s;
    // used in computing this value d

  std::list<int64_t>::iterator it1, it2;

  // Determine sample sizes
  n1 = sample1.size();
  n2 = sample2.size();

  // Calculate a conservative n approximation
  n_approx = (unsigned) ceil(float(n1*n2)/(n1+n2));
  if (printDebug) outfile << "n_approx=" << n_approx << std::endl;

  // Sort samples
  sample1.sort(); //outfile << "sorted sample1: " << sample1 << std::endl;
  sample2.sort(); //outfile << "sorted sample2: " << sample2 << std::endl;

  // We divide the range 0..1 into n1*n2 intervals of equal size 1/(n1*n2).
  //
  // Each item in sample1 makes the sample c.d.f of sample1
  // jump by a step of n2 intervals.
  // Each item in sample2 makes the sample c.d.f of sample2
  // jump by a step of n1 intervals.
  //
  // For each item we compute D, related to the distance between the two
  // sample c.d.f., s_cdf_1 - s_cdf_2, by:
  //
  //    D/(n1*n2) = s_cdf_1 - s_cdf_2
  //
  // We want to determine:
  //
  //    Dmin/(n1*n2) = min [s_cdf_1 - s_cdf_2] <= 0
  //    Dmax/(n1*n2) = max [s_cdf_1 - s_cdf_2] >= 0
  //
  // And then the value of Kolmorogov's statistic D_n1n2 is just:
  //
  //    D_n1n2 = sup |s_cdf_1 - s_cdf_2|
  //           = max [ |Dmin/(n1*n2)| ; |Dmax/(n1*n2)| ]

  D = 0; Dmin = 0; Dmax = 0;
  it1 = sample1.begin();
  it2 = sample2.begin();

  while ( (it1 != sample1.end()) && (it2 != sample2.end()) ) {

    if (*it1 == *it2) {

        if (printDebug) outfile << *it1 << " tie!";
      // steps in both sample c.d.f., we need to perform all steps
      // in this point before comparing D to Dmin and Dmax

      s = *it1;
      // perform all steps in s_cdf_1 first
      do {
    D += n2;
    it1++;
      }
      while ( (*it1 == s) && (it1 != sample1.end()) );
      // perform all steps in s_cdf_2 now
      do {
    D -= n1;
    it2++;
      }
      while ( (*it2 == s) && (it2 != sample2.end()) );

      // now adapt Dmin, Dmax if necessary
      if (D > Dmax)
    Dmax = D;
      else if (D < Dmin)
    Dmin = D;

    }

    else if (*it1 < *it2) {

    if (printDebug) outfile << *it1;
      // step in s_cdf_1, increase D by n2
      D += n2;
      it1++;

      if (D > Dmax)
    Dmax = D;

    }

    else {

      if (printDebug) outfile << *it2;
      // step in F2, decrease D by n1
      D -= n1;
      it2++;

      if (D < Dmin)
    Dmin = D;

    }

      if (printDebug) outfile << " D=" << D << " Dmin=" << Dmin << " Dmax=" << Dmax << std::endl;

  }

  // For two-sided test, take D = max (|Dmax|, |Dmin|) and compute
  // the value d of Kolmogorov's statistic (two-sided only)

  if (-Dmin > Dmax)
    D = -Dmin;
  else
    D = Dmax;

  // Hence the observed value of Kolmogorov's statistic:
  d = float(D)/(n1*n2);

  // Return p-value
  return 1 - K(n_approx,d);

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movq %rsi, -0xa8(%rbp)
movq %rdi, -0xb0(%rbp)
movb %cl, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
andb $0x1, %al
movb %al, -0x19(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x84520
leaq -0x50(%rbp), %rdi
callq 0x84520
movq -0xb0(%rbp), %rdi
callq 0x84540
movq -0xa8(%rbp), %rdi
movl %eax, -0x20(%rbp)
callq 0x84540
movl %eax, -0x24(%rbp)
movl -0x20(%rbp), %eax
movl -0x24(%rbp), %ecx
movl %eax, %edx
imull %ecx, %edx
cvtsi2ss %rdx, %xmm0
addl %ecx, %eax
cvtsi2ss %rax, %xmm1
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
callq 0x80b0
cvttsd2si %xmm0, %rax
movl %eax, -0x28(%rbp)
testb $0x1, -0x19(%rbp)
je 0x83dd8
movq -0x18(%rbp), %rdi
leaq 0x991b(%rip), %rsi      # 0x8d6d4
callq 0x8590
movq %rax, %rdi
movl -0x28(%rbp), %esi
callq 0x8790
movq %rax, %rdi
movq 0x3b18d(%rip), %rsi     # 0xbef60
callq 0x85f0
movq -0xb0(%rbp), %rdi
callq 0x84570
movq -0xa8(%rbp), %rdi
callq 0x84570
movq -0xb0(%rbp), %rdi
movl $0x0, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
movl $0x0, -0x38(%rbp)
callq 0x84970
movq -0xa8(%rbp), %rdi
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
movq %rax, -0x48(%rbp)
callq 0x84970
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0xb0(%rbp), %rdi
callq 0x2f030
movq %rax, -0x68(%rbp)
leaq -0x48(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x849a0
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0xb1(%rbp)
jne 0x83e63
jmp 0x83e86
movq -0xa8(%rbp), %rdi
callq 0x2f030
movq %rax, -0x70(%rbp)
leaq -0x50(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x849a0
movb %al, -0xb1(%rbp)
movb -0xb1(%rbp), %al
testb $0x1, %al
jne 0x83e95
jmp 0x84141
leaq -0x48(%rbp), %rdi
callq 0x2f660
movq (%rax), %rax
movq %rax, -0xc0(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x2f660
movq %rax, %rcx
movq -0xc0(%rbp), %rax
cmpq (%rcx), %rax
jne 0x84001
testb $0x1, -0x19(%rbp)
je 0x83efc
movq -0x18(%rbp), %rax
movq %rax, -0xc8(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x2f660
movq -0xc8(%rbp), %rdi
movq (%rax), %rsi
callq 0x8ac0
movq %rax, %rdi
leaq 0x97e7(%rip), %rsi      # 0x8d6de
callq 0x8590
leaq -0x48(%rbp), %rdi
callq 0x2f660
movq (%rax), %rax
movl %eax, -0x3c(%rbp)
movl -0x24(%rbp), %eax
addl -0x30(%rbp), %eax
movl %eax, -0x30(%rbp)
leaq -0x48(%rbp), %rdi
xorl %esi, %esi
callq 0x849d0
movq %rax, -0x78(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x2f660
movq (%rax), %rcx
movslq -0x3c(%rbp), %rdx
xorl %eax, %eax
cmpq %rdx, %rcx
movb %al, -0xc9(%rbp)
jne 0x83f63
movq -0xb0(%rbp), %rdi
callq 0x2f030
movq %rax, -0x80(%rbp)
leaq -0x48(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x849a0
movb %al, -0xc9(%rbp)
movb -0xc9(%rbp), %al
testb $0x1, %al
jne 0x83f0b
jmp 0x83f6f
movl -0x20(%rbp), %ecx
movl -0x30(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x30(%rbp)
leaq -0x50(%rbp), %rdi
xorl %esi, %esi
callq 0x849d0
movq %rax, -0x88(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x2f660
movq (%rax), %rcx
movslq -0x3c(%rbp), %rdx
xorl %eax, %eax
cmpq %rdx, %rcx
movb %al, -0xca(%rbp)
jne 0x83fd2
movq -0xa8(%rbp), %rdi
callq 0x2f030
movq %rax, -0x90(%rbp)
leaq -0x50(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x849a0
movb %al, -0xca(%rbp)
movb -0xca(%rbp), %al
testb $0x1, %al
jne 0x83f6f
movl -0x30(%rbp), %eax
cmpl -0x38(%rbp), %eax
jle 0x83fec
movl -0x30(%rbp), %eax
movl %eax, -0x38(%rbp)
jmp 0x83ffc
movl -0x30(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0x83ffa
movl -0x30(%rbp), %eax
movl %eax, -0x34(%rbp)
jmp 0x83ffc
jmp 0x840d8
leaq -0x48(%rbp), %rdi
callq 0x2f660
movq (%rax), %rax
movq %rax, -0xd8(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x2f660
movq %rax, %rcx
movq -0xd8(%rbp), %rax
cmpq (%rcx), %rax
jge 0x84080
testb $0x1, -0x19(%rbp)
je 0x84055
movq -0x18(%rbp), %rax
movq %rax, -0xe0(%rbp)
leaq -0x48(%rbp), %rdi
callq 0x2f660
movq -0xe0(%rbp), %rdi
movq (%rax), %rsi
callq 0x8ac0
movl -0x24(%rbp), %eax
addl -0x30(%rbp), %eax
movl %eax, -0x30(%rbp)
leaq -0x48(%rbp), %rdi
xorl %esi, %esi
callq 0x849d0
movq %rax, -0x98(%rbp)
movl -0x30(%rbp), %eax
cmpl -0x38(%rbp), %eax
jle 0x8407e
movl -0x30(%rbp), %eax
movl %eax, -0x38(%rbp)
jmp 0x840d6
testb $0x1, -0x19(%rbp)
je 0x840a9
movq -0x18(%rbp), %rax
movq %rax, -0xe8(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x2f660
movq -0xe8(%rbp), %rdi
movq (%rax), %rsi
callq 0x8ac0
movl -0x20(%rbp), %ecx
movl -0x30(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x30(%rbp)
leaq -0x50(%rbp), %rdi
xorl %esi, %esi
callq 0x849d0
movq %rax, -0xa0(%rbp)
movl -0x30(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0x840d4
movl -0x30(%rbp), %eax
movl %eax, -0x34(%rbp)
jmp 0x840d6
jmp 0x840d8
testb $0x1, -0x19(%rbp)
je 0x8413c
movq -0x18(%rbp), %rdi
leaq 0x95fb(%rip), %rsi      # 0x8d6e4
callq 0x8590
movq %rax, %rdi
movl -0x30(%rbp), %esi
callq 0x8a10
movq %rax, %rdi
leaq 0x95e5(%rip), %rsi      # 0x8d6e8
callq 0x8590
movq %rax, %rdi
movl -0x34(%rbp), %esi
callq 0x8a10
movq %rax, %rdi
leaq 0x95d2(%rip), %rsi      # 0x8d6ef
callq 0x8590
movq %rax, %rdi
movl -0x38(%rbp), %esi
callq 0x8a10
movq %rax, %rdi
movq 0x3ae29(%rip), %rsi     # 0xbef60
callq 0x85f0
jmp 0x83e35
xorl %eax, %eax
subl -0x34(%rbp), %eax
cmpl -0x38(%rbp), %eax
jle 0x84155
xorl %eax, %eax
subl -0x34(%rbp), %eax
movl %eax, -0x30(%rbp)
jmp 0x8415b
movl -0x38(%rbp), %eax
movl %eax, -0x30(%rbp)
cvtsi2ssl -0x30(%rbp), %xmm0
movl -0x20(%rbp), %eax
movl -0x24(%rbp), %ecx
imull %ecx, %eax
cvtsi2ss %rax, %xmm1
divss %xmm1, %xmm0
movss %xmm0, -0x2c(%rbp)
movl -0x28(%rbp), %edi
movss -0x2c(%rbp), %xmm0
cvtss2sd %xmm0, %xmm0
callq 0x838a0
movaps %xmm0, %xmm1
movsd 0x4315(%rip), %xmm0     # 0x884a8
subsd %xmm1, %xmm0
addq $0xf0, %rsp
popq %rbp
retq