// File: patmorin[P]rotate/rotatetest.cpp
// Function: main
int main(int argc, char *argv[]) {
    Index n, r;

    if (argc != 3) usage(argv[0]);
    std::istringstream is_n(argv[1]);
    is_n >> n;
    std::istringstream is_r(argv[2]);
    is_r >> r;

    std::cout << "n = " << n << ", r = " << r << std::endl;

		auto *a = new Data[n];

		Rotater fns[] =
		{ rotate_std<Data,Index>, rotate_stdrev<Data,Index>,
			rotate_rev<Data,Index>, rotate_gcd<Data,Index> };
		std::string fn_names[] =
		{ "rotate_std", "rotate_stdrev", "rotate_rev", "rotate_gcd" };

		if (n <= 50) {
			for (int i = 0; i < 4; i++) {
				std::iota(a, a+n, 1);
				print_array(a, n);
				rotate_std(a, n, r);
				print_array(a, n);
				std::cout << std::endl;
			}
		} else {
			for (int i = 0; i < 4; i++) {
		    std::iota(a, a+n, 1);

				std::cout << std::setw(20) << fn_names[i] << " : ";
		    speed_test(a, n, r, fns[i]);
			}
		}
    return 0;
}

// Assembly:
subq $0x528, %rsp            # imm = 0x528
movl $0x0, 0x524(%rsp)
movl %edi, 0x520(%rsp)
movq %rsi, 0x518(%rsp)
cmpl $0x3, 0x520(%rsp)
je 0x134b
movq 0x518(%rsp), %rax
movq (%rax), %rdi
callq 0x12c0
movq 0x518(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0xd0(%rsp)
leaq 0x367(%rsp), %rdi
movq %rdi, 0xd8(%rsp)
callq 0x1160
movq 0xd0(%rsp), %rsi
movq 0xd8(%rsp), %rdx
leaq 0x368(%rsp), %rdi
callq 0x1100
jmp 0x1393
leaq 0x388(%rsp), %rdi
leaq 0x368(%rsp), %rsi
movl $0x8, %edx
callq 0x1140
jmp 0x13af
leaq 0x368(%rsp), %rdi
callq 0x1070
leaq 0x367(%rsp), %rdi
callq 0x10c0
leaq 0x388(%rsp), %rdi
leaq 0x510(%rsp), %rsi
callq 0x1110
jmp 0x13e0
movq 0x518(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0xc0(%rsp)
leaq 0x1af(%rsp), %rdi
movq %rdi, 0xc8(%rsp)
callq 0x1160
movq 0xc0(%rsp), %rsi
movq 0xc8(%rsp), %rdx
leaq 0x1b0(%rsp), %rdi
callq 0x1100
jmp 0x1428
leaq 0x1d0(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
movl $0x8, %edx
callq 0x1140
jmp 0x1444
leaq 0x1b0(%rsp), %rdi
callq 0x1070
leaq 0x1af(%rsp), %rdi
callq 0x10c0
leaq 0x1d0(%rsp), %rdi
leaq 0x508(%rsp), %rsi
callq 0x1110
jmp 0x1475
movq 0x3b4c(%rip), %rdi      # 0x4fc8
leaq 0x1b9e(%rip), %rsi      # 0x3021
callq 0x10a0
movq %rax, 0xb8(%rsp)
jmp 0x1492
movq 0xb8(%rsp), %rdi
movq 0x510(%rsp), %rsi
callq 0x1050
movq %rax, 0xb0(%rsp)
jmp 0x14b1
movq 0xb0(%rsp), %rdi
leaq 0x1b66(%rip), %rsi      # 0x3026
callq 0x10a0
movq %rax, 0xa8(%rsp)
jmp 0x14cf
movq 0xa8(%rsp), %rdi
movq 0x508(%rsp), %rsi
callq 0x1050
movq %rax, 0xa0(%rsp)
jmp 0x14ee
movq 0xa0(%rsp), %rdi
movq 0x3abb(%rip), %rsi      # 0x4fb8
callq 0x10b0
jmp 0x1504
movq 0x510(%rsp), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
movq $-0x1, %rax
cmovoq %rax, %rdi
callq 0x1030
movq %rax, 0x98(%rsp)
jmp 0x1531
movq 0x98(%rsp), %rax
movq %rax, 0x1a0(%rsp)
vmovdqu 0x3837(%rip), %ymm0     # 0x4d80
vmovdqu %ymm0, 0x180(%rsp)
movb $0x1, 0xf3(%rsp)
leaq 0x100(%rsp), %rax
movq %rax, 0x88(%rsp)
movq %rax, 0xf8(%rsp)
leaq 0xf7(%rsp), %rdi
movq %rdi, 0x90(%rsp)
vzeroupper
callq 0x1160
movq 0x88(%rsp), %rdi
movq 0x90(%rsp), %rdx
leaq 0x1a8c(%rip), %rsi      # 0x302d
callq 0x1100
jmp 0x15a8
leaq 0x120(%rsp), %rax
movq %rax, 0x78(%rsp)
movq %rax, 0xf8(%rsp)
leaq 0xf6(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0x1160
movq 0x78(%rsp), %rdi
movq 0x80(%rsp), %rdx
leaq 0x1a52(%rip), %rsi      # 0x3038
callq 0x1100
jmp 0x15ed
leaq 0x140(%rsp), %rax
movq %rax, 0x68(%rsp)
movq %rax, 0xf8(%rsp)
leaq 0xf5(%rsp), %rdi
movq %rdi, 0x70(%rsp)
callq 0x1160
movq 0x68(%rsp), %rdi
movq 0x70(%rsp), %rdx
leaq 0x1a21(%rip), %rsi      # 0x3046
callq 0x1100
jmp 0x162c
leaq 0x160(%rsp), %rax
movq %rax, 0x58(%rsp)
movq %rax, 0xf8(%rsp)
leaq 0xf4(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0x1160
movq 0x58(%rsp), %rdi
movq 0x60(%rsp), %rdx
leaq 0x19ed(%rip), %rsi      # 0x3051
callq 0x1100
jmp 0x166b
movb $0x0, 0xf3(%rsp)
leaq 0xf4(%rsp), %rdi
callq 0x10c0
leaq 0xf5(%rsp), %rdi
callq 0x10c0
leaq 0xf6(%rsp), %rdi
callq 0x10c0
leaq 0xf7(%rsp), %rdi
callq 0x10c0
cmpq $0x32, 0x510(%rsp)
ja 0x1944
movl $0x0, 0xec(%rsp)
cmpl $0x4, 0xec(%rsp)
jge 0x193f
movq 0x1a0(%rsp), %rdi
movq 0x510(%rsp), %rax
leaq (%rdi,%rax,4), %rsi
movl $0x1, %edx
callq 0x1d60
jmp 0x16ef
movq 0x1a0(%rsp), %rdi
movq 0x510(%rsp), %rsi
callq 0x1db0
jmp 0x1706
movq 0x1a0(%rsp), %rdi
movq 0x510(%rsp), %rsi
movq 0x508(%rsp), %rdx
callq 0x1b00
jmp 0x1725
movq 0x1a0(%rsp), %rdi
movq 0x510(%rsp), %rsi
callq 0x1db0
jmp 0x173c
movq 0x3885(%rip), %rdi      # 0x4fc8
movq 0x386e(%rip), %rsi      # 0x4fb8
callq 0x10b0
jmp 0x1751
jmp 0x1753
movl 0xec(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xec(%rsp)
jmp 0x16c1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x358(%rsp)
movl %eax, 0x354(%rsp)
jmp 0x17a0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x358(%rsp)
movl %eax, 0x354(%rsp)
leaq 0x368(%rsp), %rdi
callq 0x1070
leaq 0x367(%rsp), %rdi
callq 0x10c0
jmp 0x1ae7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x358(%rsp)
movl %eax, 0x354(%rsp)
jmp 0x1ada
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x358(%rsp)
movl %eax, 0x354(%rsp)
jmp 0x1802
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x358(%rsp)
movl %eax, 0x354(%rsp)
leaq 0x1b0(%rsp), %rdi
callq 0x1070
leaq 0x1af(%rsp), %rdi
callq 0x10c0
jmp 0x1ada
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x358(%rsp)
movl %eax, 0x354(%rsp)
jmp 0x1acd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x358(%rsp)
movl %eax, 0x354(%rsp)
jmp 0x18aa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x358(%rsp)
movl %eax, 0x354(%rsp)
jmp 0x189d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x358(%rsp)
movl %eax, 0x354(%rsp)
jmp 0x1890
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x358(%rsp)
movl %eax, 0x354(%rsp)
leaq 0xf4(%rsp), %rdi
callq 0x10c0
leaq 0xf5(%rsp), %rdi
callq 0x10c0
leaq 0xf6(%rsp), %rdi
callq 0x10c0
leaq 0xf7(%rsp), %rdi
callq 0x10c0
testb $0x1, 0xf3(%rsp)
jne 0x18c3
jmp 0x1909
movq 0xf8(%rsp), %rax
leaq 0x100(%rsp), %rcx
cmpq %rax, %rcx
movq %rax, 0x50(%rsp)
je 0x1907
movq 0x50(%rsp), %rdi
addq $-0x20, %rdi
movq %rdi, 0x48(%rsp)
callq 0x1070
movq 0x48(%rsp), %rax
leaq 0x100(%rsp), %rcx
cmpq %rcx, %rax
movq %rax, 0x50(%rsp)
jne 0x18dd
jmp 0x1909
jmp 0x1acd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x358(%rsp)
movl %eax, 0x354(%rsp)
leaq 0x100(%rsp), %rax
movq %rax, 0x38(%rsp)
addq $0x80, %rax
movq %rax, 0x40(%rsp)
jmp 0x1aa6
jmp 0x1a33
movl $0x0, 0xe8(%rsp)
cmpl $0x4, 0xe8(%rsp)
jge 0x1a31
movq 0x1a0(%rsp), %rdi
movq 0x510(%rsp), %rax
leaq (%rdi,%rax,4), %rsi
movl $0x1, %edx
callq 0x1d60
jmp 0x197d
movl $0x14, %edi
callq 0x1e50
movl %eax, 0x34(%rsp)
jmp 0x198d
movl 0x34(%rsp), %eax
movl %eax, 0xe4(%rsp)
movl 0xe4(%rsp), %esi
movq 0x3622(%rip), %rdi      # 0x4fc8
callq 0x10d0
movq %rax, 0x28(%rsp)
jmp 0x19b2
movq 0x28(%rsp), %rdi
movslq 0xe8(%rsp), %rax
shlq $0x5, %rax
leaq 0x100(%rsp,%rax), %rsi
callq 0x1090
movq %rax, 0x20(%rsp)
jmp 0x19d7
movq 0x20(%rsp), %rdi
leaq 0x1679(%rip), %rsi      # 0x305c
callq 0x10a0
jmp 0x19ea
movq 0x1a0(%rsp), %rdi
movq 0x510(%rsp), %rsi
movq 0x508(%rsp), %rdx
movslq 0xe8(%rsp), %rax
movq 0x180(%rsp,%rax,8), %rcx
callq 0x1e70
jmp 0x1a19
jmp 0x1a1b
movl 0xe8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xe8(%rsp)
jmp 0x194f
jmp 0x1a33
movl $0x0, 0x524(%rsp)
leaq 0x100(%rsp), %rax
movq %rax, 0x10(%rsp)
addq $0x80, %rax
movq %rax, 0x18(%rsp)
movq 0x18(%rsp), %rdi
addq $-0x20, %rdi
movq %rdi, 0x8(%rsp)
callq 0x1070
movq 0x10(%rsp), %rcx
movq 0x8(%rsp), %rax
cmpq %rcx, %rax
movq %rax, 0x18(%rsp)
jne 0x1a56
leaq 0x1d0(%rsp), %rdi
callq 0x1060
leaq 0x388(%rsp), %rdi
callq 0x1060
movl 0x524(%rsp), %eax
addq $0x528, %rsp            # imm = 0x528
retq
movq 0x40(%rsp), %rdi
addq $-0x20, %rdi
movq %rdi, (%rsp)
callq 0x1070
movq 0x38(%rsp), %rcx
movq (%rsp), %rax
cmpq %rcx, %rax
movq %rax, 0x40(%rsp)
jne 0x1aa6
jmp 0x1acd
leaq 0x1d0(%rsp), %rdi
callq 0x1060
leaq 0x388(%rsp), %rdi
callq 0x1060
movq 0x358(%rsp), %rdi
callq 0x1150
nopw %cs:(%rax,%rax)
nop