// File: /workspace/github_cpp_makefile_star2_O2/cfiutak1[P]HPyC-KD-Tree/./utils/filewriter/../../src/kdtree/../quickselect/AdaptiveCacheAwareBlockquickselect.hpp
// Function: hpyc::AdaptiveCacheAwareBlockquickselect<float, 64ul, 64ul>::selectPivotAndPartitionArray(unsigned long, unsigned long, unsigned long const&, unsigned long)
inline std::size_t selectPivotAndPartitionArray(std::size_t begin, std::size_t end, const std::size_t& k, std::size_t offset) {
        constexpr std::size_t AdaptiveSampleThreshold = 2 * ItemsPerCacheLine;

        std::size_t chunk_size = end - begin;
        std::size_t sample_size = sqrt(chunk_size);

        // If the sample size is smaller than the threshold for adaptive sampling, fall back to median of 3 pivot selection
        // and use dynamic block partitioning.
        if (sample_size < AdaptiveSampleThreshold) {
            std::size_t pivot = medianOf3(begin, end);

            return dynamicBlockPartition(pivot, begin + 2, end - 2);
        }

        // The samples are moved to the beginning of the array, and of those samples, the pivot_pos-th largest sample is
        // chosen to be the pivot. The pivot position is determined by the size of k relative to the size of the chunk to partition.
        float pivot_ratio = float(k) / chunk_size;
        std::size_t pivot_pos = pivot_ratio * sample_size;

        // If the pivot position is large enough to make it viable, adjust the pivot position so that the pivot position is
        // the closest power of ItemsPerCacheLine, minus 1. The sample size is also adjusted to maintain the original
        // pivot position : sample size ratio.

        if (pivot_pos >= (AdaptiveSampleThreshold)) {
            // Round the pivot position to the closest power of ItemsPerCacheLine, minus 1
            if (((pivot_pos % ItemsPerCacheLine) >= (ItemsPerCacheLine / 2)) || (pivot_pos < ItemsPerCacheLine)) {
                pivot_pos += ((ItemsPerCacheLine - 1) - (pivot_pos % ItemsPerCacheLine));
            }

            else {
                pivot_pos -= ((pivot_pos % ItemsPerCacheLine) + 1);
            }

            // Account for the offset of the array chunk. For example, if the chunk begins at ItemsPerCacheLine + 3,
            // this will subtract 3 from the pivot position so that the unpartitioned range begins on the start of a cache
            // line.
            if (pivot_pos <= offset) { pivot_pos += (ItemsPerCacheLine - offset); }
            else { pivot_pos -= offset; }

            // Adjust the sample size based on changes to the pivot position.
            sample_size = std::ceil(float(pivot_pos) / pivot_ratio);
        }

        // Use the beginning and end of (sample size / 2) cache lines as the samples.
        for (std::size_t i = 0; i < (sample_size >> 1); ++i) {
            this->swap(begin + (i << 1), begin + (ItemsPerCacheLine * i));
            this->swap(begin + (i << 1) + 1, begin + (ItemsPerCacheLine * i) + (ItemsPerCacheLine - 1));
        }

        // If the sample size is odd, we'll just be lazy and use whatever value is already at begin + sample_size - 1. It's random enough.

        // Find the pivot_pos-th element of the sampled items.
        nth_element(begin, begin + sample_size, pivot_pos);

        // Swap all items in the sample slice that are !comp() to the pivot with items at the end of the chunk.
        for (std::size_t i = 0; i < this->num_dimensions; ++i) {
            std::swap_ranges(
                this->nodes[i] + (begin + pivot_pos + 1),
                this->nodes[i] + (begin + sample_size),
                this->nodes[i] + (end - (sample_size - pivot_pos) + 1)
            );
        }

        // Partition items between [pivot + 1, !comp() mini partition begin)
        if ((end - begin) - sample_size > (BlockSize << 1u)) {
            return staticBlockPartition(begin + pivot_pos, begin + pivot_pos + 1, end - (sample_size - pivot_pos) + 1);
        }

        else {
            return dynamicBlockPartition(begin + pivot_pos, begin + pivot_pos + 1, end - (sample_size - pivot_pos) + 1);
        }
    }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdx, %rbx
movq %rsi, %rbp
movq %rdx, %rsi
subq %rbp, %rsi
movq %rsi, %xmm0
punpckldq 0x1d79(%rip), %xmm0 # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
subpd 0x1d81(%rip), %xmm0     # 0x5030
movq %rdi, %r15
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
sqrtsd %xmm1, %xmm0
cvttsd2si %xmm0, %rax
movq %rax, %rdx
subsd 0x1d3e(%rip), %xmm0     # 0x5010
cvttsd2si %xmm0, %rdi
sarq $0x3f, %rdx
andq %rdx, %rdi
orq %rax, %rdi
cmpq $0x1f, %rdi
ja 0x330e
movq %r15, %rdi
movq %rbp, %rsi
movq %rbx, %rdx
callq 0x3514
addq $0x2, %rbp
addq $-0x2, %rbx
movq %r15, %rdi
movq %rax, %rsi
movq %rbp, %rdx
movq %rbx, %rcx
jmp 0x3501
movq (%rcx), %rax
testq %rax, %rax
js 0x331d
cvtsi2ss %rax, %xmm1
jmp 0x3332
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm1
addss %xmm1, %xmm1
testq %rsi, %rsi
js 0x333e
cvtsi2ss %rsi, %xmm0
jmp 0x3355
movq %rsi, %rax
shrq %rax
movl %esi, %ecx
andl $0x1, %ecx
orq %rax, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
divss %xmm0, %xmm1
testq %rdi, %rdi
js 0x3365
cvtsi2ss %rdi, %xmm0
jmp 0x337c
movq %rdi, %rax
shrq %rax
movl %edi, %ecx
andl $0x1, %ecx
orq %rax, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
mulss %xmm1, %xmm0
cvttss2si %xmm0, %rax
movq %rax, %rcx
subss 0x1cb0(%rip), %xmm0     # 0x5040
cvttss2si %xmm0, %r12
sarq $0x3f, %rcx
andq %rcx, %r12
orq %rax, %r12
cmpq $0x20, %r12
movq %rbx, 0x8(%rsp)
movq %rsi, 0x10(%rsp)
jb 0x341f
movl %r12d, %eax
andl $0xf, %eax
xorl %ecx, %ecx
cmpq $0x8, %rax
sbbq %rcx, %rcx
orq $0xf, %rcx
xorq %rax, %rcx
addq %r12, %rcx
subq %r8, %rcx
leaq 0x10(%rcx), %r12
cmovaq %rcx, %r12
testq %r12, %r12
js 0x33df
cvtsi2ss %r12, %xmm0
jmp 0x33f7
movq %r12, %rax
shrq %rax
movl %r12d, %ecx
andl $0x1, %ecx
orq %rax, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
divss %xmm1, %xmm0
callq 0x20c0
cvttss2si %xmm0, %rax
movq %rax, %rcx
sarq $0x3f, %rcx
subss 0x1c2c(%rip), %xmm0     # 0x5040
cvttss2si %xmm0, %rdi
andq %rcx, %rdi
orq %rax, %rdi
movq %rdi, (%rsp)
movq %rdi, %rbx
shrq %rbx
movq %rbp, %r13
movq %rbp, %r14
subq $0x1, %rbx
jb 0x345d
movq %r15, %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x3250
leaq 0x1(%r13), %rsi
leaq 0xf(%rbp), %rdx
movq %r15, %rdi
callq 0x3250
addq $0x10, %rbp
addq $0x2, %r13
jmp 0x342f
movq %r14, %rsi
movq (%rsp), %rbp
leaq (%r14,%rbp), %r13
movq %r15, %rdi
movq %r13, %rdx
movq %r12, %rcx
callq 0x311e
movq %r12, %rbx
subq %rbp, %rbx
xorl %ebp, %ebp
cmpq 0x8(%r15), %rbp
jae 0x34b6
movq (%r15), %rax
movq (%rax,%rbp,8), %rax
leaq (%rax,%r12,4), %rcx
leaq (%rcx,%r14,4), %rdi
addq $0x4, %rdi
leaq (%rax,%r13,4), %rsi
leaq (%rax,%rbx,4), %rax
movq 0x8(%rsp), %rcx
leaq (%rax,%rcx,4), %rdx
addq $0x4, %rdx
callq 0x360e
incq %rbp
jmp 0x347e
movq 0x10(%rsp), %rdi
movq (%rsp), %rcx
subq %rcx, %rdi
movq %r14, %rax
leaq (%r12,%r14), %rsi
movq 0x8(%rsp), %r14
subq %rcx, %r14
leaq (%r12,%rax), %rdx
incq %rdx
leaq (%r14,%r12), %rcx
incq %rcx
cmpq $0x80, %rdi
jbe 0x34fe
movq %r15, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3632
movq %r15, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3578