// File: kebwi[P]Trifid/src/FourierTransform.cpp
// Function: fourierTest()
void fourierTest()
{
	SeedRandom(0);
	
	cout << "Float type sizes on this machine:" << endl;
	cout << "    float:       " << sizeof(float) << endl;
	cout << "    double:      " << sizeof(double) << endl;
	cout << "    long double: " << sizeof(long double) << endl;
	cout << endl;
	
	cout << "Fourier Transform correctness test:" << endl;
	cout << "This test being performed with a floating point type of size: " << sizeof(Float_t) << endl;
	cout << "See FloatType.h for information on how to set the floating point type." << endl;
	cout << endl;
	
	Float_t a[16];
	for (int j = 0; j < 4; j++)
		for (int i = 0; i < 4; i++)
			a[j * 4 + i] = RandZeroFloat(1.0);
	
	cout.precision(8);
	cout << "Input array and copy/paste for matlab script:" << endl;
	cout << "a = [ ";
	for (int j = 0; j < 4; j++)
		for (int i = 0; i < 4; i++)
		{
			cout << a[j * 4 + i];
			if (i != 4 - 1)
				cout << ", ";
			else if (j != 4 - 1)
				cout << "; ";
			else cout << " ]" << endl;
		}
	cout << "b = fft2(a)" << endl;
	cout << "c = ifft2(b)" << endl;
	cout << endl;
	
	cout << "Original signal:" << endl;
	for (int j = 0; j < 4; j++)
	{
		for (int i = 0; i < 4; i++)
			cout << setw(15) << a[j * 4 + i];
		cout << endl;
	}
	cout << endl;
	
	int err = fft2dInit(log2(4), log2(4));
	if (err != 0)
		cout << err << endl;
	
	rfft2d(a, log2(4), log2(4));
	
	cout << "Fourier Transform:" << endl;
	for (int j = 0; j < 4; j++)
	{
		for (int i = 0; i < 4; i++)
			cout << setw(15) << a[j * 4 + i];
		cout << endl;
	}
	cout << endl;
	
	rifft2d(a, log2(4), log2(4));
	
	cout << "Inverse Fourier Transform (should match original signal above):" << endl;
	for (int j = 0; j < 4; j++)
	{
		for (int i = 0; i < 4; i++)
			cout << setw(15) << a[j * 4 + i];
		cout << endl;
	}
	cout << endl;
	
	//=======================================================================
	
	cout << "Fourier Transform timing test" << endl;
	cout << "This test being performed with a floating point type of size: " << sizeof(Float_t) << endl;
	cout << "See FloatType.h for information on how to set the floating point type." << endl;
	cout << endl;
	
	int dim = 512;
	Float_t *a2 = new Float_t[dim * dim];
	for (int j = 0; j < dim; j++)
		for (int i = 0; i < dim; i++)
			a2[j * dim + i] = RandZeroFloat(1.0);
	
	err = fft2dInit(log2(dim), log2(dim));
	if (err != 0)
		cout << err << endl;
	
	Float_t meanTime_s = 0;
	int numPasses = 100;
	for (int i = 0; i < numPasses; i++)
	{
		unsigned long startTime = getCurrentTime_ms();
		rfft2d(a2, log2(dim), log2(dim));
		unsigned long elapsedTime = getCurrentTime_ms() - startTime;
		meanTime_s += (Float_t)elapsedTime / CURRENT_TIME_PER_SEC_F;
	}
	meanTime_s /= (Float_t)numPasses;
	cout << "Mean time to perform 2D Fourier Transform on a " << dim << " x " << dim << " image: "
		<< meanTime_s << " seconds" << endl << endl;
	
	delete [] a2;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x140, %rsp            # imm = 0x140
xorl %edi, %edi
callq 0x37e60
movq 0x316b7(%rip), %rdi     # 0x59fd0
leaq 0x236cb(%rip), %rsi     # 0x4bfeb
callq 0x4390
movq %rax, %rdi
movq 0x31689(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x31695(%rip), %rdi     # 0x59fd0
leaq 0x236cb(%rip), %rsi     # 0x4c00d
callq 0x4390
movq %rax, %rdi
movl $0x4, %esi
callq 0x40c0
movq %rax, %rdi
movq 0x3165a(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x31666(%rip), %rdi     # 0x59fd0
leaq 0x236ae(%rip), %rsi     # 0x4c01f
callq 0x4390
movq %rax, %rdi
movl $0x8, %esi
callq 0x40c0
movq %rax, %rdi
movq 0x3162b(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x31637(%rip), %rdi     # 0x59fd0
leaq 0x23691(%rip), %rsi     # 0x4c031
callq 0x4390
movq %rax, %rdi
movl $0x10, %esi
callq 0x40c0
movq %rax, %rdi
movq 0x315fc(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x31608(%rip), %rdi     # 0x59fd0
movq 0x315e9(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x315f5(%rip), %rdi     # 0x59fd0
leaq 0x23661(%rip), %rsi     # 0x4c043
callq 0x4390
movq %rax, %rdi
movq 0x315c7(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x315d3(%rip), %rdi     # 0x59fd0
leaq 0x23663(%rip), %rsi     # 0x4c067
callq 0x4390
movq %rax, %rdi
movl $0x8, %esi
callq 0x40c0
movq %rax, %rdi
movq 0x31598(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x315a4(%rip), %rdi     # 0x59fd0
leaq 0x23673(%rip), %rsi     # 0x4c0a6
callq 0x4390
movq %rax, %rdi
movq 0x31576(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x31582(%rip), %rdi     # 0x59fd0
movq 0x31563(%rip), %rsi     # 0x59fb8
callq 0x43d0
movl $0x0, -0x84(%rbp)
cmpl $0x4, -0x84(%rbp)
jge 0x28ac8
movl $0x0, -0x88(%rbp)
cmpl $0x4, -0x88(%rbp)
jge 0x28ab5
movsd 0x20598(%rip), %xmm0    # 0x49020
callq 0x37ee0
movl -0x84(%rbp), %eax
shll $0x2, %eax
addl -0x88(%rbp), %eax
cltq
movsd %xmm0, -0x80(%rbp,%rax,8)
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0x28a77
jmp 0x28ab7
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
jmp 0x28a64
movq 0x31501(%rip), %rax     # 0x59fd0
movq (%rax), %rax
movq 0x314f7(%rip), %rdi     # 0x59fd0
addq -0x18(%rax), %rdi
movl $0x8, %esi
callq 0xf310
movq 0x314e2(%rip), %rdi     # 0x59fd0
leaq 0x235f8(%rip), %rsi     # 0x4c0ed
callq 0x4390
movq %rax, %rdi
movq 0x314b4(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x314c0(%rip), %rdi     # 0x59fd0
leaq 0x23604(%rip), %rsi     # 0x4c11b
callq 0x4390
movl $0x0, -0x8c(%rbp)
cmpl $0x4, -0x8c(%rbp)
jge 0x28bf9
movl $0x0, -0x90(%rbp)
cmpl $0x4, -0x90(%rbp)
jge 0x28be3
movl -0x8c(%rbp), %eax
shll $0x2, %eax
addl -0x90(%rbp), %eax
cltq
movsd -0x80(%rbp,%rax,8), %xmm0
movq 0x31468(%rip), %rdi     # 0x59fd0
callq 0x4670
cmpl $0x3, -0x90(%rbp)
je 0x28b8b
movq 0x31453(%rip), %rdi     # 0x59fd0
leaq 0x22962(%rip), %rsi     # 0x4b4e6
callq 0x4390
jmp 0x28bcd
cmpl $0x3, -0x8c(%rbp)
je 0x28ba9
movq 0x31435(%rip), %rdi     # 0x59fd0
leaq 0x23580(%rip), %rsi     # 0x4c122
callq 0x4390
jmp 0x28bcb
movq 0x31420(%rip), %rdi     # 0x59fd0
leaq 0x2356e(%rip), %rsi     # 0x4c125
callq 0x4390
movq %rax, %rdi
movq 0x313f2(%rip), %rsi     # 0x59fb8
callq 0x43d0
jmp 0x28bcd
jmp 0x28bcf
movl -0x90(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x90(%rbp)
jmp 0x28b3d
jmp 0x28be5
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
jmp 0x28b26
movq 0x313d0(%rip), %rdi     # 0x59fd0
leaq 0x23521(%rip), %rsi     # 0x4c128
callq 0x4390
movq %rax, %rdi
movq 0x313a2(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x313ae(%rip), %rdi     # 0x59fd0
leaq 0x2350b(%rip), %rsi     # 0x4c134
callq 0x4390
movq %rax, %rdi
movq 0x31380(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x3138c(%rip), %rdi     # 0x59fd0
movq 0x3136d(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x31379(%rip), %rdi     # 0x59fd0
leaq 0x234e3(%rip), %rsi     # 0x4c141
callq 0x4390
movq %rax, %rdi
movq 0x3134b(%rip), %rsi     # 0x59fb8
callq 0x43d0
movl $0x0, -0x94(%rbp)
cmpl $0x4, -0x94(%rbp)
jge 0x28d15
movl $0x0, -0x98(%rbp)
cmpl $0x4, -0x98(%rbp)
jge 0x28cee
movl $0xf, %edi
callq 0xe410
movl %eax, -0x9c(%rbp)
movl -0x9c(%rbp), %esi
movq 0x31317(%rip), %rdi     # 0x59fd0
callq 0x4430
movq %rax, %rdi
movl -0x94(%rbp), %eax
shll $0x2, %eax
addl -0x98(%rbp), %eax
cltq
movsd -0x80(%rbp,%rax,8), %xmm0
callq 0x4670
movl -0x98(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x98(%rbp)
jmp 0x28c93
movq 0x312db(%rip), %rdi     # 0x59fd0
movq 0x312bc(%rip), %rsi     # 0x59fb8
callq 0x43d0
movl -0x94(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x94(%rbp)
jmp 0x28c7c
movq 0x312b4(%rip), %rdi     # 0x59fd0
movq 0x31295(%rip), %rsi     # 0x59fb8
callq 0x43d0
movl $0x4, %edi
callq 0x29350
cvttsd2si %xmm0, %rax
movq %rax, -0xf8(%rbp)
movl $0x4, %edi
callq 0x29350
movq -0xf8(%rbp), %rdi
cvttsd2si %xmm0, %rsi
callq 0x384c0
movl %eax, -0xa0(%rbp)
cmpl $0x0, -0xa0(%rbp)
je 0x28d89
movl -0xa0(%rbp), %esi
movq 0x3125b(%rip), %rdi     # 0x59fd0
callq 0x4600
movq %rax, %rdi
movq 0x31234(%rip), %rsi     # 0x59fb8
callq 0x43d0
leaq -0x80(%rbp), %rax
movq %rax, -0x108(%rbp)
movl $0x4, %edi
callq 0x29350
cvttsd2si %xmm0, %rax
movq %rax, -0x100(%rbp)
movl $0x4, %edi
callq 0x29350
movq -0x108(%rbp), %rdi
movq -0x100(%rbp), %rsi
cvttsd2si %xmm0, %rdx
callq 0x39510
movq 0x311fd(%rip), %rdi     # 0x59fd0
leaq 0x23378(%rip), %rsi     # 0x4c152
callq 0x4390
movq %rax, %rdi
movq 0x311cf(%rip), %rsi     # 0x59fb8
callq 0x43d0
movl $0x0, -0xa4(%rbp)
cmpl $0x4, -0xa4(%rbp)
jge 0x28e91
movl $0x0, -0xa8(%rbp)
cmpl $0x4, -0xa8(%rbp)
jge 0x28e6a
movl $0xf, %edi
callq 0xe410
movl %eax, -0xac(%rbp)
movl -0xac(%rbp), %esi
movq 0x3119b(%rip), %rdi     # 0x59fd0
callq 0x4430
movq %rax, %rdi
movl -0xa4(%rbp), %eax
shll $0x2, %eax
addl -0xa8(%rbp), %eax
cltq
movsd -0x80(%rbp,%rax,8), %xmm0
callq 0x4670
movl -0xa8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa8(%rbp)
jmp 0x28e0f
movq 0x3115f(%rip), %rdi     # 0x59fd0
movq 0x31140(%rip), %rsi     # 0x59fb8
callq 0x43d0
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x28df8
movq 0x31138(%rip), %rdi     # 0x59fd0
movq 0x31119(%rip), %rsi     # 0x59fb8
callq 0x43d0
leaq -0x80(%rbp), %rax
movq %rax, -0x118(%rbp)
movl $0x4, %edi
callq 0x29350
cvttsd2si %xmm0, %rax
movq %rax, -0x110(%rbp)
movl $0x4, %edi
callq 0x29350
movq -0x118(%rbp), %rdi
movq -0x110(%rbp), %rsi
cvttsd2si %xmm0, %rdx
callq 0x39be0
movq 0x310e2(%rip), %rdi     # 0x59fd0
leaq 0x23270(%rip), %rsi     # 0x4c165
callq 0x4390
movq %rax, %rdi
movq 0x310b4(%rip), %rsi     # 0x59fb8
callq 0x43d0
movl $0x0, -0xb0(%rbp)
cmpl $0x4, -0xb0(%rbp)
jge 0x28fac
movl $0x0, -0xb4(%rbp)
cmpl $0x4, -0xb4(%rbp)
jge 0x28f85
movl $0xf, %edi
callq 0xe410
movl %eax, -0xb8(%rbp)
movl -0xb8(%rbp), %esi
movq 0x31080(%rip), %rdi     # 0x59fd0
callq 0x4430
movq %rax, %rdi
movl -0xb0(%rbp), %eax
shll $0x2, %eax
addl -0xb4(%rbp), %eax
cltq
movsd -0x80(%rbp,%rax,8), %xmm0
callq 0x4670
movl -0xb4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb4(%rbp)
jmp 0x28f2a
movq 0x31044(%rip), %rdi     # 0x59fd0
movq 0x31025(%rip), %rsi     # 0x59fb8
callq 0x43d0
movl -0xb0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb0(%rbp)
jmp 0x28f13
movq 0x3101d(%rip), %rdi     # 0x59fd0
movq 0x30ffe(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x3100a(%rip), %rdi     # 0x59fd0
leaq 0x231d8(%rip), %rsi     # 0x4c1a5
callq 0x4390
movq %rax, %rdi
movq 0x30fdc(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x30fe8(%rip), %rdi     # 0x59fd0
leaq 0x23078(%rip), %rsi     # 0x4c067
callq 0x4390
movq %rax, %rdi
movl $0x8, %esi
callq 0x40c0
movq %rax, %rdi
movq 0x30fad(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x30fb9(%rip), %rdi     # 0x59fd0
leaq 0x23088(%rip), %rsi     # 0x4c0a6
callq 0x4390
movq %rax, %rdi
movq 0x30f8b(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq 0x30f97(%rip), %rdi     # 0x59fd0
movq 0x30f78(%rip), %rsi     # 0x59fb8
callq 0x43d0
movl $0x200, -0xbc(%rbp)     # imm = 0x200
movl -0xbc(%rbp), %eax
imull -0xbc(%rbp), %eax
cltq
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x4030
movq %rax, -0xc8(%rbp)
movl $0x0, -0xcc(%rbp)
movl -0xcc(%rbp), %eax
cmpl -0xbc(%rbp), %eax
jge 0x29109
movl $0x0, -0xd0(%rbp)
movl -0xd0(%rbp), %eax
cmpl -0xbc(%rbp), %eax
jge 0x290f6
movsd 0x1ff62(%rip), %xmm0    # 0x49020
callq 0x37ee0
movq -0xc8(%rbp), %rax
movl -0xcc(%rbp), %ecx
imull -0xbc(%rbp), %ecx
addl -0xd0(%rbp), %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0xd0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd0(%rbp)
jmp 0x290a8
jmp 0x290f8
movl -0xcc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xcc(%rbp)
jmp 0x29090
movl -0xbc(%rbp), %edi
callq 0x29350
cvttsd2si %xmm0, %rax
movq %rax, -0x120(%rbp)
movl -0xbc(%rbp), %edi
callq 0x29350
movq -0x120(%rbp), %rdi
cvttsd2si %xmm0, %rsi
callq 0x384c0
movl %eax, -0xa0(%rbp)
cmpl $0x0, -0xa0(%rbp)
je 0x2916c
movl -0xa0(%rbp), %esi
movq 0x30e78(%rip), %rdi     # 0x59fd0
callq 0x4600
movq %rax, %rdi
movq 0x30e51(%rip), %rsi     # 0x59fb8
callq 0x43d0
xorps %xmm0, %xmm0
movsd %xmm0, -0xd8(%rbp)
movl $0x64, -0xdc(%rbp)
movl $0x0, -0xe0(%rbp)
movl -0xe0(%rbp), %eax
cmpl -0xdc(%rbp), %eax
jge 0x29261
callq 0x55c0
movq %rax, -0xe8(%rbp)
movq -0xc8(%rbp), %rax
movq %rax, -0x130(%rbp)
movl -0xbc(%rbp), %edi
callq 0x29350
cvttsd2si %xmm0, %rax
movq %rax, -0x128(%rbp)
movl -0xbc(%rbp), %edi
callq 0x29350
movq -0x130(%rbp), %rdi
movq -0x128(%rbp), %rsi
cvttsd2si %xmm0, %rdx
callq 0x39510
callq 0x55c0
movq -0xe8(%rbp), %rcx
subq %rcx, %rax
movq %rax, -0xf0(%rbp)
movaps 0x1fe42(%rip), %xmm1    # 0x49050
movq -0xf0(%rbp), %xmm0
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x1fe3e(%rip), %xmm1    # 0x49060
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd 0x229e7(%rip), %xmm1    # 0x4bc20
divsd %xmm1, %xmm0
addsd -0xd8(%rbp), %xmm0
movsd %xmm0, -0xd8(%rbp)
movl -0xe0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe0(%rbp)
jmp 0x2918b
cvtsi2sdl -0xdc(%rbp), %xmm1
movsd -0xd8(%rbp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, -0xd8(%rbp)
movq 0x30d4c(%rip), %rdi     # 0x59fd0
leaq 0x22f38(%rip), %rsi     # 0x4c1c3
callq 0x4390
movq %rax, %rdi
movl -0xbc(%rbp), %esi
callq 0x4600
movq %rax, %rdi
leaq 0x22f4b(%rip), %rsi     # 0x4c1f3
callq 0x4390
movq %rax, %rdi
movl -0xbc(%rbp), %esi
callq 0x4600
movq %rax, %rdi
leaq 0x22f32(%rip), %rsi     # 0x4c1f7
callq 0x4390
movq %rax, %rdi
movsd -0xd8(%rbp), %xmm0
callq 0x4670
movq %rax, %rdi
leaq 0x22f1c(%rip), %rsi     # 0x4c200
callq 0x4390
movq %rax, %rdi
movq 0x30cc5(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq %rax, %rdi
movq 0x30cb6(%rip), %rsi     # 0x59fb8
callq 0x43d0
movq -0xc8(%rbp), %rax
movq %rax, -0x138(%rbp)
cmpq $0x0, %rax
je 0x29327
movq -0x138(%rbp), %rdi
callq 0x44d0
addq $0x140, %rsp            # imm = 0x140
popq %rbp
retq