// File: /workspace/github_cpp_makefile_star2_O3/cfiutak1[P]HPyC-KD-Tree/./utils/filewriter/../../src/kdtree/KDTree.hpp
// Function: hpyc::KDTree<float>::buildTree(unsigned long, unsigned long, unsigned int)
void KDTree<ItemT>::buildTree(const std::size_t subarray_begin, const std::size_t subarray_end, const unsigned int depth) {
    std::size_t range = subarray_end - subarray_begin;

    // Base case - If there is one element left, it is already sorted and thus in its correct position.
    if (range == 1) { return; }

    // Base case - If there are two elements left, they will be in their correct positions if they are sorted.
    else if (range == 2) {
        if (this->nodes[depth][subarray_begin] > this->nodes[depth][subarray_begin + 1]) {
            this->swap(subarray_begin, subarray_begin + 1);
        }

        return;
    }

    else if (range == 3) {
        AdaptiveCacheAwareBlockquickselect<ItemT> qs(this->nodes, this->num_dimensions, depth);
        qs.sort3(subarray_begin);

        return;
    }

    // Partition the current subarray around the median at the current dimension.
    AdaptiveCacheAwareBlockquickselect<ItemT> qs(this->nodes, this->num_dimensions, depth);
    qs.nth_element(subarray_begin, subarray_end, (range / 2));

    unsigned int new_depth = (depth + 1) & (-1 + (depth == this->num_dimensions - 1));

    // Build left subtree (all elements left of the median)
    this->buildTree(subarray_begin, subarray_begin + (range / 2), new_depth);

    // Build right subtree (all elements right of the median)
    this->buildTree(subarray_begin + (range / 2) + 1, subarray_end, new_depth);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdx, %r12
subq %rsi, %r12
cmpq $0x1, %r12
je 0x3504
movl %ecx, %ebp
movq %rsi, %rbx
movq %rdi, %r14
cmpq $0x3, %r12
je 0x33eb
cmpq $0x2, %r12
jne 0x34a2
movq 0x8(%r14), %rax
movl %ebp, %ecx
movq (%rax,%rcx,8), %rcx
movss (%rcx,%rbx,4), %xmm0
ucomiss 0x4(%rcx,%rbx,4), %xmm0
jbe 0x3504
movq 0x18(%r14), %rcx
testq %rcx, %rcx
je 0x3504
xorl %edx, %edx
movq (%rax,%rdx,8), %rsi
movsd (%rsi,%rbx,4), %xmm0
shufps $0xe1, %xmm0, %xmm0     # xmm0 = xmm0[1,0,2,3]
movlps %xmm0, (%rsi,%rbx,4)
incq %rdx
cmpq %rdx, %rcx
jne 0x33cd
jmp 0x3504
movq 0x8(%r14), %rax
movq 0x18(%r14), %rcx
movl %ebp, %edx
movq (%rax,%rdx,8), %rdx
movss 0x4(%rdx,%rbx,4), %xmm0
ucomiss 0x8(%rdx,%rbx,4), %xmm0
jbe 0x3432
testq %rcx, %rcx
je 0x3504
xorl %esi, %esi
movq (%rax,%rsi,8), %rdi
movsd 0x4(%rdi,%rbx,4), %xmm0
shufps $0xe1, %xmm0, %xmm0     # xmm0 = xmm0[1,0,2,3]
movlps %xmm0, 0x4(%rdi,%rbx,4)
incq %rsi
cmpq %rsi, %rcx
jne 0x3411
movss 0x4(%rdx,%rbx,4), %xmm0
movss (%rdx,%rbx,4), %xmm1
ucomiss %xmm0, %xmm1
setbe %sil
testq %rcx, %rcx
sete %dil
orb %sil, %dil
jne 0x346b
xorl %esi, %esi
movq (%rax,%rsi,8), %rdi
movsd (%rdi,%rbx,4), %xmm0
shufps $0xe1, %xmm0, %xmm0     # xmm0 = xmm0[1,0,2,3]
movlps %xmm0, (%rdi,%rbx,4)
incq %rsi
cmpq %rsi, %rcx
jne 0x344c
movss 0x4(%rdx,%rbx,4), %xmm0
ucomiss 0x8(%rdx,%rbx,4), %xmm0
setbe %dl
testq %rcx, %rcx
sete %sil
orb %dl, %sil
jne 0x3504
xorl %edx, %edx
movq (%rax,%rdx,8), %rsi
movsd 0x4(%rsi,%rbx,4), %xmm0
shufps $0xe1, %xmm0, %xmm0     # xmm0 = xmm0[1,0,2,3]
movlps %xmm0, 0x4(%rsi,%rbx,4)
incq %rdx
cmpq %rdx, %rcx
jne 0x3485
jmp 0x3504
movq %rdx, %r15
movq 0x8(%r14), %rax
movq 0x18(%r14), %rcx
movq %rsp, %rdi
movq %rax, (%rdi)
movq %rcx, 0x8(%rdi)
movl %ebp, 0x10(%rdi)
shrq %r12
movq %rbx, %rsi
movq %r12, %rcx
callq 0x3514
movl %ebp, %eax
incl %ebp
movq 0x18(%r14), %rcx
decq %rcx
xorl %r13d, %r13d
cmpq %rax, %rcx
cmovnel %ebp, %r13d
leaq (%r12,%rbx), %rdx
movq %r14, %rdi
movq %rbx, %rsi
movl %r13d, %ecx
callq 0x336e
leaq (%r12,%rbx), %rsi
incq %rsi
movq %r14, %rdi
movq %r15, %rdx
movl %r13d, %ecx
callq 0x336e
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop