// File: Baobaobear[P]sort/./sortlib.hpp
// Function: void baobao::internal::tim_sort_buffer<true, baobao::TestClass*, std::less<baobao::TestClass>>(baobao::TestClass*, baobao::TestClass*, unsigned long, std::less<baobao::TestClass>)
void tim_sort_buffer(RandomAccessIterator beg, RandomAccessIterator end, size_t bufsize, Comp compare)
{
    typedef typename std::iterator_traits<RandomAccessIterator>::value_type value_type;
    if (end - beg > 1)
    {
        RandomAccessIterator run_stack[78]; // ln(2^32)/ln(4/3) = 77.1
        RandomAccessIterator* stack_top = run_stack + 1;
        run_stack[0] = beg;
        run_stack[1] = beg = tim_sort_create_run(beg, end, compare);

        if (end > beg && (end - run_stack[0]) * sizeof(value_type) > merge_sort_stack_buffer_size)
        {
            if (bufsize >= (size_t)(end - run_stack[0]) / 2)
            {
                value_type* buf = safecopy ? new value_type[(end - run_stack[0]) / 2]
                    : (value_type*)malloc((end - run_stack[0]) / 2 * sizeof(value_type));
                while (beg < end)
                {
                    RandomAccessIterator run = tim_sort_create_run(beg, end, compare);
                    *++stack_top = run;
                    beg = run;

                    //tim_sort_stack_merge<T, RandomAccessIterator, Comp>(buf, run_stack, stack_top, end);
                    tim_sort_stack_merge_13<safecopy>(buf, run_stack, stack_top, end, compare);
                }

                tim_sort_force_stack_merge<safecopy>(buf, run_stack, stack_top, compare);
                if (safecopy)
                    delete[] buf;
                else
                    free(buf);
            }
            else
            {
                value_type* buf = safecopy ? new value_type[bufsize]
                    : (value_type*)malloc(bufsize * sizeof(value_type));
                while (beg < end)
                {
                    RandomAccessIterator run = tim_sort_create_run(beg, end, compare);
                    *++stack_top = run;
                    beg = run;

                    //tim_sort_stack_merge<T, RandomAccessIterator, Comp>(buf, run_stack, stack_top, end);
                    tim_sort_stack_merge_with_buffer_13<safecopy>(buf, bufsize, run_stack, stack_top, end, compare);
                }

                tim_sort_force_stack_merge_with_buffer<safecopy>(buf, bufsize, run_stack, stack_top, compare);
                if (safecopy)
                    delete[] buf;
                else
                    free(buf);
            }
        }
        else if (end > beg)
        {
            typedef typename std::iterator_traits<RandomAccessIterator>::value_type value_type;
            value_type buf[merge_sort_stack_buffer_size / sizeof(value_type)];
            while (beg < end)
            {
                RandomAccessIterator run = tim_sort_create_run(beg, end, compare);
                *++stack_top = run;
                beg = run;

                //tim_sort_stack_merge<T, RandomAccessIterator, Comp>(buf, run_stack, stack_top, end);
                tim_sort_stack_merge_13<safecopy>(buf, run_stack, stack_top, end, compare);
            }

            tim_sort_force_stack_merge<safecopy>(buf, run_stack, stack_top, compare);
        }
    }
}

// Assembly:
subq $0x4378, %rsp           # imm = 0x4378
movq %rdi, 0x4368(%rsp)
movq %rsi, 0x4360(%rsp)
movq %rdx, 0x4358(%rsp)
movq 0x4360(%rsp), %rax
movq 0x4368(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
cmpq $0x1, %rax
jle 0x121b2
leaq 0x40e0(%rsp), %rax
addq $0x8, %rax
movq %rax, 0x40d8(%rsp)
movq 0x4368(%rsp), %rax
movq %rax, 0x40e0(%rsp)
movq 0x4368(%rsp), %rdi
movq 0x4360(%rsp), %rsi
callq 0x10c70
movq %rax, 0x4368(%rsp)
movq %rax, 0x40e8(%rsp)
movq 0x4360(%rsp), %rax
cmpq 0x4368(%rsp), %rax
jbe 0x120aa
movq 0x4360(%rsp), %rax
movq 0x40e0(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
shlq $0x5, %rax
cmpq $0x4000, %rax           # imm = 0x4000
jbe 0x120aa
movq 0x4358(%rsp), %rax
movq 0x4360(%rsp), %rcx
movq 0x40e0(%rsp), %rdx
subq %rdx, %rcx
sarq $0x5, %rcx
shrq %rcx
cmpq %rcx, %rax
jb 0x11f11
movq 0x4360(%rsp), %rax
movq 0x40e0(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
movl $0x2, %ecx
cqto
idivq %rcx
movq %rax, 0x70(%rsp)
movl $0x20, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, %rcx
movq 0x70(%rsp), %rax
movq %rcx, 0x78(%rsp)
cmpq $0x0, %rax
je 0x11e12
movq 0x78(%rsp), %rax
movq 0x70(%rsp), %rdx
shlq $0x5, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0x60(%rsp)
movq %rax, 0x68(%rsp)
movq 0x68(%rsp), %rdi
movq %rdi, 0x58(%rsp)
callq 0x61b0
jmp 0x11dfa
movq 0x60(%rsp), %rcx
movq 0x58(%rsp), %rax
addq $0x20, %rax
cmpq %rcx, %rax
movq %rax, 0x68(%rsp)
jne 0x11de9
movq 0x78(%rsp), %rax
movq %rax, 0x40c8(%rsp)
movq 0x4368(%rsp), %rax
cmpq 0x4360(%rsp), %rax
jae 0x11ed2
movq 0x4368(%rsp), %rdi
movq 0x4360(%rsp), %rsi
callq 0x10c70
movq %rax, 0x40b0(%rsp)
movq 0x40b0(%rsp), %rcx
movq 0x40d8(%rsp), %rax
movq %rax, %rdx
addq $0x8, %rdx
movq %rdx, 0x40d8(%rsp)
movq %rcx, 0x8(%rax)
movq 0x40b0(%rsp), %rax
movq %rax, 0x4368(%rsp)
movq 0x40c8(%rsp), %rdi
leaq 0x40e0(%rsp), %rsi
movq 0x4360(%rsp), %rcx
leaq 0x40d8(%rsp), %rdx
callq 0x121d0
jmp 0x11e1f
movq 0x78(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x40c0(%rsp)
movl %eax, 0x40bc(%rsp)
callq 0x2200
jmp 0x121ba
movq 0x40c8(%rsp), %rdi
leaq 0x40e0(%rsp), %rsi
movq 0x40d8(%rsp), %rdx
callq 0x124e0
movq 0x40c8(%rsp), %rax
movq %rax, 0x50(%rsp)
cmpq $0x0, %rax
je 0x11f0c
movq 0x50(%rsp), %rdi
callq 0x2200
jmp 0x120a5
movq 0x4358(%rsp), %rax
movq %rax, 0x40(%rsp)
movl $0x20, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x2030
movq %rax, %rcx
movq 0x40(%rsp), %rax
movq %rcx, 0x48(%rsp)
cmpq $0x0, %rax
je 0x11f99
movq 0x48(%rsp), %rax
movq 0x40(%rsp), %rdx
shlq $0x5, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0x30(%rsp)
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x61b0
jmp 0x11f81
movq 0x30(%rsp), %rcx
movq 0x28(%rsp), %rax
addq $0x20, %rax
cmpq %rcx, %rax
movq %rax, 0x38(%rsp)
jne 0x11f70
movq 0x48(%rsp), %rax
movq %rax, 0x40a0(%rsp)
movq 0x4368(%rsp), %rax
cmpq 0x4360(%rsp), %rax
jae 0x12061
movq 0x4368(%rsp), %rdi
movq 0x4360(%rsp), %rsi
callq 0x10c70
movq %rax, 0x4098(%rsp)
movq 0x4098(%rsp), %rcx
movq 0x40d8(%rsp), %rax
movq %rax, %rdx
addq $0x8, %rdx
movq %rdx, 0x40d8(%rsp)
movq %rcx, 0x8(%rax)
movq 0x4098(%rsp), %rax
movq %rax, 0x4368(%rsp)
movq 0x40a0(%rsp), %rdi
movq 0x4358(%rsp), %rsi
leaq 0x40e0(%rsp), %rdx
movq 0x4360(%rsp), %r8
leaq 0x40d8(%rsp), %rcx
callq 0x12650
jmp 0x11fa6
movq 0x48(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x40c0(%rsp)
movl %eax, 0x40bc(%rsp)
callq 0x2200
jmp 0x121ba
movq 0x40a0(%rsp), %rdi
movq 0x4358(%rsp), %rsi
leaq 0x40e0(%rsp), %rdx
movq 0x40d8(%rsp), %rcx
callq 0x12970
movq 0x40a0(%rsp), %rax
movq %rax, 0x20(%rsp)
cmpq $0x0, %rax
je 0x120a3
movq 0x20(%rsp), %rdi
callq 0x2200
jmp 0x120a5
jmp 0x121b0
movq 0x4360(%rsp), %rax
cmpq 0x4368(%rsp), %rax
jbe 0x121ae
leaq 0x90(%rsp), %rax
movq %rax, %rcx
addq $0x4000, %rcx           # imm = 0x4000
movq %rcx, 0x10(%rsp)
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x61b0
movq 0x8(%rsp), %rax
movq 0x10(%rsp), %rcx
addq $0x20, %rax
cmpq %rcx, %rax
movq %rax, 0x18(%rsp)
jne 0x120dc
jmp 0x12105
movq 0x4368(%rsp), %rax
cmpq 0x4360(%rsp), %rax
jae 0x12191
movq 0x4368(%rsp), %rdi
movq 0x4360(%rsp), %rsi
callq 0x10c70
movq %rax, 0x88(%rsp)
movq 0x88(%rsp), %rcx
movq 0x40d8(%rsp), %rax
movq %rax, %rdx
addq $0x8, %rdx
movq %rdx, 0x40d8(%rsp)
movq %rcx, 0x8(%rax)
movq 0x88(%rsp), %rax
movq %rax, 0x4368(%rsp)
leaq 0x90(%rsp), %rdi
leaq 0x40e0(%rsp), %rsi
movq 0x4360(%rsp), %rcx
leaq 0x40d8(%rsp), %rdx
callq 0x121d0
jmp 0x12105
leaq 0x90(%rsp), %rdi
leaq 0x40e0(%rsp), %rsi
movq 0x40d8(%rsp), %rdx
callq 0x124e0
jmp 0x121b0
jmp 0x121b2
addq $0x4378, %rsp           # imm = 0x4378
retq
movq 0x40c0(%rsp), %rdi
callq 0x2280
nopw (%rax,%rax)