// File: Baobaobear[P]sort/./sortlib.hpp
// Function: baobao::TestClass* baobao::internal::tim_sort_create_run<baobao::TestClass*, std::less<baobao::TestClass>>(baobao::TestClass*, baobao::TestClass*, std::less<baobao::TestClass>)
RandomAccessIterator tim_sort_create_run(RandomAccessIterator beg, RandomAccessIterator end, Comp compare)
{
    if (end - beg < timsort_last_run_threshold) // must bigger than timsort_min_run
    {
        insert_sort(beg, end, compare);
        return end;
    }

    bool ascending;
    RandomAccessIterator run_end = beg + 3;

    if (compare(*(beg + 1), *beg))
    {
        if (!compare(*(beg + 2), *beg))
        {
            std::swap(*beg, *(beg + 1));
            ascending = true;
        }
        else if (compare(*(beg + 2), *(beg + 1)))
        {
            ascending = false;
        }
        else
        {
            std::swap(*(beg + 2), *(beg + 1));
            ascending = false;
        }
    }
    else
    {
        if (compare(*(beg + 2), *beg))
        {
            std::swap(*beg, *(beg + 1));
            ascending = false;
        }
        else if (!compare(*(beg + 2), *(beg + 1)))
        {
            ascending = true;
        }
        else
        {
            std::swap(*(beg + 2), *(beg + 1));
            ascending = true;
        }
    }

    if (!ascending)
    {
        while (run_end < end && compare(*run_end, *(run_end - 1)))
        {
            ++run_end;
        }

        if (run_end - beg < timsort_min_run)
        {
            insert_sort_part_rev(beg, run_end, beg + timsort_min_run, compare);
            run_end = beg + timsort_min_run;
            while (run_end < end && compare(*run_end, *(run_end - timsort_insert_gap)))
            {
                unguarded_insert_single_rev(run_end, compare);
                ++run_end;
            }
        }

        // reverse
        typename std::iterator_traits<RandomAccessIterator>::value_type t;
        for (RandomAccessIterator b = beg, e = run_end - 1; b < e; ++b, --e)
        {
            t = *b; *b = *e; *e = t;
        }
    }
    else
    {
        while (run_end < end && !compare(*run_end, *(run_end - 1)))
        {
            ++run_end;
        }

        if (run_end - beg < timsort_min_run)
        {
            insert_sort_part(beg, run_end, beg + timsort_min_run, compare);
            run_end = beg + timsort_min_run;
            while (run_end < end && !compare(*run_end, *(run_end - timsort_insert_gap)))
            {
                unguarded_insert_single(run_end, compare);
                ++run_end;
            }
        }
    }

    return run_end;
}

// Assembly:
subq $0x78, %rsp
movq %rdi, 0x60(%rsp)
movq %rsi, 0x58(%rsp)
movq 0x58(%rsp), %rax
movq 0x60(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
cmpq $0x40, %rax
jge 0x10cb3
movq 0x60(%rsp), %rdi
movq 0x58(%rsp), %rsi
callq 0xcc80
movq 0x58(%rsp), %rax
movq %rax, 0x70(%rsp)
jmp 0x11044
movq 0x60(%rsp), %rax
addq $0x60, %rax
movq %rax, 0x48(%rsp)
movq 0x60(%rsp), %rsi
addq $0x20, %rsi
movq 0x60(%rsp), %rdx
leaq 0x6f(%rsp), %rdi
callq 0xcd80
testb $0x1, %al
jne 0x10cdf
jmp 0x10d5e
movq 0x60(%rsp), %rsi
addq $0x40, %rsi
movq 0x60(%rsp), %rdx
leaq 0x6f(%rsp), %rdi
callq 0xcd80
testb $0x1, %al
jne 0x10d15
movq 0x60(%rsp), %rdi
movq 0x60(%rsp), %rsi
addq $0x20, %rsi
callq 0x8660
movb $0x1, 0x56(%rsp)
jmp 0x10d5c
movq 0x60(%rsp), %rsi
addq $0x40, %rsi
movq 0x60(%rsp), %rdx
addq $0x20, %rdx
leaq 0x6f(%rsp), %rdi
callq 0xcd80
testb $0x1, %al
jne 0x10d37
jmp 0x10d3e
movb $0x0, 0x56(%rsp)
jmp 0x10d5a
movq 0x60(%rsp), %rdi
addq $0x40, %rdi
movq 0x60(%rsp), %rsi
addq $0x20, %rsi
callq 0x8660
movb $0x0, 0x56(%rsp)
jmp 0x10d5c
jmp 0x10ddd
movq 0x60(%rsp), %rsi
addq $0x40, %rsi
movq 0x60(%rsp), %rdx
leaq 0x6f(%rsp), %rdi
callq 0xcd80
testb $0x1, %al
jne 0x10d7c
jmp 0x10d96
movq 0x60(%rsp), %rdi
movq 0x60(%rsp), %rsi
addq $0x20, %rsi
callq 0x8660
movb $0x0, 0x56(%rsp)
jmp 0x10ddb
movq 0x60(%rsp), %rsi
addq $0x40, %rsi
movq 0x60(%rsp), %rdx
addq $0x20, %rdx
leaq 0x6f(%rsp), %rdi
callq 0xcd80
testb $0x1, %al
jne 0x10dbd
movb $0x1, 0x56(%rsp)
jmp 0x10dd9
movq 0x60(%rsp), %rdi
addq $0x40, %rdi
movq 0x60(%rsp), %rsi
addq $0x20, %rsi
callq 0x8660
movb $0x1, 0x56(%rsp)
jmp 0x10ddb
jmp 0x10ddd
testb $0x1, 0x56(%rsp)
jne 0x10f4d
jmp 0x10dea
movq 0x48(%rsp), %rcx
xorl %eax, %eax
cmpq 0x58(%rsp), %rcx
movb %al, 0xd(%rsp)
jae 0x10e18
movq 0x48(%rsp), %rsi
movq 0x48(%rsp), %rdx
addq $-0x20, %rdx
leaq 0x6f(%rsp), %rdi
callq 0xcd80
movb %al, 0xd(%rsp)
movb 0xd(%rsp), %al
testb $0x1, %al
jne 0x10e22
jmp 0x10e32
movq 0x48(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x48(%rsp)
jmp 0x10dea
movq 0x48(%rsp), %rax
movq 0x60(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
cmpq $0x20, %rax
jge 0x10ecf
movq 0x60(%rsp), %rdi
movq 0x48(%rsp), %rsi
movq 0x60(%rsp), %rdx
addq $0x400, %rdx            # imm = 0x400
callq 0x11970
movq 0x60(%rsp), %rax
addq $0x400, %rax            # imm = 0x400
movq %rax, 0x48(%rsp)
movq 0x48(%rsp), %rcx
xorl %eax, %eax
cmpq 0x58(%rsp), %rcx
movb %al, 0xc(%rsp)
jae 0x10ea9
movq 0x48(%rsp), %rsi
movq 0x48(%rsp), %rdx
addq $-0x100, %rdx
leaq 0x6f(%rsp), %rdi
callq 0xcd80
movb %al, 0xc(%rsp)
movb 0xc(%rsp), %al
testb $0x1, %al
jne 0x10eb3
jmp 0x10ecd
movq 0x48(%rsp), %rdi
callq 0x11a70
movq 0x48(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x48(%rsp)
jmp 0x10e78
jmp 0x10ecf
leaq 0x24(%rsp), %rdi
callq 0x61b0
movq 0x60(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x48(%rsp), %rax
addq $-0x20, %rax
movq %rax, 0x10(%rsp)
movq 0x18(%rsp), %rax
cmpq 0x10(%rsp), %rax
jae 0x10f48
movq 0x18(%rsp), %rsi
leaq 0x24(%rsp), %rdi
callq 0x8710
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdi
callq 0x8710
movq 0x10(%rsp), %rdi
leaq 0x24(%rsp), %rsi
callq 0x8710
movq 0x18(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x18(%rsp)
movq 0x10(%rsp), %rax
addq $-0x20, %rax
movq %rax, 0x10(%rsp)
jmp 0x10ef1
jmp 0x1103a
jmp 0x10f4f
movq 0x48(%rsp), %rcx
xorl %eax, %eax
cmpq 0x58(%rsp), %rcx
movb %al, 0xb(%rsp)
jae 0x10f7f
movq 0x48(%rsp), %rsi
movq 0x48(%rsp), %rdx
addq $-0x20, %rdx
leaq 0x6f(%rsp), %rdi
callq 0xcd80
xorb $-0x1, %al
movb %al, 0xb(%rsp)
movb 0xb(%rsp), %al
testb $0x1, %al
jne 0x10f89
jmp 0x10f99
movq 0x48(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x48(%rsp)
jmp 0x10f4f
movq 0x48(%rsp), %rax
movq 0x60(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
cmpq $0x20, %rax
jge 0x11038
movq 0x60(%rsp), %rdi
movq 0x48(%rsp), %rsi
movq 0x60(%rsp), %rdx
addq $0x400, %rdx            # imm = 0x400
callq 0xd8b0
movq 0x60(%rsp), %rax
addq $0x400, %rax            # imm = 0x400
movq %rax, 0x48(%rsp)
movq 0x48(%rsp), %rcx
xorl %eax, %eax
cmpq 0x58(%rsp), %rcx
movb %al, 0xa(%rsp)
jae 0x11012
movq 0x48(%rsp), %rsi
movq 0x48(%rsp), %rdx
addq $-0x100, %rdx
leaq 0x6f(%rsp), %rdi
callq 0xcd80
xorb $-0x1, %al
movb %al, 0xa(%rsp)
movb 0xa(%rsp), %al
testb $0x1, %al
jne 0x1101c
jmp 0x11036
movq 0x48(%rsp), %rdi
callq 0x11b10
movq 0x48(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x48(%rsp)
jmp 0x10fdf
jmp 0x11038
jmp 0x1103a
movq 0x48(%rsp), %rax
movq %rax, 0x70(%rsp)
movq 0x70(%rsp), %rax
addq $0x78, %rsp
retq
nop