// File: Baobaobear[P]sort/./sortlib.hpp
// Function: void baobao::internal::shell_sort<baobao::internal::indirect_sort_iter_warp<baobao::TestClass*>*, baobao::internal::indirect_sort_comp_warp<baobao::TestClass*, std::less<baobao::TestClass>>>(baobao::internal::indirect_sort_iter_warp<baobao::TestClass*>*, baobao::internal::indirect_sort_iter_warp<baobao::TestClass*>*, baobao::internal::indirect_sort_comp_warp<baobao::TestClass*, std::less<baobao::TestClass>>)
void shell_sort(RandomAccessIterator beg, RandomAccessIterator end, Comp compare)
{
    if (end - beg > shellsort_insertion_sort_threshold)
    {
        typedef typename std::iterator_traits<RandomAccessIterator>::difference_type diff_type;
        typedef typename std::iterator_traits<RandomAccessIterator>::value_type value_type;
        diff_type len = end - beg;
        diff_type incre_list[61] = { 0, 9, 34, 182, 836, 4025, 19001, 90358, 428481, 2034035, 9651787, 45806244, 217378076, 1031612713 };
        const double incre_factor = 2.9; // simple and fast enought

        if (!util::is_scalar<value_type>::value)
        {
            incre_list[1] = 10;
        }
        diff_type incre_index = 0;
        for (diff_type i = 1; i < 60; ++i)
        {
            diff_type mul = incre_list[i];
            if (mul * incre_factor >= len)
            {
                incre_index = i;
                break;
            }
            if (!util::is_scalar<value_type>::value || incre_list[i + 1] == 0)
            {
                incre_list[i + 1] = (diff_type)(mul * incre_factor);
            }
        }

        for (; incre_index > 0; --incre_index)
        {
            bool swaped = false;
            diff_type incre = incre_list[incre_index];
            for (diff_type i = incre; i < len; i++)
            {
                if (compare(*(beg + i), *(beg + i - incre)))
                {
                    value_type val = *(beg + i);
                    *(beg + i) = *(beg + i - incre);
                    diff_type pos = i - incre;
                    for (; pos >= incre && compare(val, *(beg + pos - incre)); pos -= incre)
                    {
                        *(beg + pos) = *(beg + pos - incre);
                    }
                    *(beg + pos) = val;
                    swaped = true;
                }
            }
            if (!swaped)
            {
                RandomAccessIterator last = insert_sort_limit(beg, end, compare, 1);
                if (last == end)
                {
                    return;
                }
                if (last - beg >= incre << 1)
                {
                    beg += ((last - beg) / incre - 1) * incre;
                    len = end - beg;
                }
            }
        }

        insert_sort(beg, beg + incre_list[1], compare);
        unguarded_insert_sort(beg + incre_list[1], end, compare);
    }
    else
    {
        insert_sort(beg, end, compare);
    }
}

// Assembly:
subq $0x2b8, %rsp            # imm = 0x2B8
movq %rdx, 0x48(%rsp)
movq %rdi, 0x2b0(%rsp)
movq %rsi, 0x2a8(%rsp)
movq %rdx, 0x2a0(%rsp)
movq 0x2a8(%rsp), %rax
movq 0x2b0(%rsp), %rcx
subq %rcx, %rax
sarq $0x4, %rax
cmpq $0x20, %rax
jle 0x13eac
movq 0x2a8(%rsp), %rax
movq 0x2b0(%rsp), %rcx
subq %rcx, %rax
sarq $0x4, %rax
movq %rax, 0x298(%rsp)
leaq 0xb0(%rsp), %rdi
leaq 0x13aad(%rip), %rsi     # 0x274c0
movl $0x1e8, %edx            # imm = 0x1E8
callq 0x2180
movsd 0x135e3(%rip), %xmm0    # 0x27008
movsd %xmm0, 0xa8(%rsp)
movq $0xa, 0xb8(%rsp)
movq $0x0, 0xa0(%rsp)
movq $0x1, 0x98(%rsp)
cmpq $0x3c, 0x98(%rsp)
jge 0x13af5
movq 0x98(%rsp), %rax
movq 0xb0(%rsp,%rax,8), %rax
movq %rax, 0x90(%rsp)
cvtsi2sdq 0x90(%rsp), %xmm0
movsd 0x1357d(%rip), %xmm1    # 0x27008
mulsd %xmm1, %xmm0
cvtsi2sdq 0x298(%rsp), %xmm1
ucomisd %xmm1, %xmm0
jb 0x13ab1
movq 0x98(%rsp), %rax
movq %rax, 0xa0(%rsp)
jmp 0x13af5
cvtsi2sdq 0x90(%rsp), %xmm0
movsd 0x13545(%rip), %xmm1    # 0x27008
mulsd %xmm1, %xmm0
cvttsd2si %xmm0, %rcx
movq 0x98(%rsp), %rax
movq %rcx, 0xb8(%rsp,%rax,8)
movq 0x98(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x98(%rsp)
jmp 0x13a52
jmp 0x13af7
cmpq $0x0, 0xa0(%rsp)
jle 0x13e12
movb $0x0, 0x8f(%rsp)
movq 0xa0(%rsp), %rax
movq 0xb0(%rsp,%rax,8), %rax
movq %rax, 0x80(%rsp)
movq 0x80(%rsp), %rax
movq %rax, 0x78(%rsp)
movq 0x78(%rsp), %rax
cmpq 0x298(%rsp), %rax
jge 0x13d0a
movq 0x48(%rsp), %rdi
movq 0x2b0(%rsp), %rsi
movq 0x78(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rsi
movq 0x2b0(%rsp), %rdx
movq 0x78(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rdx
xorl %eax, %eax
subq 0x80(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rdx
callq 0x144a0
testb $0x1, %al
jne 0x13b92
jmp 0x13cf5
movq 0x2b0(%rsp), %rax
movq 0x78(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq (%rax), %rcx
movq %rcx, 0x68(%rsp)
movq 0x8(%rax), %rax
movq %rax, 0x70(%rsp)
movq 0x2b0(%rsp), %rcx
movq 0x78(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rcx
xorl %eax, %eax
subq 0x80(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rcx
movq 0x2b0(%rsp), %rax
movq 0x78(%rsp), %rdx
shlq $0x4, %rdx
addq %rdx, %rax
movq (%rcx), %rdx
movq %rdx, (%rax)
movq 0x8(%rcx), %rcx
movq %rcx, 0x8(%rax)
movq 0x78(%rsp), %rax
subq 0x80(%rsp), %rax
movq %rax, 0x60(%rsp)
movq 0x60(%rsp), %rcx
xorl %eax, %eax
cmpq 0x80(%rsp), %rcx
movb %al, 0x47(%rsp)
jl 0x13c5d
movq 0x48(%rsp), %rdi
movq 0x2b0(%rsp), %rdx
movq 0x60(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rdx
xorl %eax, %eax
subq 0x80(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rdx
leaq 0x68(%rsp), %rsi
callq 0x144a0
movb %al, 0x47(%rsp)
movb 0x47(%rsp), %al
testb $0x1, %al
jne 0x13c67
jmp 0x13cc8
movq 0x2b0(%rsp), %rcx
movq 0x60(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rcx
xorl %eax, %eax
subq 0x80(%rsp), %rax
shlq $0x4, %rax
addq %rax, %rcx
movq 0x2b0(%rsp), %rax
movq 0x60(%rsp), %rdx
shlq $0x4, %rdx
addq %rdx, %rax
movq (%rcx), %rdx
movq %rdx, (%rax)
movq 0x8(%rcx), %rcx
movq %rcx, 0x8(%rax)
movq 0x80(%rsp), %rcx
movq 0x60(%rsp), %rax
subq %rcx, %rax
movq %rax, 0x60(%rsp)
jmp 0x13c10
movq 0x2b0(%rsp), %rax
movq 0x60(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq 0x68(%rsp), %rcx
movq %rcx, (%rax)
movq 0x70(%rsp), %rcx
movq %rcx, 0x8(%rax)
movb $0x1, 0x8f(%rsp)
jmp 0x13cf7
movq 0x78(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x78(%rsp)
jmp 0x13b33
testb $0x1, 0x8f(%rsp)
jne 0x13df7
movq 0x48(%rsp), %rsi
movq 0x2b0(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x2a8(%rsp), %rax
movq %rax, 0x38(%rsp)
leaq 0x57(%rsp), %rdi
callq 0x13670
movq 0x30(%rsp), %rdi
movq 0x38(%rsp), %rsi
leaq 0x57(%rsp), %rdx
movl $0x1, %ecx
callq 0x14530
movq %rax, 0x58(%rsp)
movq 0x58(%rsp), %rax
cmpq 0x2a8(%rsp), %rax
jne 0x13d73
jmp 0x13ee7
movq 0x58(%rsp), %rax
movq 0x2b0(%rsp), %rcx
subq %rcx, %rax
sarq $0x4, %rax
movq 0x80(%rsp), %rcx
shlq %rcx
cmpq %rcx, %rax
jl 0x13df5
movq 0x58(%rsp), %rax
movq 0x2b0(%rsp), %rcx
subq %rcx, %rax
sarq $0x4, %rax
cqto
idivq 0x80(%rsp)
subq $0x1, %rax
imulq 0x80(%rsp), %rax
shlq $0x4, %rax
addq 0x2b0(%rsp), %rax
movq %rax, 0x2b0(%rsp)
movq 0x2a8(%rsp), %rax
movq 0x2b0(%rsp), %rcx
subq %rcx, %rax
sarq $0x4, %rax
movq %rax, 0x298(%rsp)
jmp 0x13df7
jmp 0x13df9
movq 0xa0(%rsp), %rax
addq $-0x1, %rax
movq %rax, 0xa0(%rsp)
jmp 0x13af7
movq 0x48(%rsp), %rsi
movq 0x2b0(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x2b0(%rsp), %rax
movq 0xb8(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, 0x18(%rsp)
leaq 0x56(%rsp), %rdi
callq 0x13670
movq 0x10(%rsp), %rdi
movq 0x18(%rsp), %rsi
leaq 0x56(%rsp), %rdx
callq 0x148d0
movq 0x48(%rsp), %rsi
movq 0x2b0(%rsp), %rax
movq 0xb8(%rsp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, 0x20(%rsp)
movq 0x2a8(%rsp), %rax
movq %rax, 0x28(%rsp)
leaq 0x55(%rsp), %rdi
callq 0x13670
movq 0x20(%rsp), %rdi
movq 0x28(%rsp), %rsi
leaq 0x55(%rsp), %rdx
callq 0x14a00
jmp 0x13ee7
movq 0x48(%rsp), %rsi
movq 0x2b0(%rsp), %rax
movq %rax, (%rsp)
movq 0x2a8(%rsp), %rax
movq %rax, 0x8(%rsp)
leaq 0x54(%rsp), %rdi
callq 0x13670
movq (%rsp), %rdi
movq 0x8(%rsp), %rsi
leaq 0x54(%rsp), %rdx
callq 0x148d0
addq $0x2b8, %rsp            # imm = 0x2B8
retq
nop