// File: Baobaobear[P]sort/./grailsort.hpp
// Function: void Mrrl::grail_CombineBlocks<baobao::TestClass*, baobao::TestClass*, std::less<baobao::TestClass>>(baobao::TestClass*, baobao::TestClass*, baobao::TestClass*, int, int, bool, baobao::TestClass*, std::less<baobao::TestClass>)
void grail_CombineBlocks(RandomAccessIterator keys, RandomAccessIterator beg, RandomAccessIterator end, int LL, int lblock, bool havebuf, RandomAccessBufferIterator xbuf, Comp compare) {
    RandomAccessIterator arr1;

    int M = (int)((end - beg) / (2 * LL));
    int lrest = (int)((end - beg) % (2 * LL));
    if (lrest <= LL) {
        end -= lrest;
        lrest = 0;
    }
    if (xbuf)
    {
        //memcpy(xbuf, beg - lblock, lblock * sizeof(value_type)); // TODO
        for (int i = 0; i < lblock; ++i)
        {
            *(xbuf + i) = *(beg - lblock + i);
        }
    }
    for (int b = 0; b <= M; b++) {
        if (b == M && lrest == 0) break;
        arr1 = beg + b * 2 * LL;
        int NBlk = (b == M ? lrest : 2 * LL) / lblock;
        grail_SortIns(keys, keys + NBlk + (b == M ? 1 : 0), compare);
        int midkey = LL / lblock;
        for (int u = 1; u < NBlk; u++) {
            int p = u - 1;
            for (int v = u; v < NBlk; v++) {
                if (compare(*(arr1 + v*lblock), *(arr1 + p*lblock)) ||
                    (grail_lesseq(*(arr1 + v*lblock), *(arr1 + p*lblock), compare) && compare(*(keys + v), *(keys + p))))
                    p = v;
            }
            if (p != u - 1) {
                grail_swapN(arr1 + (u - 1)*lblock, arr1 + p*lblock, lblock);
                grail_swap1(keys + (u - 1), keys + p);
                if (midkey == u - 1 || midkey == p) midkey ^= (u - 1) ^ p;
            }
        }
        int nbl2 = 0, llast = 0;
        if (b == M) llast = lrest%lblock;
        if (llast != 0) {
            while (nbl2 < NBlk && compare(*(arr1 + NBlk*lblock), *(arr1 + (NBlk - nbl2 - 1)*lblock))) nbl2++;
        }
        if (xbuf) grail_MergeBuffersLeftWithXBuf(keys, keys + midkey, arr1, NBlk - nbl2, lblock, nbl2, llast, compare);
        else grail_MergeBuffersLeft(keys, keys + midkey, arr1, NBlk - nbl2, lblock, havebuf, nbl2, llast, compare);
    }
    if (xbuf) {
        for (RandomAccessIterator p = end; --p >= beg;) *p = *(p - lblock);
        //memcpy(beg - lblock, xbuf, lblock * sizeof(value_type)); // TODO
        for (int i = 0; i < lblock; ++i)
        {
            *(beg - lblock + i) = *(xbuf + i);
        }
    }
    else if (havebuf) while (--end >= beg) grail_swap1(end, end - lblock);
}

// Assembly:
subq $0x98, %rsp
movb %r9b, %al
movq 0xa0(%rsp), %r9
movq %rdi, 0x88(%rsp)
movq %rsi, 0x80(%rsp)
movq %rdx, 0x78(%rsp)
movl %ecx, 0x74(%rsp)
movl %r8d, 0x70(%rsp)
andb $0x1, %al
movb %al, 0x6f(%rsp)
movq 0x78(%rsp), %rax
movq 0x80(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
movl 0x74(%rsp), %ecx
shll %ecx
movslq %ecx, %rcx
cqto
idivq %rcx
movl %eax, 0x5c(%rsp)
movq 0x78(%rsp), %rax
movq 0x80(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
movl 0x74(%rsp), %ecx
shll %ecx
movslq %ecx, %rcx
cqto
idivq %rcx
movl %edx, %eax
movl %eax, 0x58(%rsp)
movl 0x58(%rsp), %eax
cmpl 0x74(%rsp), %eax
jg 0x16283
movl 0x58(%rsp), %ecx
movq 0x78(%rsp), %rax
movslq %ecx, %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x78(%rsp)
movl $0x0, 0x58(%rsp)
cmpq $0x0, 0xa0(%rsp)
je 0x162ed
movl $0x0, 0x54(%rsp)
movl 0x54(%rsp), %eax
cmpl 0x70(%rsp), %eax
jge 0x162eb
movq 0x80(%rsp), %rsi
movslq 0x70(%rsp), %rcx
xorl %eax, %eax
subq %rcx, %rax
shlq $0x5, %rax
addq %rax, %rsi
movslq 0x54(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0xa0(%rsp), %rdi
movslq 0x54(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdi
callq 0x8710
movl 0x54(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x54(%rsp)
jmp 0x16296
jmp 0x162ed
movl $0x0, 0x50(%rsp)
movl 0x50(%rsp), %eax
cmpl 0x5c(%rsp), %eax
jg 0x166c4
movl 0x50(%rsp), %eax
cmpl 0x5c(%rsp), %eax
jne 0x16319
cmpl $0x0, 0x58(%rsp)
jne 0x16319
jmp 0x166c4
movq 0x80(%rsp), %rax
movl 0x50(%rsp), %ecx
shll %ecx
imull 0x74(%rsp), %ecx
movslq %ecx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x60(%rsp)
movl 0x50(%rsp), %eax
cmpl 0x5c(%rsp), %eax
jne 0x1634f
movl 0x58(%rsp), %eax
movl %eax, 0x18(%rsp)
jmp 0x16359
movl 0x74(%rsp), %eax
shll %eax
movl %eax, 0x18(%rsp)
movl 0x18(%rsp), %eax
cltd
idivl 0x70(%rsp)
movl %eax, 0x4c(%rsp)
movq 0x88(%rsp), %rdi
movq 0x88(%rsp), %rsi
movslq 0x4c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movl 0x50(%rsp), %edx
movl 0x5c(%rsp), %r8d
xorl %eax, %eax
movl $0x1, %ecx
cmpl %r8d, %edx
cmovel %ecx, %eax
cltq
shlq $0x5, %rax
addq %rax, %rsi
callq 0x15590
movl 0x74(%rsp), %eax
cltd
idivl 0x70(%rsp)
movl %eax, 0x44(%rsp)
movl $0x1, 0x40(%rsp)
movl 0x40(%rsp), %eax
cmpl 0x4c(%rsp), %eax
jge 0x16576
movl 0x40(%rsp), %eax
subl $0x1, %eax
movl %eax, 0x3c(%rsp)
movl 0x40(%rsp), %eax
movl %eax, 0x38(%rsp)
movl 0x38(%rsp), %eax
cmpl 0x4c(%rsp), %eax
jge 0x164b7
movq 0x60(%rsp), %rsi
movl 0x38(%rsp), %eax
imull 0x70(%rsp), %eax
cltq
shlq $0x5, %rax
addq %rax, %rsi
movq 0x60(%rsp), %rdx
movl 0x3c(%rsp), %eax
imull 0x70(%rsp), %eax
cltq
shlq $0x5, %rax
addq %rax, %rdx
leaq 0x97(%rsp), %rdi
callq 0xcd80
testb $0x1, %al
jne 0x1649d
movq 0x60(%rsp), %rdi
movl 0x38(%rsp), %eax
imull 0x70(%rsp), %eax
cltq
shlq $0x5, %rax
addq %rax, %rdi
movq 0x60(%rsp), %rsi
movl 0x3c(%rsp), %eax
imull 0x70(%rsp), %eax
cltq
shlq $0x5, %rax
addq %rax, %rsi
callq 0x17050
testb $0x1, %al
jne 0x16462
jmp 0x164a5
movq 0x88(%rsp), %rsi
movslq 0x38(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x88(%rsp), %rdx
movslq 0x3c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdx
leaq 0x97(%rsp), %rdi
callq 0xcd80
testb $0x1, %al
jne 0x1649d
jmp 0x164a5
movl 0x38(%rsp), %eax
movl %eax, 0x3c(%rsp)
jmp 0x164a7
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x38(%rsp)
jmp 0x163dc
movl 0x3c(%rsp), %eax
movl 0x40(%rsp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
je 0x16564
movq 0x60(%rsp), %rdi
movl 0x40(%rsp), %eax
subl $0x1, %eax
imull 0x70(%rsp), %eax
cltq
shlq $0x5, %rax
addq %rax, %rdi
movq 0x60(%rsp), %rsi
movl 0x3c(%rsp), %eax
imull 0x70(%rsp), %eax
cltq
shlq $0x5, %rax
addq %rax, %rsi
movslq 0x70(%rsp), %rdx
callq 0x16ff0
movq 0x88(%rsp), %rdi
movl 0x40(%rsp), %eax
subl $0x1, %eax
cltq
shlq $0x5, %rax
addq %rax, %rdi
movq 0x88(%rsp), %rsi
movslq 0x3c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
callq 0x16c80
movl 0x44(%rsp), %eax
movl 0x40(%rsp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
je 0x1654f
movl 0x44(%rsp), %eax
cmpl 0x3c(%rsp), %eax
jne 0x16562
movl 0x40(%rsp), %eax
subl $0x1, %eax
xorl 0x3c(%rsp), %eax
xorl 0x44(%rsp), %eax
movl %eax, 0x44(%rsp)
jmp 0x16564
jmp 0x16566
movl 0x40(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40(%rsp)
jmp 0x163bb
movl $0x0, 0x30(%rsp)
movl $0x0, 0x2c(%rsp)
movl 0x50(%rsp), %eax
cmpl 0x5c(%rsp), %eax
jne 0x1659d
movl 0x58(%rsp), %eax
cltd
idivl 0x70(%rsp)
movl %edx, 0x2c(%rsp)
cmpl $0x0, 0x2c(%rsp)
je 0x16615
jmp 0x165a6
movl 0x30(%rsp), %ecx
xorl %eax, %eax
cmpl 0x4c(%rsp), %ecx
movb %al, 0x17(%rsp)
jge 0x165fc
movq 0x60(%rsp), %rsi
movl 0x4c(%rsp), %eax
imull 0x70(%rsp), %eax
cltq
shlq $0x5, %rax
addq %rax, %rsi
movq 0x60(%rsp), %rdx
movl 0x4c(%rsp), %eax
subl 0x30(%rsp), %eax
subl $0x1, %eax
imull 0x70(%rsp), %eax
cltq
shlq $0x5, %rax
addq %rax, %rdx
leaq 0x97(%rsp), %rdi
callq 0xcd80
movb %al, 0x17(%rsp)
movb 0x17(%rsp), %al
testb $0x1, %al
jne 0x16606
jmp 0x16613
movl 0x30(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x30(%rsp)
jmp 0x165a6
jmp 0x16615
cmpq $0x0, 0xa0(%rsp)
je 0x16661
movq 0x88(%rsp), %rdi
movq 0x88(%rsp), %rsi
movslq 0x44(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x60(%rsp), %rdx
movl 0x4c(%rsp), %ecx
subl 0x30(%rsp), %ecx
movl 0x70(%rsp), %r8d
movl 0x30(%rsp), %r9d
movl 0x2c(%rsp), %eax
movl %eax, (%rsp)
callq 0x17080
jmp 0x166b2
movq 0x88(%rsp), %rdi
movq 0x88(%rsp), %rsi
movslq 0x44(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x60(%rsp), %rdx
movl 0x4c(%rsp), %ecx
subl 0x30(%rsp), %ecx
movl 0x70(%rsp), %r8d
movb 0x6f(%rsp), %r9b
movl 0x30(%rsp), %r10d
movl 0x2c(%rsp), %eax
andb $0x1, %r9b
movzbl %r9b, %r9d
movl %r10d, (%rsp)
movl %eax, 0x8(%rsp)
callq 0x17410
jmp 0x166b4
movl 0x50(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x50(%rsp)
jmp 0x162f5
cmpq $0x0, 0xa0(%rsp)
je 0x16776
movq 0x78(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x20(%rsp), %rax
addq $-0x20, %rax
movq %rax, 0x20(%rsp)
cmpq 0x80(%rsp), %rax
jb 0x16717
movq 0x20(%rsp), %rsi
movslq 0x70(%rsp), %rcx
xorl %eax, %eax
subq %rcx, %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x20(%rsp), %rdi
callq 0x8710
jmp 0x166dd
movl $0x0, 0x1c(%rsp)
movl 0x1c(%rsp), %eax
cmpl 0x70(%rsp), %eax
jge 0x16774
movq 0xa0(%rsp), %rsi
movslq 0x1c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x80(%rsp), %rdi
movslq 0x70(%rsp), %rcx
xorl %eax, %eax
subq %rcx, %rax
shlq $0x5, %rax
addq %rax, %rdi
movslq 0x1c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdi
callq 0x8710
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0x1671f
jmp 0x167bd
testb $0x1, 0x6f(%rsp)
je 0x167bb
jmp 0x1677f
movq 0x78(%rsp), %rax
addq $-0x20, %rax
movq %rax, 0x78(%rsp)
cmpq 0x80(%rsp), %rax
jb 0x167b9
movq 0x78(%rsp), %rdi
movq 0x78(%rsp), %rsi
movslq 0x70(%rsp), %rcx
xorl %eax, %eax
subq %rcx, %rax
shlq $0x5, %rax
addq %rax, %rsi
callq 0x16c80
jmp 0x1677f
jmp 0x167bb
jmp 0x167bd
addq $0x98, %rsp
retq
nopw %cs:(%rax,%rax)
nop