// File: /workspace/github_cpp_makefile_star2_O2/tomfunkhouser[P]gaps/apps/msh2df/../../pkgs/R3Shapes/R3Kdtree.cpp
// Function: gaps::R3Kdtree<Point*>::PartitionPoints(Point**, int, int, int, int)
int R3Kdtree<PtrType>::
PartitionPoints(PtrType *points, int npoints, RNDimension dim, int imin, int imax)
{
  // Check range
  assert(imin <= imax);
  assert(imin >= 0);
  assert(imin < npoints);
  assert(imax >= 0);
  assert(imax < npoints);
  if (imin == imax) return imin;

  // Choose a coordinate at random to split upon
  int irand = (int) (imin + RNRandomScalar() * (imax - imin + 1));
  if (irand < imin) irand = imin;
  if (irand > imax) irand = imax;
  RNCoord split_coord = Position(points[irand])[dim];

  // Swap values at irand and imax
  PtrType swap = points[irand];
  points[irand] = points[imax];
  points[imax] = swap;

  // Partition points according to coordinate
  int split_index = imin;
  int middle_index = (imin + imax) / 2;
  for (int i = imin; i < imax; i++) {
    assert(split_index <= i);
    RNCoord coord = Position(points[i])[dim];
    if (coord < split_coord) {
      PtrType swap = points[split_index];
      points[split_index] = points[i];
      points[i] = swap;
      split_index++;
    }
    else if (coord == split_coord) {
      if (split_index < middle_index) {
        PtrType swap = points[split_index];
        points[split_index] = points[i];
        points[i] = swap;
        split_index++;
      }
    }
  }

  // Swap values at split_index and imax
  swap = points[split_index];
  points[split_index] = points[imax];
  points[imax] = swap;

  // Now split_index has value split_coord
  // All values to the left of split_index have values < split_coord
  // All values to the right of split_index have values >= split_coord

  // Recurse until we find the median
  if (split_index == imin) {
    if (imin >= npoints/2) return imin;
    else return PartitionPoints(points, npoints, dim, imin+1, imax);
  }
  else if (split_index == imax) {
    if (imax <= npoints/2) return imax;
    else return PartitionPoints(points, npoints, dim, imin, imax-1);
  }
  else {
    if (split_index == npoints/2) return split_index;
    else if (split_index > npoints/2) return PartitionPoints(points, npoints, dim, imin, split_index-1);
    else return PartitionPoints(points, npoints, dim, split_index+1, imax);
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movl %r8d, %r13d
movl %r9d, %ebx
subl %r8d, %ebx
je 0x13e18
movl %r9d, %ebp
movl %ecx, %r14d
movq %rsi, %r12
movl %edx, 0x8(%rsp)
cvtsi2sd %r13d, %xmm0
movsd %xmm0, 0x10(%rsp)
movq %rdi, (%rsp)
callq 0x6e9fa
incl %ebx
cvtsi2sd %ebx, %xmm1
mulsd %xmm0, %xmm1
addsd 0x10(%rsp), %xmm1
cvttsd2si %xmm1, %eax
cmpl %r13d, %eax
cmovlel %r13d, %eax
cmpl %ebp, %eax
cmovgel %ebp, %eax
movslq %eax, %r15
movq (%r12,%r15,8), %rdx
leaq 0x30(%rsp), %rdi
movq (%rsp), %rsi
callq 0x13a9a
movl %r14d, 0xc(%rsp)
movslq %r14d, %r14
movsd 0x30(%rsp,%r14,8), %xmm0
movsd %xmm0, 0x10(%rsp)
movq (%r12,%r15,8), %rax
movslq %ebp, %rbx
movq (%r12,%rbx,8), %rcx
movq %rcx, (%r12,%r15,8)
movq %rax, (%r12,%rbx,8)
movq %rbp, 0x18(%rsp)
leal (%rbp,%r13), %eax
pushq $0x2
popq %rcx
cltd
idivl %ecx
movl %eax, 0x24(%rsp)
movslq %r13d, %r15
movq %r13, 0x28(%rsp)
movl %r13d, %ebp
movslq %ebp, %r13
cmpq %rbx, %r15
jge 0x13d94
movq (%r12,%r15,8), %rdx
leaq 0x30(%rsp), %rdi
movq (%rsp), %rsi
callq 0x13a9a
movsd 0x30(%rsp,%r14,8), %xmm0
movsd 0x10(%rsp), %xmm1
ucomisd %xmm0, %xmm1
ja 0x13d7d
ucomisd 0x10(%rsp), %xmm0
jne 0x13d8f
jp 0x13d8f
cmpl 0x24(%rsp), %ebp
jge 0x13d8f
movq (%r12,%r13,8), %rax
movq (%r12,%r15,8), %rcx
movq %rcx, (%r12,%r13,8)
movq %rax, (%r12,%r15,8)
incl %ebp
incq %r15
jmp 0x13d40
movq (%r12,%r13,8), %rax
movq (%r12,%rbx,8), %rcx
movq %rcx, (%r12,%r13,8)
movq %rax, (%r12,%rbx,8)
movq 0x28(%rsp), %rax
cmpl %eax, %r13d
movq %rax, %r13
jne 0x13ddf
movl 0x8(%rsp), %r8d
movl %r8d, %eax
cltd
pushq $0x2
popq %rcx
idivl %ecx
cmpl %r13d, %eax
movl 0xc(%rsp), %ecx
jle 0x13e18
incl %r13d
movq (%rsp), %rdi
movq %r12, %rsi
movl %r8d, %edx
movl %r13d, %r8d
movq 0x18(%rsp), %r9
jmp 0x13e10
movl 0x8(%rsp), %r8d
movl %r8d, %eax
cltd
pushq $0x2
popq %rcx
idivl %ecx
movq 0x18(%rsp), %r9
cmpl %r9d, %ebp
movl 0xc(%rsp), %ecx
jne 0x13e2a
cmpl %r9d, %eax
jge 0x13e33
decl %r9d
movq (%rsp), %rdi
movq %r12, %rsi
movl %r8d, %edx
movl %r13d, %r8d
callq 0x13c86
movl %eax, %r13d
movl %r13d, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpl %eax, %ebp
jne 0x13e38
movl %ebp, %r13d
jmp 0x13e18
movl %r9d, %r13d
jmp 0x13e18
jle 0x13e4e
decl %ebp
movq (%rsp), %rdi
movq %r12, %rsi
movl %r8d, %edx
movl %r13d, %r8d
movl %ebp, %r9d
jmp 0x13e10
incl %ebp
movq (%rsp), %rdi
movq %r12, %rsi
movl %r8d, %edx
movl %ebp, %r8d
jmp 0x13dd8