// File: /workspace/github_cpp_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movq %rsi, -0x88(%rbp)
movq %rdi, %rbx
movq (%rdx), %rsi
movq 0x8(%rsi), %rax
cmpq 0x10(%rsi), %rax
je 0x3c40
movq %r8, %r13
movq %rcx, %r12
movq %r9, -0x38(%rbp)
movq %rdx, -0x60(%rbp)
movq %rbx, -0x58(%rbp)
addq $0x8, %rsi
leaq -0xc8(%rbp), %rbx
movq %rbx, %rdi
callq 0x45ba
movq 0x8(%rbx), %r14
subq (%rbx), %r14
movq %rbx, %rdi
movq %r12, %rsi
callq 0x46ed
movl %eax, %ebx
movq (%r13), %rsi
leaq -0xc8(%rbp), %rdi
callq 0x4598
movl (%rax), %r15d
movq (%r13), %rsi
movq %r12, %rdi
callq 0x4752
movq %r12, -0x40(%rbp)
sarq $0x2, %r14
subl (%rax), %r15d
movq -0x58(%rbp), %r12
movq %r12, %rdi
movq -0x38(%rbp), %rsi
callq 0x54ee
movq 0x10(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x2c(%rbp)
movl %eax, -0x38(%rbp)
cmpl %eax, %ebx
jge 0x3b76
movl %ebx, -0x2c(%rbp)
movq %r12, %rdi
movq -0x60(%rbp), %rsi
callq 0x487e
movl %ebx, -0x38(%rbp)
movq (%r13), %rax
incq %rax
xorl %edx, %edx
divq %r14
leaq -0x68(%rbp), %rax
movq %rdx, (%rax)
xorps %xmm0, %xmm0
leaq -0xa0(%rbp), %rbx
movaps %xmm0, (%rbx)
leaq -0x80(%rbp), %rax
movaps %xmm0, (%rax)
xorl %r14d, %r14d
xorl %eax, %eax
testl %r15d, %r15d
setg %r14b
setle %al
movq -0x60(%rbp), %r13
movq (%r13), %rcx
shll $0x4, %eax
shll $0x4, %r14d
leaq (%rcx,%rax), %rsi
addq $0x20, %rsi
movq %rbx, %rdi
callq 0x487e
movq (%r13), %rax
leaq (%rax,%r14), %rsi
addq $0x20, %rsi
leaq -0x80(%rbp), %rdi
callq 0x487e
leaq -0x2c(%rbp), %r14
movq %r14, (%rsp)
leaq -0x50(%rbp), %rdi
movq -0x88(%rbp), %r13
movq %r13, %rsi
movq %rbx, %rdx
movq -0x40(%rbp), %rcx
leaq -0x68(%rbp), %r8
movq %r12, %r9
callq 0x3ab2
movq -0x50(%rbp), %rdi
movq 0x8(%rdi), %rax
cmpq 0x10(%rdi), %rax
je 0x3c50
addq $0x8, %rdi
movq -0x40(%rbp), %rsi
callq 0x46ed
movl %eax, %ebx
movl -0x38(%rbp), %eax
cmpl %eax, %ebx
jge 0x3c53
movl %ebx, -0x2c(%rbp)
leaq -0x50(%rbp), %rsi
movq %r12, %rdi
callq 0x487e
movl %ebx, %eax
jmp 0x3c53
movq %rbx, %rdi
callq 0x4630
movq %rbx, %rax
jmp 0x3cf8
movl -0x38(%rbp), %eax
imull %r15d, %r15d
cmpl %eax, %r15d
jge 0x3ccb
movl %eax, %r15d
movq %r14, (%rsp)
leaq -0xb0(%rbp), %rdi
leaq -0x80(%rbp), %rdx
leaq -0x68(%rbp), %r8
movq %r13, %rsi
movq -0x40(%rbp), %rcx
movq %r12, %r9
callq 0x3ab2
leaq -0x50(%rbp), %rbx
leaq -0xb0(%rbp), %rsi
movq %rbx, %rdi
callq 0x5790
leaq -0xa8(%rbp), %rdi
callq 0x4978
movq (%rbx), %rdi
movq 0x8(%rdi), %rax
cmpq 0x10(%rdi), %rax
je 0x3ccb
addq $0x8, %rdi
movq -0x40(%rbp), %rsi
callq 0x46ed
cmpl %r15d, %eax
jge 0x3ccb
leaq -0x50(%rbp), %rsi
movq %r12, %rdi
callq 0x487e
leaq -0x48(%rbp), %rdi
callq 0x4978
leaq -0x78(%rbp), %rdi
callq 0x4978
leaq -0x98(%rbp), %rdi
callq 0x4978
leaq -0xc8(%rbp), %rdi
callq 0x552c
movq %r12, %rax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x3d0e
jmp 0x3d0e
movq %rax, %r14
leaq -0x48(%rbp), %rdi
callq 0x4978
jmp 0x3d1f
movq %rax, %r14
leaq -0x78(%rbp), %rdi
callq 0x4978
leaq -0x98(%rbp), %rdi
callq 0x4978
movq -0x58(%rbp), %rdi
addq $0x8, %rdi
callq 0x4978
jmp 0x3d46
movq %rax, %r14
leaq -0xc8(%rbp), %rdi
callq 0x552c
movq %r14, %rdi
callq 0x3380