// File: kingufl[P]Rmapper/src/KDTree.cpp
// Function: KDTree::nearest_(std::shared_ptr<KDNode> const&, std::vector<int, std::allocator<int>> const&, unsigned long const&, std::shared_ptr<KDNode> const&, int const&)
KDNodePtr KDTree::nearest_(   //
    const KDNodePtr &branch,  //
    const point_t &pt,        //
    const size_t &level,      //
    const KDNodePtr &best,    //
    const int &best_dist   //
) {
    int d, dx, dx2;

    if (!bool(*branch)) {
        return NewKDNodePtr();  // basically, null
    }

    point_t branch_pt(*branch);
    size_t dim = branch_pt.size();

    d = dist2(branch_pt, pt);
    dx = branch_pt.at(level) - pt.at(level);
    dx2 = dx * dx;

    KDNodePtr best_l = best;
    int best_dist_l = best_dist;

    if (d < best_dist) {
        best_dist_l = d;
        best_l = branch;
    }

    size_t next_lv = (level + 1) % dim;
    KDNodePtr section;
    KDNodePtr other;

    // select which branch makes sense to check
    if (dx > 0) {
        section = branch->left;
        other = branch->right;
    } else {
        section = branch->right;
        other = branch->left;
    }

    // keep nearest neighbor from further down the tree
    KDNodePtr further = nearest_(section, pt, next_lv, best_l, best_dist_l);
    if (!further->x.empty()) {
        int dl = dist2(further->x, pt);
        if (dl < best_dist_l) {
            best_dist_l = dl;
            best_l = further;
        }
    }
    // only check the other branch if it makes sense to do so
    if (dx2 < best_dist_l) {
        further = nearest_(other, pt, next_lv, best_l, best_dist_l);
        if (!further->x.empty()) {
            int dl = dist2(further->x, pt);
            if (dl < best_dist_l) {
                best_dist_l = dl;
                best_l = further;
            }
        }
    }

    return best_l;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x120, %rsp            # imm = 0x120
movq %rdi, -0xe8(%rbp)
movq %rdi, %rax
movq %rax, -0xe0(%rbp)
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xd8(%rbp)
movq -0x18(%rbp), %rdi
callq 0x5a60
movq %rax, %rdi
callq 0x3800
testb $0x1, %al
jne 0x3e59
movq -0xe8(%rbp), %rdi
callq 0x38c0
jmp 0x4228
movq -0x18(%rbp), %rdi
callq 0x5a60
movq %rax, %rsi
leaq -0x58(%rbp), %rdi
movq %rdi, -0xf8(%rbp)
callq 0x3830
movq -0xf8(%rbp), %rdi
callq 0x56e0
movq -0xf8(%rbp), %rdi
movq %rax, -0x60(%rbp)
movq -0x20(%rbp), %rsi
callq 0x5a90
movl %eax, -0xec(%rbp)
jmp 0x3e9d
movl -0xec(%rbp), %eax
movl %eax, -0x34(%rbp)
movq -0x28(%rbp), %rax
movq (%rax), %rsi
leaq -0x58(%rbp), %rdi
callq 0x5460
movq %rax, -0x100(%rbp)
jmp 0x3ebf
movq -0x100(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x10c(%rbp)
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rax
movq (%rax), %rsi
callq 0x5b20
movq %rax, -0x108(%rbp)
jmp 0x3ee7
movq -0xe8(%rbp), %rdi
movq -0x108(%rbp), %rcx
movl -0x10c(%rbp), %eax
subl (%rcx), %eax
movl %eax, -0x38(%rbp)
movl -0x38(%rbp), %eax
imull -0x38(%rbp), %eax
movl %eax, -0x3c(%rbp)
movb $0x0, -0x6d(%rbp)
movq -0x30(%rbp), %rsi
callq 0x5b60
movq 0x10(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x74(%rbp)
movl -0x34(%rbp), %eax
movq 0x10(%rbp), %rcx
cmpl (%rcx), %eax
jge 0x3f54
movq -0xe8(%rbp), %rdi
movl -0x34(%rbp), %eax
movl %eax, -0x74(%rbp)
movq -0x18(%rbp), %rsi
callq 0x53b0
jmp 0x3f54
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
jmp 0x421d
movq -0x28(%rbp), %rax
movq (%rax), %rax
addq $0x1, %rax
xorl %ecx, %ecx
movl %ecx, %edx
divq -0x60(%rbp)
movq %rdx, -0x80(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x5140
leaq -0xa0(%rbp), %rdi
callq 0x5140
cmpl $0x0, -0x38(%rbp)
jle 0x3fc3
movq -0x18(%rbp), %rdi
callq 0x5b90
movq %rax, %rsi
addq $0x20, %rsi
leaq -0x90(%rbp), %rdi
callq 0x53b0
movq -0x18(%rbp), %rdi
callq 0x5b90
movq %rax, %rsi
addq $0x30, %rsi
leaq -0xa0(%rbp), %rdi
callq 0x53b0
jmp 0x3ffb
movq -0x18(%rbp), %rdi
callq 0x5b90
movq %rax, %rsi
addq $0x30, %rsi
leaq -0x90(%rbp), %rdi
callq 0x53b0
movq -0x18(%rbp), %rdi
callq 0x5b90
movq %rax, %rsi
addq $0x20, %rsi
leaq -0xa0(%rbp), %rdi
callq 0x53b0
movq -0xe8(%rbp), %r9
movq -0xd8(%rbp), %rsi
movq -0x20(%rbp), %rcx
movq %rsp, %rax
leaq -0x74(%rbp), %rdx
movq %rdx, (%rax)
leaq -0xb0(%rbp), %rdi
leaq -0x90(%rbp), %rdx
leaq -0x80(%rbp), %r8
callq 0x3df0
jmp 0x4030
leaq -0xb0(%rbp), %rdi
callq 0x5b90
movq %rax, %rdi
addq $0x8, %rdi
callq 0x54a0
testb $0x1, %al
jne 0x40d9
leaq -0xb0(%rbp), %rdi
callq 0x5b90
movq %rax, %rdi
addq $0x8, %rdi
movq -0x20(%rbp), %rsi
callq 0x5a90
movl %eax, -0x110(%rbp)
jmp 0x4074
movl -0x110(%rbp), %eax
movl %eax, -0xb4(%rbp)
movl -0xb4(%rbp), %eax
cmpl -0x74(%rbp), %eax
jge 0x40d7
movq -0xe8(%rbp), %rdi
movl -0xb4(%rbp), %eax
movl %eax, -0x74(%rbp)
leaq -0xb0(%rbp), %rsi
callq 0x53b0
jmp 0x40d7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
jmp 0x41e0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x53e0
jmp 0x41e0
jmp 0x40d9
movl -0x3c(%rbp), %eax
cmpl -0x74(%rbp), %eax
jge 0x41b0
movq -0xe8(%rbp), %r9
movq -0xd8(%rbp), %rsi
movq -0x20(%rbp), %rcx
movq %rsp, %rax
leaq -0x74(%rbp), %rdx
movq %rdx, (%rax)
leaq -0xc8(%rbp), %rdi
leaq -0xa0(%rbp), %rdx
leaq -0x80(%rbp), %r8
callq 0x3df0
jmp 0x411a
leaq -0xb0(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x57d0
leaq -0xc8(%rbp), %rdi
callq 0x53e0
leaq -0xb0(%rbp), %rdi
callq 0x5b90
movq %rax, %rdi
addq $0x8, %rdi
callq 0x54a0
testb $0x1, %al
jne 0x41ae
leaq -0xb0(%rbp), %rdi
callq 0x5b90
movq %rax, %rdi
addq $0x8, %rdi
movq -0x20(%rbp), %rsi
callq 0x5a90
movl %eax, -0x114(%rbp)
jmp 0x4179
movl -0x114(%rbp), %eax
movl %eax, -0xcc(%rbp)
movl -0xcc(%rbp), %eax
cmpl -0x74(%rbp), %eax
jge 0x41ac
movq -0xe8(%rbp), %rdi
movl -0xcc(%rbp), %eax
movl %eax, -0x74(%rbp)
leaq -0xb0(%rbp), %rsi
callq 0x53b0
jmp 0x41ae
jmp 0x41b0
movb $0x1, -0x6d(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x53e0
leaq -0xa0(%rbp), %rdi
callq 0x53e0
leaq -0x90(%rbp), %rdi
callq 0x53e0
testb $0x1, -0x6d(%rbp)
jne 0x4212
jmp 0x4206
leaq -0xa0(%rbp), %rdi
callq 0x53e0
leaq -0x90(%rbp), %rdi
callq 0x53e0
movq -0xe8(%rbp), %rdi
callq 0x53e0
jmp 0x421d
movq -0xe8(%rbp), %rdi
callq 0x53e0
leaq -0x58(%rbp), %rdi
callq 0x5400
jmp 0x4228
leaq -0x58(%rbp), %rdi
callq 0x5400
jmp 0x4238
movq -0xe0(%rbp), %rax
addq $0x120, %rsp            # imm = 0x120
popq %rbp
retq
movq -0x68(%rbp), %rdi
callq 0x33d0
nopw %cs:(%rax,%rax)