// File: gjoni[P]iPot/src/kdtree.cpp
// Function: kd_nearest_i(kdnode*, double const*, kdnode**, double*, kdhyperrect*)
static void kd_nearest_i(struct kdnode *node, const double *pos, struct kdnode **result, double *result_dist_sq, struct kdhyperrect* rect)
{
	int dir = node->dir;
	int i;
	double dummy, dist_sq;
	struct kdnode *nearer_subtree, *farther_subtree;
	double *nearer_hyperrect_coord, *farther_hyperrect_coord;

	/* Decide whether to go left or right in the tree */
	dummy = pos[dir] - node->pos[dir];
	if (dummy <= 0) {
		nearer_subtree = node->left;
		farther_subtree = node->right;
		nearer_hyperrect_coord = rect->max + dir;
		farther_hyperrect_coord = rect->min + dir;
	} else {
		nearer_subtree = node->right;
		farther_subtree = node->left;
		nearer_hyperrect_coord = rect->min + dir;
		farther_hyperrect_coord = rect->max + dir;
	}

	if (nearer_subtree) {
		/* Slice the hyperrect to get the hyperrect of the nearer subtree */
		dummy = *nearer_hyperrect_coord;
		*nearer_hyperrect_coord = node->pos[dir];
		/* Recurse down into nearer subtree */
		kd_nearest_i(nearer_subtree, pos, result, result_dist_sq, rect);
		/* Undo the slice */
		*nearer_hyperrect_coord = dummy;
	}

	/* Check the distance of the point at the current node, compare it
	 * with our best so far */
	dist_sq = 0;
	for(i=0; i < rect->dim; i++) {
		dist_sq += SQ(node->pos[i] - pos[i]);
	}
	if (dist_sq < *result_dist_sq) {
		*result = node;
		*result_dist_sq = dist_sq;
	}

	if (farther_subtree) {
		/* Get the hyperrect of the farther subtree */
		dummy = *farther_hyperrect_coord;
		*farther_hyperrect_coord = node->pos[dir];
		/* Check if we have to recurse down by calculating the closest
		 * point of the hyperrect and see if it's closer than our
		 * minimum distance in result_dist_sq. */
		if (hyperrect_dist_sq(rect, pos) < *result_dist_sq) {
			/* Recurse down into farther subtree */
			kd_nearest_i(farther_subtree, pos, result, result_dist_sq, rect);
		}
		/* Undo the slice on the hyperrect */
		*farther_hyperrect_coord = dummy;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq -0x8(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x8(%rbp), %rax
movq (%rax), %rax
movslq -0x2c(%rbp), %rcx
subsd (%rax,%rcx,8), %xmm0
movsd %xmm0, -0x38(%rbp)
xorps %xmm0, %xmm0
ucomisd -0x38(%rbp), %xmm0
jb 0x31e2a
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x60(%rbp)
jmp 0x31e70
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x28(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq -0x28(%rbp), %rax
movq 0x10(%rax), %rax
movslq -0x2c(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x60(%rbp)
cmpq $0x0, -0x48(%rbp)
je 0x31ec2
movq -0x58(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x38(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rax
movslq -0x2c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x58(%rbp), %rax
movsd %xmm0, (%rax)
movq -0x48(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %r8
callq 0x31d90
movsd -0x38(%rbp), %xmm0
movq -0x58(%rbp), %rax
movsd %xmm0, (%rax)
xorps %xmm0, %xmm0
movsd %xmm0, -0x40(%rbp)
movl $0x0, -0x30(%rbp)
movl -0x30(%rbp), %eax
movq -0x28(%rbp), %rcx
cmpl (%rcx), %eax
jge 0x31f33
movq -0x8(%rbp), %rax
movq (%rax), %rax
movslq -0x30(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x10(%rbp), %rax
movslq -0x30(%rbp), %rcx
subsd (%rax,%rcx,8), %xmm0
movq -0x8(%rbp), %rax
movq (%rax), %rax
movslq -0x30(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm2
movq -0x10(%rbp), %rax
movslq -0x30(%rbp), %rcx
subsd (%rax,%rcx,8), %xmm2
movsd -0x40(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x40(%rbp)
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x31ed1
movsd -0x40(%rbp), %xmm1
movq -0x20(%rbp), %rax
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x31f5e
movq -0x8(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movsd -0x40(%rbp), %xmm0
movq -0x20(%rbp), %rax
movsd %xmm0, (%rax)
cmpq $0x0, -0x50(%rbp)
je 0x31fce
movq -0x60(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x38(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rax
movslq -0x2c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x60(%rbp), %rax
movsd %xmm0, (%rax)
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq 0x32b20
movaps %xmm0, %xmm1
movq -0x20(%rbp), %rax
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x31fc1
movq -0x50(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %r8
callq 0x31d90
movsd -0x38(%rbp), %xmm0
movq -0x60(%rbp), %rax
movsd %xmm0, (%rax)
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)