// File: /workspace/github_cpp_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rsi, %rbx
movq %rdi, %r14
movl 0x10(%rdi), %ebp
movl 0x10(%rsi), %esi
movl %esi, %eax
imull %ebp, %eax
cvtsi2ss %rax, %xmm0
movq %rsi, 0x20(%rsp)
leal (%rsi,%rbp), %eax
cvtsi2ss %rax, %xmm1
movl %ecx, %r15d
movq %rdx, 0x18(%rsp)
movss %xmm0, 0x2c(%rsp)
divss %xmm1, %xmm0
callq 0x7230
cvttss2si %xmm0, %r12
movl %r15d, 0x14(%rsp)
testl %r15d, %r15d
je 0x3e1c0
leaq 0x82eb(%rip), %rsi      # 0x46464
movl $0x9, %edx
movq 0x18(%rsp), %r15
movq %r15, %rdi
callq 0x74b0
movl %r12d, %esi
movq %r15, %rdi
callq 0x72d0
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x73f0
movsbl %al, %esi
movq %r15, %rdi
callq 0x7040
movq %rax, %rdi
callq 0x72e0
movq %r12, 0x30(%rsp)
movq %r14, %rdi
callq 0x3e5d0
movq %rbx, %rdi
callq 0x3e5d0
movq (%r14), %r12
movq (%rbx), %r13
cmpq %r14, %r12
setne %al
cmpq %rbx, %r13
setne %cl
andb %al, %cl
movl $0x0, 0x10(%rsp)
movl $0x0, 0xc(%rsp)
cmpb $0x1, %cl
movq 0x20(%rsp), %rcx
jne 0x3e3b2
xorl %r15d, %r15d
movl $0x0, 0xc(%rsp)
movl $0x0, 0x10(%rsp)
movq %rbp, 0x40(%rsp)
movq %rbx, 0x38(%rsp)
movq 0x10(%r12), %rsi
movq 0x10(%r13), %rax
cmpq %rax, %rsi
jne 0x3e297
cmpb $0x0, 0x14(%rsp)
je 0x3e261
movq 0x18(%rsp), %rdi
callq 0x73e0
movl $0x5, %edx
movq %rax, %rdi
leaq 0x821c(%rip), %rsi      # 0x4646e
callq 0x74b0
movq 0x20(%rsp), %rcx
movq 0x10(%r12), %rsi
movslq %esi, %rax
addl %ecx, %r15d
movq (%r12), %r12
cmpq %r14, %r12
je 0x3e277
cmpq %rax, 0x10(%r12)
je 0x3e264
subl %ebp, %r15d
movq (%r13), %r13
cmpq %rbx, %r13
je 0x3e289
cmpq %rax, 0x10(%r13)
je 0x3e277
cmpl 0x10(%rsp), %r15d
jle 0x3e2e7
movl %r15d, 0x10(%rsp)
jmp 0x3e2f6
jge 0x3e2c7
cmpb $0x0, 0x14(%rsp)
je 0x3e2af
movq 0x18(%rsp), %rdi
callq 0x73e0
movq 0x20(%rsp), %rcx
addl %ecx, %r15d
movq (%r12), %r12
movl 0x10(%rsp), %eax
cmpl %eax, %r15d
cmovgl %r15d, %eax
movl %eax, 0x10(%rsp)
jmp 0x3e2f6
cmpb $0x0, 0x14(%rsp)
je 0x3e2e0
movq 0x18(%rsp), %rdi
movq %rax, %rsi
callq 0x73e0
movq 0x20(%rsp), %rcx
subl %ebp, %r15d
movq (%r13), %r13
movl 0xc(%rsp), %eax
cmpl %eax, %r15d
cmovll %r15d, %eax
movl %eax, 0xc(%rsp)
cmpb $0x0, 0x14(%rsp)
je 0x3e3a4
movl $0x3, %edx
movq 0x18(%rsp), %rbx
movq %rbx, %rdi
leaq 0x815f(%rip), %rsi      # 0x46474
callq 0x74b0
movq %rbx, %rdi
movq 0x38(%rsp), %rbx
movl %r15d, %esi
callq 0x7710
movq %rax, %rbp
movl $0x6, %edx
movq %rax, %rdi
leaq 0x813c(%rip), %rsi      # 0x46478
callq 0x74b0
movq %rbp, %rdi
movl 0xc(%rsp), %esi
callq 0x7710
movq %rax, %rbp
movl $0x6, %edx
movq %rax, %rdi
leaq 0x8120(%rip), %rsi      # 0x4647f
callq 0x74b0
movq %rbp, %rdi
movl 0x10(%rsp), %esi
callq 0x7710
movq %rax, %rbp
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbp, %rdi
movl $0xa, %esi
callq 0x73f0
movsbl %al, %esi
movq %rbp, %rdi
movq 0x40(%rsp), %rbp
callq 0x7040
movq %rax, %rdi
callq 0x72e0
movq 0x20(%rsp), %rcx
cmpq %r14, %r12
je 0x3e3b2
cmpq %rbx, %r13
jne 0x3e224
movl 0xc(%rsp), %eax
negl %eax
movl 0x10(%rsp), %ecx
cmpl %eax, %ecx
cmovgl %ecx, %eax
xorps %xmm0, %xmm0
cvtsi2ss %eax, %xmm0
divss 0x2c(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movq 0x30(%rsp), %rdi
callq 0x3dc65
movsd 0x308c(%rip), %xmm1     # 0x41470
subsd %xmm0, %xmm1
movapd %xmm1, %xmm0
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq