// File: Baobaobear[P]sort/./grailsort.hpp
// Function: void Mrrl::grail_BuildBlocks<baobao::TestClass*, baobao::TestClass*, std::less<baobao::TestClass>>(baobao::TestClass*, baobao::TestClass*, int, baobao::TestClass*, int, std::less<baobao::TestClass>)
void grail_BuildBlocks(RandomAccessIterator beg, RandomAccessIterator end, int K, RandomAccessBufferIterator extbuf, int LExtBuf, Comp compare) {
    int h, restk, kbuf;
    kbuf = K < LExtBuf ? K : LExtBuf;
    while (kbuf&(kbuf - 1)) kbuf &= kbuf - 1;  // max power or 2 - just in case

    if (kbuf) {
        //memcpy(extbuf, &*(beg - kbuf), kbuf * sizeof(value_type)); // TODO
        for (int i = 0; i < kbuf; ++i)
        {
            *(extbuf + i) = *(beg - kbuf + i);
        }
        for (RandomAccessIterator m = beg + 1; m < end; m += 2) {
            int u = 0;
            if (compare(*m, *(m - 1))) u = 1;
            *(m - 3) = *(m - 1 + u);
            *(m - 2) = *(m - u);
        }
        if ((end - beg) % 2) *(end - 3) = *(end - 1);
        beg -= 2; end -= 2;
        for (h = 2; h < kbuf; h *= 2) {
            RandomAccessIterator p0 = beg;
            RandomAccessIterator p1 = end - 2 * h;
            while (p0 <= p1) {
                grail_MergeLeftWithXBuf(p0, p0 + h, p0 + h + h, p0 - h, compare);
                p0 += 2 * h;
            }
            if (end - p0 > h) {
                grail_MergeLeftWithXBuf(p0, p0 + h, end, p0 - h, compare);
            }
            else {
                for (; p0 < end; p0++) *(p0 - h) = *p0;
            }
            beg -= h; end -= h;
        }
        //memcpy(&*end, extbuf, kbuf * sizeof(value_type)); // TODO
        for (int i = 0; i < kbuf; ++i)
        {
            *(end + i) = *(extbuf + i);
        }
    }
    else {
        for (RandomAccessIterator m = beg + 1; m < end; m += 2) {
            int u = 0;
            if (compare(*m, *(m - 1))) u = 1;
            grail_swap1(m - 3, m - 1 + u);
            grail_swap1(m - 2, m - u);
        }
        if ((end - beg) % 2) grail_swap1(end - 1, end - 3);
        beg -= 2; end -= 2;
        h = 2;
    }
    for (; h < K; h *= 2) {
        RandomAccessIterator p0 = beg;
        RandomAccessIterator p1 = end - 2 * h;
        while (p0 <= p1) {
            grail_MergeLeft(p0, p0 + h, p0 + h + h, p0 - h, compare);
            p0 += 2 * h;
        }
        if (end - p0 > h) {
            grail_MergeLeft(p0, p0 + h, end, p0 - h, compare);
        }
        else grail_rotate(p0 - h, p0, end);
        beg -= h; end -= h;
    }
    restk = (end - beg) % (2 * K);
    RandomAccessIterator p = end - restk;
    if (restk <= K) grail_rotate(p, p + restk, p + restk + K);
    else grail_MergeRight(p, p + K, p + restk, p + restk + K, compare);
    while (p > beg) {
        p -= 2 * K;
        grail_MergeRight(p, p + K, p + K + K, p + K + K + K, compare);
    }
}

// Assembly:
subq $0xa8, %rsp
movq %rdi, 0x98(%rsp)
movq %rsi, 0x90(%rsp)
movl %edx, 0x8c(%rsp)
movq %rcx, 0x80(%rsp)
movl %r8d, 0x7c(%rsp)
movl 0x8c(%rsp), %eax
cmpl 0x7c(%rsp), %eax
jge 0x159c5
movl 0x8c(%rsp), %eax
movl %eax, 0x8(%rsp)
jmp 0x159cd
movl 0x7c(%rsp), %eax
movl %eax, 0x8(%rsp)
movl 0x8(%rsp), %eax
movl %eax, 0x70(%rsp)
movl 0x70(%rsp), %eax
movl 0x70(%rsp), %ecx
subl $0x1, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
je 0x159f8
movl 0x70(%rsp), %eax
subl $0x1, %eax
andl 0x70(%rsp), %eax
movl %eax, 0x70(%rsp)
jmp 0x159d5
cmpl $0x0, 0x70(%rsp)
je 0x15d78
movl $0x0, 0x6c(%rsp)
movl 0x6c(%rsp), %eax
cmpl 0x70(%rsp), %eax
jge 0x15a60
movq 0x98(%rsp), %rsi
movslq 0x70(%rsp), %rcx
xorl %eax, %eax
subq %rcx, %rax
shlq $0x5, %rax
addq %rax, %rsi
movslq 0x6c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x80(%rsp), %rdi
movslq 0x6c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdi
callq 0x8710
movl 0x6c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x6c(%rsp)
jmp 0x15a0b
movq 0x98(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x60(%rsp)
movq 0x60(%rsp), %rax
cmpq 0x90(%rsp), %rax
jae 0x15b0f
movl $0x0, 0x5c(%rsp)
movq 0x60(%rsp), %rsi
movq 0x60(%rsp), %rdx
addq $-0x20, %rdx
leaq 0xa7(%rsp), %rdi
callq 0xcd80
testb $0x1, %al
jne 0x15aad
jmp 0x15ab5
movl $0x1, 0x5c(%rsp)
movq 0x60(%rsp), %rsi
addq $-0x20, %rsi
movslq 0x5c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x60(%rsp), %rdi
addq $-0x60, %rdi
callq 0x8710
movq 0x60(%rsp), %rsi
movslq 0x5c(%rsp), %rcx
xorl %eax, %eax
subq %rcx, %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x60(%rsp), %rdi
addq $-0x40, %rdi
callq 0x8710
movq 0x60(%rsp), %rax
addq $0x40, %rax
movq %rax, 0x60(%rsp)
jmp 0x15a71
movq 0x90(%rsp), %rax
movq 0x98(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
movl $0x2, %ecx
cqto
idivq %rcx
cmpq $0x0, %rdx
je 0x15b53
movq 0x90(%rsp), %rsi
addq $-0x20, %rsi
movq 0x90(%rsp), %rdi
addq $-0x60, %rdi
callq 0x8710
movq 0x98(%rsp), %rax
addq $-0x40, %rax
movq %rax, 0x98(%rsp)
movq 0x90(%rsp), %rax
addq $-0x40, %rax
movq %rax, 0x90(%rsp)
movl $0x2, 0x78(%rsp)
movl 0x78(%rsp), %eax
cmpl 0x70(%rsp), %eax
jge 0x15d27
movq 0x98(%rsp), %rax
movq %rax, 0x50(%rsp)
movq 0x90(%rsp), %rax
movl 0x78(%rsp), %ecx
shll %ecx
movslq %ecx, %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x48(%rsp)
movq 0x50(%rsp), %rax
cmpq 0x48(%rsp), %rax
ja 0x15c36
movq 0x50(%rsp), %rdi
movq 0x50(%rsp), %rsi
movslq 0x78(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x50(%rsp), %rdx
movslq 0x78(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdx
movslq 0x78(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdx
movq 0x50(%rsp), %rcx
movslq 0x78(%rsp), %r8
xorl %eax, %eax
subq %r8, %rax
shlq $0x5, %rax
addq %rax, %rcx
callq 0x16cf0
movl 0x78(%rsp), %ecx
shll %ecx
movq 0x50(%rsp), %rax
movslq %ecx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x50(%rsp)
jmp 0x15bc0
movq 0x90(%rsp), %rax
movq 0x50(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
movslq 0x78(%rsp), %rcx
cmpq %rcx, %rax
jle 0x15c8f
movq 0x50(%rsp), %rdi
movq 0x50(%rsp), %rsi
movslq 0x78(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x90(%rsp), %rdx
movq 0x50(%rsp), %rcx
movslq 0x78(%rsp), %r8
xorl %eax, %eax
subq %r8, %rax
shlq $0x5, %rax
addq %rax, %rcx
callq 0x16cf0
jmp 0x15cd2
jmp 0x15c91
movq 0x50(%rsp), %rax
cmpq 0x90(%rsp), %rax
jae 0x15cd0
movq 0x50(%rsp), %rsi
movq 0x50(%rsp), %rdi
movslq 0x78(%rsp), %rcx
xorl %eax, %eax
subq %rcx, %rax
shlq $0x5, %rax
addq %rax, %rdi
callq 0x8710
movq 0x50(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x50(%rsp)
jmp 0x15c91
jmp 0x15cd2
movl 0x78(%rsp), %ecx
movq 0x98(%rsp), %rax
movslq %ecx, %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x98(%rsp)
movl 0x78(%rsp), %ecx
movq 0x90(%rsp), %rax
movslq %ecx, %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x90(%rsp)
movl 0x78(%rsp), %eax
shll %eax
movl %eax, 0x78(%rsp)
jmp 0x15b83
movl $0x0, 0x40(%rsp)
movl 0x40(%rsp), %eax
cmpl 0x70(%rsp), %eax
jge 0x15d73
movq 0x80(%rsp), %rsi
movslq 0x40(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x90(%rsp), %rdi
movslq 0x40(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdi
callq 0x8710
movl 0x40(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40(%rsp)
jmp 0x15d2f
jmp 0x15e9b
movq 0x98(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rax
cmpq 0x90(%rsp), %rax
jae 0x15e27
movl $0x0, 0x34(%rsp)
movq 0x38(%rsp), %rsi
movq 0x38(%rsp), %rdx
addq $-0x20, %rdx
leaq 0xa7(%rsp), %rdi
callq 0xcd80
testb $0x1, %al
jne 0x15dc5
jmp 0x15dcd
movl $0x1, 0x34(%rsp)
movq 0x38(%rsp), %rdi
addq $-0x60, %rdi
movq 0x38(%rsp), %rsi
addq $-0x20, %rsi
movslq 0x34(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
callq 0x16c80
movq 0x38(%rsp), %rdi
addq $-0x40, %rdi
movq 0x38(%rsp), %rsi
movslq 0x34(%rsp), %rcx
xorl %eax, %eax
subq %rcx, %rax
shlq $0x5, %rax
addq %rax, %rsi
callq 0x16c80
movq 0x38(%rsp), %rax
addq $0x40, %rax
movq %rax, 0x38(%rsp)
jmp 0x15d89
movq 0x90(%rsp), %rax
movq 0x98(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
movl $0x2, %ecx
cqto
idivq %rcx
cmpq $0x0, %rdx
je 0x15e6b
movq 0x90(%rsp), %rdi
addq $-0x20, %rdi
movq 0x90(%rsp), %rsi
addq $-0x60, %rsi
callq 0x16c80
movq 0x98(%rsp), %rax
addq $-0x40, %rax
movq %rax, 0x98(%rsp)
movq 0x90(%rsp), %rax
addq $-0x40, %rax
movq %rax, 0x90(%rsp)
movl $0x2, 0x78(%rsp)
jmp 0x15e9d
movl 0x78(%rsp), %eax
cmpl 0x8c(%rsp), %eax
jge 0x16029
movq 0x98(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x90(%rsp), %rax
movl 0x78(%rsp), %ecx
shll %ecx
movslq %ecx, %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x20(%rsp)
movq 0x28(%rsp), %rax
cmpq 0x20(%rsp), %rax
ja 0x15f53
movq 0x28(%rsp), %rdi
movq 0x28(%rsp), %rsi
movslq 0x78(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x28(%rsp), %rdx
movslq 0x78(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdx
movslq 0x78(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdx
movq 0x28(%rsp), %rcx
movslq 0x78(%rsp), %r8
xorl %eax, %eax
subq %r8, %rax
shlq $0x5, %rax
addq %rax, %rcx
callq 0x16df0
movl 0x78(%rsp), %ecx
shll %ecx
movq 0x28(%rsp), %rax
movslq %ecx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x28(%rsp)
jmp 0x15edd
movq 0x90(%rsp), %rax
movq 0x28(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
movslq 0x78(%rsp), %rcx
cmpq %rcx, %rax
jle 0x15fac
movq 0x28(%rsp), %rdi
movq 0x28(%rsp), %rsi
movslq 0x78(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x90(%rsp), %rdx
movq 0x28(%rsp), %rcx
movslq 0x78(%rsp), %r8
xorl %eax, %eax
subq %r8, %rax
shlq $0x5, %rax
addq %rax, %rcx
callq 0x16df0
jmp 0x15fd4
movq 0x28(%rsp), %rdi
movslq 0x78(%rsp), %rcx
xorl %eax, %eax
subq %rcx, %rax
shlq $0x5, %rax
addq %rax, %rdi
movq 0x28(%rsp), %rsi
movq 0x90(%rsp), %rdx
callq 0x16af0
movl 0x78(%rsp), %ecx
movq 0x98(%rsp), %rax
movslq %ecx, %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x98(%rsp)
movl 0x78(%rsp), %ecx
movq 0x90(%rsp), %rax
movslq %ecx, %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x90(%rsp)
movl 0x78(%rsp), %eax
shll %eax
movl %eax, 0x78(%rsp)
jmp 0x15e9d
movq 0x90(%rsp), %rax
movq 0x98(%rsp), %rcx
subq %rcx, %rax
sarq $0x5, %rax
movl 0x8c(%rsp), %ecx
shll %ecx
movslq %ecx, %rcx
cqto
idivq %rcx
movl %edx, %eax
movl %eax, 0x74(%rsp)
movq 0x90(%rsp), %rax
movslq 0x74(%rsp), %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x10(%rsp)
movl 0x74(%rsp), %eax
cmpl 0x8c(%rsp), %eax
jg 0x160bf
movq 0x10(%rsp), %rdi
movq 0x10(%rsp), %rsi
movslq 0x74(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x10(%rsp), %rdx
movslq 0x74(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdx
movslq 0x8c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdx
callq 0x16af0
jmp 0x1610e
movq 0x10(%rsp), %rdi
movq 0x10(%rsp), %rsi
movslq 0x8c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x10(%rsp), %rdx
movslq 0x74(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdx
movq 0x10(%rsp), %rcx
movslq 0x74(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rcx
movslq 0x8c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rcx
callq 0x16ed0
jmp 0x16110
movq 0x10(%rsp), %rax
cmpq 0x98(%rsp), %rax
jbe 0x161bd
movl 0x8c(%rsp), %ecx
shll %ecx
movq 0x10(%rsp), %rax
movslq %ecx, %rdx
xorl %ecx, %ecx
subq %rdx, %rcx
shlq $0x5, %rcx
addq %rcx, %rax
movq %rax, 0x10(%rsp)
movq 0x10(%rsp), %rdi
movq 0x10(%rsp), %rsi
movslq 0x8c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rsi
movq 0x10(%rsp), %rdx
movslq 0x8c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdx
movslq 0x8c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rdx
movq 0x10(%rsp), %rcx
movslq 0x8c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rcx
movslq 0x8c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rcx
movslq 0x8c(%rsp), %rax
shlq $0x5, %rax
addq %rax, %rcx
callq 0x16ed0
jmp 0x16110
addq $0xa8, %rsp
retq
nopw %cs:(%rax,%rax)
nop