// File: kingufl[P]Rmapper/src/KDTree.cpp
// Function: KDTree::make_tree(__gnu_cxx::__normal_iterator<std::pair<std::vector<int, std::allocator<int>>, unsigned long>*, std::vector<std::pair<std::vector<int, std::allocator<int>>, unsigned long>, std::allocator<std::pair<std::vector<int, std::allocator<int>>, unsigned long>>>> const&, __gnu_cxx::__normal_iterator<std::pair<std::vector<int, std::allocator<int>>, unsigned long>*, std::vector<std::pair<std::vector<int, std::allocator<int>>, unsigned long>, std::allocator<std::pair<std::vector<int, std::allocator<int>>, unsigned long>>>> const&, unsigned long const&, unsigned long const&)
KDNodePtr KDTree::make_tree(const pointIndexArr::iterator &begin,  //
                            const pointIndexArr::iterator &end,    //
                            const size_t &length,                  //
                            const size_t &level                    //
) {
    if (begin == end) {
        return NewKDNodePtr();  // empty tree
    }

    size_t dim = begin->first.size();

    if (length > 1) {
        sort_on_idx(begin, end, level);
    }

    auto middle = begin + (length / 2);

    auto l_begin = begin;
    auto l_end = middle;
    auto r_begin = middle + 1;
    auto r_end = end;

    size_t l_len = length / 2;
    size_t r_len = length - l_len - 1;

    KDNodePtr left;
    if (l_len > 0 && dim > 0) {
        left = make_tree(l_begin, l_end, l_len, (level + 1) % dim);
    } else {
        left = leaf;
    }
    KDNodePtr right;
    if (r_len > 0 && dim > 0) {
        right = make_tree(r_begin, r_end, r_len, (level + 1) % dim);
    } else {
        right = leaf;
    }

    // KDNode result = KDNode();
    return std::make_shared< KDNode >(*middle, left, right);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xf0, %rsp
movq %rdi, -0xe8(%rbp)
movq %rdi, %rax
movq %rax, -0xe0(%rbp)
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
movq -0x20(%rbp), %rsi
callq 0x5680
testb $0x1, %al
jne 0x3972
jmp 0x3983
movq -0xe8(%rbp), %rdi
callq 0x38c0
jmp 0x3bc3
movq -0x18(%rbp), %rdi
callq 0x56c0
movq %rax, %rdi
callq 0x56e0
movq %rax, -0x38(%rbp)
movq -0x28(%rbp), %rax
cmpq $0x1, (%rax)
jbe 0x39b6
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x30(%rbp), %rax
movq (%rax), %rdx
callq 0x5700
movq -0x18(%rbp), %rdi
movq -0x28(%rbp), %rax
movq (%rax), %rsi
shrq %rsi
callq 0x5790
movq %rax, -0x40(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0x50(%rbp)
leaq -0x40(%rbp), %rdi
movl $0x1, %esi
callq 0x5790
movq %rax, -0x58(%rbp)
movq -0x20(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x60(%rbp)
movq -0x28(%rbp), %rax
movq (%rax), %rax
shrq %rax
movq %rax, -0x68(%rbp)
movq -0x28(%rbp), %rax
movq (%rax), %rax
subq -0x68(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x70(%rbp)
leaq -0x80(%rbp), %rdi
callq 0x5140
cmpq $0x0, -0x68(%rbp)
jbe 0x3aac
cmpq $0x0, -0x38(%rbp)
jbe 0x3aac
movq -0xd8(%rbp), %rsi
movq -0x30(%rbp), %rax
movq (%rax), %rax
incq %rax
movq -0x38(%rbp), %rcx
xorl %edx, %edx
divq %rcx
movq %rdx, -0x98(%rbp)
leaq -0x90(%rbp), %rdi
leaq -0x48(%rbp), %rdx
leaq -0x50(%rbp), %rcx
leaq -0x68(%rbp), %r8
leaq -0x98(%rbp), %r9
callq 0x3920
jmp 0x3a77
leaq -0x80(%rbp), %rdi
leaq -0x90(%rbp), %rsi
callq 0x57d0
leaq -0x90(%rbp), %rdi
callq 0x53e0
jmp 0x3ac0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
jmp 0x3bb8
movq -0xd8(%rbp), %rsi
addq $0x10, %rsi
leaq -0x80(%rbp), %rdi
callq 0x53b0
leaq -0xb8(%rbp), %rdi
callq 0x5140
cmpq $0x0, -0x70(%rbp)
jbe 0x3b65
cmpq $0x0, -0x38(%rbp)
jbe 0x3b65
movq -0xd8(%rbp), %rsi
movq -0x30(%rbp), %rax
movq (%rax), %rax
incq %rax
movq -0x38(%rbp), %rcx
xorl %edx, %edx
divq %rcx
movq %rdx, -0xd0(%rbp)
leaq -0xc8(%rbp), %rdi
leaq -0x58(%rbp), %rdx
leaq -0x60(%rbp), %rcx
leaq -0x70(%rbp), %r8
leaq -0xd0(%rbp), %r9
callq 0x3920
jmp 0x3b24
leaq -0xb8(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x57d0
leaq -0xc8(%rbp), %rdi
callq 0x53e0
jmp 0x3b7c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xa0(%rbp)
movl %eax, -0xa4(%rbp)
leaq -0xb8(%rbp), %rdi
callq 0x53e0
jmp 0x3bb8
movq -0xd8(%rbp), %rsi
addq $0x10, %rsi
leaq -0xb8(%rbp), %rdi
callq 0x53b0
leaq -0x40(%rbp), %rdi
callq 0x5880
movq -0xe8(%rbp), %rdi
movq %rax, %rsi
leaq -0x80(%rbp), %rdx
leaq -0xb8(%rbp), %rcx
callq 0x5800
jmp 0x3ba1
leaq -0xb8(%rbp), %rdi
callq 0x53e0
leaq -0x80(%rbp), %rdi
callq 0x53e0
jmp 0x3bc3
leaq -0x80(%rbp), %rdi
callq 0x53e0
jmp 0x3bd3
movq -0xe0(%rbp), %rax
addq $0xf0, %rsp
popq %rbp
retq
movq -0xa0(%rbp), %rdi
callq 0x33d0
nop