// File: /workspace/github_cpp_makefile_star2_O1/travisdowns[P]sort-bench/radix7.cpp
// Function: radix_sort7(unsigned long*, unsigned long)
void radix_sort7(uint64_t *a, size_t count)
{
    std::unique_ptr<uint64_t[]> queue_area(new uint64_t[count]);
    // huge_unique_ptr<uint64_t[]> queue_area = make_huge_array<uint64_t>(count, false);

    freq_array_type freqs = {};
    count_frequency(a, count, freqs);

    uint64_t *from = a, *to = queue_area.get();

    for (size_t pass = 0; pass < RADIX_LEVELS; pass++) {

        if (is_trivial(freqs[pass], count)) {
            // this pass would do nothing, just skip it
            continue;
        }

        uint64_t shift = pass * RADIX_BITS;

        // array of pointers to the current position in each queue, which we set up based on the
        // known final sizes of each queue (i.e., "tighly packed")
        uint64_t * queue_ptrs[RADIX_SIZE], * next = to;
        for (size_t i = 0; i < RADIX_SIZE; i++) {
            queue_ptrs[i] = next;
            next += freqs[pass][i];
        }

        // copy each element into the appropriate queue based on the current RADIX_BITS sized
        // "digit" within it
        for (size_t i = 0; i < count; i++) {
            size_t value = from[i];
            size_t index = (value >> shift) & RADIX_MASK;
            *queue_ptrs[index]++ = value;
            __builtin_prefetch(queue_ptrs[index] + 1);
        }

        // swap from and to areas
        std::swap(from, to);
    }

    // because of the last swap, the "from" area has the sorted payload: if it's
    // not the original array "a", do a final copy
    if (from != a) {
        std::copy(from, from + count, a);
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x4818, %rsp           # imm = 0x4818
movq %rsi, %r15
movq %rdi, %rbx
movq %rsi, %rax
shrq $0x3d, %rax
leaq (,%rsi,8), %rcx
xorl %edi, %edi
negq %rax
sbbq %rdi, %rdi
movq %rcx, 0x8(%rsp)
orq %rcx, %rdi
callq 0x2030
movq %rax, %r12
leaq 0x810(%rsp), %r13
movl $0x4000, %edx           # imm = 0x4000
movq %r13, %rdi
xorl %esi, %esi
callq 0x20b0
testq %r15, %r15
je 0x3bc0
xorl %eax, %eax
movq (%rbx,%rax,8), %rcx
xorl %edx, %edx
movzbl %cl, %esi
leaq (%rsp,%rsi,8), %rsi
addq $0x810, %rsi            # imm = 0x810
incq (%rdx,%rsi)
shrq $0x8, %rcx
addq $0x800, %rdx            # imm = 0x800
cmpq $0x4000, %rdx           # imm = 0x4000
jne 0x3b92
incq %rax
cmpq %r15, %rax
jne 0x3b8c
leaq 0x818(%rsp), %rax
xorl %edx, %edx
movl $0x800, %edi            # imm = 0x800
movq %r12, %r8
movq %rbx, %r9
movq %rdx, %rcx
shlq $0xb, %rcx
movq 0x810(%rsp,%rcx), %rsi
cmpq %r15, %rsi
sete %cl
testq %rsi, %rsi
je 0x3bf3
xorl %esi, %esi
jmp 0x3c29
xorl %r10d, %r10d
movq %r10, %rsi
cmpq $0xff, %r10
je 0x3c1e
movq (%rax,%rsi,8), %r11
xorl %ebp, %ebp
cmpq %r15, %r11
sete %bpl
leaq 0x1(%rsi), %r10
movzbl %cl, %ecx
testq %r11, %r11
cmovnel %ebp, %ecx
je 0x3bf6
cmpq $0xff, %rsi
setae %sil
testq %r15, %r15
sete %r10b
movl %esi, %r11d
xorb $0x1, %r11b
orb %r10b, %r11b
je 0x3cf4
orb %cl, %sil
testb $0x1, %sil
je 0x3c4e
movq %r9, %rsi
jmp 0x3cb1
xorl %ecx, %ecx
movq %r8, %rsi
movq %rsi, 0x10(%rsp,%rcx,8)
movq (%r13,%rcx,8), %r10
leaq (%rsi,%r10,8), %rsi
incq %rcx
cmpq $0x100, %rcx            # imm = 0x100
jne 0x3c53
testq %r15, %r15
je 0x3ca8
leaq (,%rdx,8), %rcx
xorl %esi, %esi
movq (%r9,%rsi,8), %r10
movq %r10, %r11
shrq %cl, %r11
movzbl %r11b, %r11d
movq 0x10(%rsp,%r11,8), %rbp
leaq 0x8(%rbp), %r14
movq %r14, 0x10(%rsp,%r11,8)
movq %r10, (%rbp)
prefetcht0 0x10(%rbp)
incq %rsi
cmpq %rsi, %r15
jne 0x3c7c
movq %r8, %rsi
movq %r9, %r8
movq %rsi, %r9
incq %rdx
addq %rdi, %rax
addq %rdi, %r13
cmpq $0x8, %rdx
jne 0x3bd5
testq %r15, %r15
je 0x3cdb
cmpq %rbx, %rsi
je 0x3cdb
movq %rbx, %rdi
movq 0x8(%rsp), %rdx
callq 0x21b0
movq %r12, %rdi
addq $0x4818, %rsp           # imm = 0x4818
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2160
leaq 0x17be(%rip), %rdi      # 0x54b9
leaq 0x17ef(%rip), %rsi      # 0x54f1
leaq 0x17c6(%rip), %rcx      # 0x54cf
movl $0x2f, %edx
callq 0x20c0
nop