// File: 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:
subq $0xb8, %rsp
movq %rdi, 0xa8(%rsp)
movq %rsi, 0xa0(%rsp)
movl %edx, 0x9c(%rsp)
movl %ecx, 0x98(%rsp)
movl %r8d, 0x94(%rsp)
movl %r9d, 0x90(%rsp)
movq 0xa8(%rsp), %rax
movq %rax, 0x18(%rsp)
movl 0x94(%rsp), %eax
cmpl 0x90(%rsp), %eax
jne 0x19055
movl 0x94(%rsp), %eax
movl %eax, 0xb4(%rsp)
jmp 0x194fc
cvtsi2sdl 0x94(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
callq 0xe1930
movsd 0x10(%rsp), %xmm1
movl 0x90(%rsp), %eax
subl 0x94(%rsp), %eax
addl $0x1, %eax
cvtsi2sd %eax, %xmm2
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movl %eax, 0x8c(%rsp)
movl 0x8c(%rsp), %eax
cmpl 0x94(%rsp), %eax
jge 0x190b5
movl 0x94(%rsp), %eax
movl %eax, 0x8c(%rsp)
movl 0x8c(%rsp), %eax
cmpl 0x90(%rsp), %eax
jle 0x190d3
movl 0x90(%rsp), %eax
movl %eax, 0x8c(%rsp)
movq 0x18(%rsp), %rsi
movq 0xa0(%rsp), %rax
movslq 0x8c(%rsp), %rcx
movq (%rax,%rcx,8), %rdx
leaq 0x68(%rsp), %rdi
callq 0x18bc0
movl 0x98(%rsp), %esi
leaq 0x68(%rsp), %rdi
callq 0x17e60
movsd %xmm0, 0x80(%rsp)
movq 0xa0(%rsp), %rax
movslq 0x8c(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x60(%rsp)
movq 0xa0(%rsp), %rax
movslq 0x90(%rsp), %rcx
movq (%rax,%rcx,8), %rdx
movq 0xa0(%rsp), %rax
movslq 0x8c(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movq 0x60(%rsp), %rdx
movq 0xa0(%rsp), %rax
movslq 0x90(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movl 0x94(%rsp), %eax
movl %eax, 0x5c(%rsp)
movl 0x94(%rsp), %eax
addl 0x90(%rsp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, 0x58(%rsp)
movl 0x94(%rsp), %eax
movl %eax, 0x54(%rsp)
movl 0x54(%rsp), %eax
cmpl 0x90(%rsp), %eax
jge 0x192de
movq 0x18(%rsp), %rsi
movq 0xa0(%rsp), %rax
movslq 0x54(%rsp), %rcx
movq (%rax,%rcx,8), %rdx
leaq 0x30(%rsp), %rdi
callq 0x18bc0
movl 0x98(%rsp), %esi
leaq 0x30(%rsp), %rdi
callq 0x17e60
movsd %xmm0, 0x48(%rsp)
movsd 0x48(%rsp), %xmm1
movsd 0x80(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x19252
movq 0xa0(%rsp), %rax
movslq 0x5c(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x28(%rsp)
movq 0xa0(%rsp), %rax
movslq 0x54(%rsp), %rcx
movq (%rax,%rcx,8), %rdx
movq 0xa0(%rsp), %rax
movslq 0x5c(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movq 0x28(%rsp), %rdx
movq 0xa0(%rsp), %rax
movslq 0x54(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movl 0x5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x5c(%rsp)
jmp 0x192cc
movsd 0x48(%rsp), %xmm0
ucomisd 0x80(%rsp), %xmm0
jne 0x192ca
jp 0x192ca
movl 0x5c(%rsp), %eax
cmpl 0x58(%rsp), %eax
jge 0x192c8
movq 0xa0(%rsp), %rax
movslq 0x5c(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x20(%rsp)
movq 0xa0(%rsp), %rax
movslq 0x54(%rsp), %rcx
movq (%rax,%rcx,8), %rdx
movq 0xa0(%rsp), %rax
movslq 0x5c(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movq 0x20(%rsp), %rdx
movq 0xa0(%rsp), %rax
movslq 0x54(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movl 0x5c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x5c(%rsp)
jmp 0x192ca
jmp 0x192cc
jmp 0x192ce
movl 0x54(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x54(%rsp)
jmp 0x1919a
movq 0xa0(%rsp), %rax
movslq 0x5c(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0x60(%rsp)
movq 0xa0(%rsp), %rax
movslq 0x90(%rsp), %rcx
movq (%rax,%rcx,8), %rdx
movq 0xa0(%rsp), %rax
movslq 0x5c(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movq 0x60(%rsp), %rdx
movq 0xa0(%rsp), %rax
movslq 0x90(%rsp), %rcx
movq %rdx, (%rax,%rcx,8)
movl 0x5c(%rsp), %eax
cmpl 0x94(%rsp), %eax
jne 0x193b6
movl 0x94(%rsp), %eax
movl %eax, 0xc(%rsp)
movl 0x9c(%rsp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl 0xc(%rsp), %eax
cmpl %ecx, %eax
jl 0x19376
movl 0x94(%rsp), %eax
movl %eax, 0xb4(%rsp)
jmp 0x194fc
movq 0x18(%rsp), %rdi
movq 0xa0(%rsp), %rsi
movl 0x9c(%rsp), %edx
movl 0x98(%rsp), %ecx
movl 0x94(%rsp), %r8d
addl $0x1, %r8d
movl 0x90(%rsp), %r9d
callq 0x18ff0
movl %eax, 0xb4(%rsp)
jmp 0x194fc
movl 0x5c(%rsp), %eax
cmpl 0x90(%rsp), %eax
jne 0x1943a
movl 0x90(%rsp), %eax
movl %eax, 0x8(%rsp)
movl 0x9c(%rsp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl 0x8(%rsp), %eax
cmpl %ecx, %eax
jg 0x193fa
movl 0x90(%rsp), %eax
movl %eax, 0xb4(%rsp)
jmp 0x194fc
movq 0x18(%rsp), %rdi
movq 0xa0(%rsp), %rsi
movl 0x9c(%rsp), %edx
movl 0x98(%rsp), %ecx
movl 0x94(%rsp), %r8d
movl 0x90(%rsp), %r9d
subl $0x1, %r9d
callq 0x18ff0
movl %eax, 0xb4(%rsp)
jmp 0x194fc
movl 0x5c(%rsp), %eax
movl %eax, 0x4(%rsp)
movl 0x9c(%rsp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl 0x4(%rsp), %eax
cmpl %ecx, %eax
jne 0x1946b
movl 0x5c(%rsp), %eax
movl %eax, 0xb4(%rsp)
jmp 0x194fc
movl 0x5c(%rsp), %eax
movl %eax, (%rsp)
movl 0x9c(%rsp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movl (%rsp), %eax
cmpl %ecx, %eax
jle 0x194c4
movq 0x18(%rsp), %rdi
movq 0xa0(%rsp), %rsi
movl 0x9c(%rsp), %edx
movl 0x98(%rsp), %ecx
movl 0x94(%rsp), %r8d
movl 0x5c(%rsp), %r9d
subl $0x1, %r9d
callq 0x18ff0
movl %eax, 0xb4(%rsp)
jmp 0x194fc
movq 0x18(%rsp), %rdi
movq 0xa0(%rsp), %rsi
movl 0x9c(%rsp), %edx
movl 0x98(%rsp), %ecx
movl 0x5c(%rsp), %r8d
addl $0x1, %r8d
movl 0x90(%rsp), %r9d
callq 0x18ff0
movl %eax, 0xb4(%rsp)
movl 0xb4(%rsp), %eax
addq $0xb8, %rsp
retq
nopl (%rax,%rax)