// File: 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
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x78(%rbp)
movq $0x20, -0x38(%rbp)
movq -0x20(%rbp), %rax
movq -0x18(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0x40(%rbp)
movaps 0x3d2b(%rip), %xmm1     # 0x8020
movq -0x40(%rbp), %xmm0
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x3d2a(%rip), %xmm1     # 0x8030
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
callq 0x2120
movaps %xmm0, %xmm1
cvttsd2si %xmm1, %rax
movq %rax, %rdx
sarq $0x3f, %rdx
movsd 0x3cdf(%rip), %xmm1     # 0x8010
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %rcx
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, -0x48(%rbp)
cmpq $0x20, -0x48(%rbp)
jae 0x4386
movq -0x78(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x4770
movq -0x78(%rbp), %rdi
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rsi
movq -0x18(%rbp), %rdx
addq $0x2, %rdx
movq -0x20(%rbp), %rcx
subq $0x2, %rcx
callq 0x4820
movq %rax, -0x8(%rbp)
jmp 0x475d
movq -0x28(%rbp), %rax
movq (%rax), %rax
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x80(%rbp)
testq %rax, %rax
movss %xmm0, -0x7c(%rbp)
js 0x43c2
movss -0x80(%rbp), %xmm0
movss %xmm0, -0x7c(%rbp)
movss -0x7c(%rbp), %xmm0
movss %xmm0, -0x8c(%rbp)
movq -0x40(%rbp), %rax
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x88(%rbp)
testq %rax, %rax
movss %xmm0, -0x84(%rbp)
js 0x4414
movss -0x88(%rbp), %xmm0
movss %xmm0, -0x84(%rbp)
movss -0x8c(%rbp), %xmm0
movss -0x84(%rbp), %xmm1
divss %xmm1, %xmm0
movss %xmm0, -0x54(%rbp)
movss -0x54(%rbp), %xmm0
movss %xmm0, -0x98(%rbp)
movq -0x48(%rbp), %rax
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0x94(%rbp)
testq %rax, %rax
movss %xmm0, -0x90(%rbp)
js 0x447f
movss -0x94(%rbp), %xmm0
movss %xmm0, -0x90(%rbp)
movss -0x98(%rbp), %xmm0
movss -0x90(%rbp), %xmm1
mulss %xmm1, %xmm0
movaps %xmm0, %xmm1
cvttss2si %xmm1, %rax
movq %rax, %rdx
sarq $0x3f, %rdx
movss 0x3b96(%rip), %xmm1     # 0x8040
subss %xmm1, %xmm0
cvttss2si %xmm0, %rcx
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, -0x60(%rbp)
cmpq $0x20, -0x60(%rbp)
jb 0x45bf
movq -0x60(%rbp), %rax
andq $0xf, %rax
cmpq $0x8, %rax
jae 0x44dd
cmpq $0x10, -0x60(%rbp)
jae 0x44f7
movq -0x60(%rbp), %rcx
andq $0xf, %rcx
movl $0xf, %eax
subq %rcx, %rax
addq -0x60(%rbp), %rax
movq %rax, -0x60(%rbp)
jmp 0x450e
movq -0x60(%rbp), %rcx
andq $0xf, %rcx
addq $0x1, %rcx
movq -0x60(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
cmpq -0x30(%rbp), %rax
ja 0x452b
movl $0x10, %eax
subq -0x30(%rbp), %rax
addq -0x60(%rbp), %rax
movq %rax, -0x60(%rbp)
jmp 0x453a
movq -0x30(%rbp), %rcx
movq -0x60(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, -0xa0(%rbp)
testq %rax, %rax
movss %xmm0, -0x9c(%rbp)
js 0x457f
movss -0xa0(%rbp), %xmm0
movss %xmm0, -0x9c(%rbp)
movss -0x9c(%rbp), %xmm0
movss -0x54(%rbp), %xmm1
divss %xmm1, %xmm0
callq 0x4960
movaps %xmm0, %xmm1
cvttss2si %xmm1, %rax
movq %rax, %rdx
sarq $0x3f, %rdx
movss 0x3a94(%rip), %xmm1     # 0x8040
subss %xmm1, %xmm0
cvttss2si %xmm0, %rcx
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, -0x48(%rbp)
movq $0x0, -0x68(%rbp)
movq -0x68(%rbp), %rax
movq -0x48(%rbp), %rcx
shrq %rcx
cmpq %rcx, %rax
jae 0x4639
movq -0x78(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x68(%rbp), %rax
shlq %rax
addq %rax, %rsi
movq -0x18(%rbp), %rdx
movq -0x68(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdx
callq 0x4230
movq -0x78(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x68(%rbp), %rax
shlq %rax
addq %rax, %rsi
addq $0x1, %rsi
movq -0x18(%rbp), %rdx
movq -0x68(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdx
addq $0xf, %rdx
callq 0x4230
movq -0x68(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x68(%rbp)
jmp 0x45c7
movq -0x78(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x18(%rbp), %rdx
addq -0x48(%rbp), %rdx
movq -0x60(%rbp), %rcx
callq 0x3f10
movq $0x0, -0x70(%rbp)
movq -0x78(%rbp), %rcx
movq -0x70(%rbp), %rax
cmpq 0x8(%rcx), %rax
jae 0x46df
movq -0x78(%rbp), %rax
movq (%rax), %rcx
movq -0x70(%rbp), %rdx
movq (%rcx,%rdx,8), %rdi
movq -0x18(%rbp), %rcx
addq -0x60(%rbp), %rcx
addq $0x1, %rcx
shlq $0x2, %rcx
addq %rcx, %rdi
movq (%rax), %rcx
movq -0x70(%rbp), %rdx
movq (%rcx,%rdx,8), %rsi
movq -0x18(%rbp), %rcx
addq -0x48(%rbp), %rcx
shlq $0x2, %rcx
addq %rcx, %rsi
movq (%rax), %rax
movq -0x70(%rbp), %rcx
movq (%rax,%rcx,8), %rdx
movq -0x20(%rbp), %rax
movq -0x48(%rbp), %rcx
subq -0x60(%rbp), %rcx
subq %rcx, %rax
addq $0x1, %rax
shlq $0x2, %rax
addq %rax, %rdx
callq 0x4980
movq -0x70(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x70(%rbp)
jmp 0x465a
movq -0x20(%rbp), %rax
subq -0x18(%rbp), %rax
subq -0x48(%rbp), %rax
cmpq $0x80, %rax
jbe 0x4729
movq -0x78(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq -0x60(%rbp), %rsi
movq -0x18(%rbp), %rdx
addq -0x60(%rbp), %rdx
addq $0x1, %rdx
movq -0x20(%rbp), %rcx
movq -0x48(%rbp), %rax
subq -0x60(%rbp), %rax
subq %rax, %rcx
addq $0x1, %rcx
callq 0x49d0
movq %rax, -0x8(%rbp)
jmp 0x475d
movq -0x78(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq -0x60(%rbp), %rsi
movq -0x18(%rbp), %rdx
addq -0x60(%rbp), %rdx
addq $0x1, %rdx
movq -0x20(%rbp), %rcx
movq -0x48(%rbp), %rax
subq -0x60(%rbp), %rax
subq %rax, %rcx
addq $0x1, %rcx
callq 0x4820
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0xa0, %rsp
popq %rbp
retq
nopw (%rax,%rax)