// File: /workspace/github_cpp_makefile_star2_O1/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 $0x58, %rsp
movl %r8d, %r13d
cmpl %r8d, %r9d
je 0x153f3
movl %r9d, %ebp
movl %ecx, %ebx
movq %rsi, %r12
movq %rdi, %r14
movl %edx, 0x8(%rsp)
cvtsi2sd %r13d, %xmm0
movsd %xmm0, 0x18(%rsp)
callq 0x7a508
movl %ebp, %eax
subl %r13d, %eax
incl %eax
cvtsi2sd %eax, %xmm1
mulsd %xmm0, %xmm1
addsd 0x18(%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 0x40(%rsp), %rdi
movq %r14, 0x20(%rsp)
movq %r14, %rsi
callq 0x15044
movl %ebp, %r14d
movl %ebx, 0xc(%rsp)
movslq %ebx, %rbx
movsd 0x40(%rsp,%rbx,8), %xmm0
movsd %xmm0, 0x18(%rsp)
movq (%r12,%r15,8), %rax
movq %rbp, 0x10(%rsp)
movslq %ebp, %rdx
movq (%r12,%rdx,8), %rcx
movq %rcx, (%r12,%r15,8)
movq %rdx, 0x38(%rsp)
movq %rax, (%r12,%rdx,8)
movl %r13d, %ebp
movq %r13, 0x30(%rsp)
subl %r13d, %r14d
jle 0x15370
movq 0x30(%rsp), %rcx
movq 0x10(%rsp), %rax
addl %ecx, %eax
movl %eax, %edx
shrl $0x1f, %edx
addl %eax, %edx
sarl %edx
movl %edx, 0x2c(%rsp)
movslq %ecx, %rax
leaq (%r12,%rax,8), %r15
xorl %r13d, %r13d
movl %ecx, %ebp
movq (%r15,%r13,8), %rdx
leaq 0x40(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x15044
movsd 0x40(%rsp,%rbx,8), %xmm0
movsd 0x18(%rsp), %xmm1
ucomisd %xmm0, %xmm1
ja 0x15353
ucomisd 0x18(%rsp), %xmm0
jne 0x15368
jp 0x15368
cmpl 0x2c(%rsp), %ebp
jge 0x15368
movslq %ebp, %rax
movq (%r12,%rax,8), %rcx
movq (%r15,%r13,8), %rdx
movq %rdx, (%r12,%rax,8)
movq %rcx, (%r15,%r13,8)
incl %ebp
incq %r13
cmpl %r13d, %r14d
jne 0x1531e
movslq %ebp, %rax
movq (%r12,%rax,8), %rcx
movq 0x38(%rsp), %rsi
movq (%r12,%rsi,8), %rdx
movq %rdx, (%r12,%rax,8)
movq %rcx, (%r12,%rsi,8)
movq 0x30(%rsp), %r13
cmpl %r13d, %eax
jne 0x153bd
movl 0x8(%rsp), %edx
movl %edx, %eax
shrl $0x1f, %eax
addl %edx, %eax
sarl %eax
cmpl %r13d, %eax
movl 0xc(%rsp), %ecx
movq 0x20(%rsp), %rdi
jle 0x153f3
incl %r13d
movq %r12, %rsi
movl %r13d, %r8d
movq 0x10(%rsp), %r9
jmp 0x153eb
movl 0x8(%rsp), %edx
movl %edx, %eax
shrl $0x1f, %eax
addl %edx, %eax
sarl %eax
movq 0x10(%rsp), %r9
cmpl %r9d, %ebp
movl 0xc(%rsp), %ecx
movq 0x20(%rsp), %rdi
jne 0x15405
cmpl %r9d, %eax
jge 0x1540e
decl %r9d
movq %r12, %rsi
movl %r13d, %r8d
callq 0x15242
movl %eax, %r13d
movl %r13d, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
cmpl %eax, %ebp
jne 0x15413
movl %ebp, %r13d
jmp 0x153f3
movl %r9d, %r13d
jmp 0x153f3
jle 0x15422
decl %ebp
movq %r12, %rsi
movl %r13d, %r8d
movl %ebp, %r9d
jmp 0x153eb
incl %ebp
movq %r12, %rsi
movl %ebp, %r8d
jmp 0x153b6