// File: hdlguy[P]fft_demo/fft.cpp
// Function: Fft::convolve(std::vector<double, std::allocator<double>> const&, std::vector<double, std::allocator<double>> const&, std::vector<double, std::allocator<double>> const&, std::vector<double, std::allocator<double>> const&, std::vector<double, std::allocator<double>>&, std::vector<double, std::allocator<double>>&)
void Fft::convolve(const vector<double> &xreal, const vector<double> &ximag, const vector<double> &yreal, const vector<double> &yimag, vector<double> &outreal, vector<double> &outimag) {
	if (xreal.size() != ximag.size() || xreal.size() != yreal.size() || yreal.size() != yimag.size() || xreal.size() != outreal.size() || outreal.size() != outimag.size())
		throw "Mismatched lengths";
	
	size_t n = xreal.size();
	vector<double> xr(xreal);
	vector<double> xi(ximag);
	vector<double> yr(yreal);
	vector<double> yi(yimag);
	
	transform(xr, xi);
	transform(yr, yi);
	for (size_t i = 0; i < n; i++) {
		double temp = xr[i] * yr[i] - xi[i] * yi[i];
		xi[i] = xi[i] * yr[i] + xr[i] * yi[i];
		xr[i] = temp;
	}
	inverseTransform(xr, xi);
	for (size_t i = 0; i < n; i++) {  // Scaling (because this FFT implementation omits it)
		outreal[i] = xr[i] / n;
		outimag[i] = xi[i] / n;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x160, %rsp            # imm = 0x160
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq -0x8(%rbp), %rdi
callq 0x2e00
movq %rax, -0xc8(%rbp)
movq -0x10(%rbp), %rdi
callq 0x2e00
movq %rax, %rcx
movq -0xc8(%rbp), %rax
cmpq %rcx, %rax
jne 0x27bf
movq -0x8(%rbp), %rdi
callq 0x2e00
movq %rax, -0xd0(%rbp)
movq -0x18(%rbp), %rdi
callq 0x2e00
movq %rax, %rcx
movq -0xd0(%rbp), %rax
cmpq %rcx, %rax
jne 0x27bf
movq -0x18(%rbp), %rdi
callq 0x2e00
movq %rax, -0xd8(%rbp)
movq -0x20(%rbp), %rdi
callq 0x2e00
movq %rax, %rcx
movq -0xd8(%rbp), %rax
cmpq %rcx, %rax
jne 0x27bf
movq -0x8(%rbp), %rdi
callq 0x2e00
movq %rax, -0xe0(%rbp)
movq -0x28(%rbp), %rdi
callq 0x2e00
movq %rax, %rcx
movq -0xe0(%rbp), %rax
cmpq %rcx, %rax
jne 0x27bf
movq -0x28(%rbp), %rdi
callq 0x2e00
movq %rax, -0xe8(%rbp)
movq -0x30(%rbp), %rdi
callq 0x2e00
movq %rax, %rcx
movq -0xe8(%rbp), %rax
cmpq %rcx, %rax
je 0x27e6
movl $0x8, %edi
callq 0x10a0
movq %rax, %rdi
leaq 0x386d(%rip), %rax      # 0x6040
movq %rax, (%rdi)
movq 0x67eb(%rip), %rsi      # 0x8fc8
xorl %eax, %eax
movl %eax, %edx
callq 0x1170
movq -0x8(%rbp), %rdi
callq 0x2e00
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x2f50
movq -0x10(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x2f50
jmp 0x280f
movq -0x18(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0x2f50
jmp 0x2821
movq -0x20(%rbp), %rsi
leaq -0xa8(%rbp), %rdi
callq 0x2f50
jmp 0x2833
leaq -0x50(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x1310
jmp 0x2842
leaq -0x90(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x1310
jmp 0x2857
movq $0x0, -0xb0(%rbp)
movq -0xb0(%rbp), %rax
cmpq -0x38(%rbp), %rax
jae 0x2a65
movq -0xb0(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x2ed0
movsd (%rax), %xmm0
movsd %xmm0, -0x120(%rbp)
movq -0xb0(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0x2ed0
movsd (%rax), %xmm0
movsd %xmm0, -0x118(%rbp)
movq -0xb0(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x2ed0
movsd (%rax), %xmm0
movsd %xmm0, -0x128(%rbp)
movq -0xb0(%rbp), %rsi
leaq -0xa8(%rbp), %rdi
callq 0x2ed0
movsd -0x128(%rbp), %xmm1
movsd -0x120(%rbp), %xmm0
movsd -0x118(%rbp), %xmm2
mulsd (%rax), %xmm1
movq %xmm1, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0xb8(%rbp)
movq -0xb0(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x2ed0
movsd (%rax), %xmm0
movsd %xmm0, -0x108(%rbp)
movq -0xb0(%rbp), %rsi
leaq -0x90(%rbp), %rdi
callq 0x2ed0
movsd (%rax), %xmm0
movsd %xmm0, -0x100(%rbp)
movq -0xb0(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x2ed0
movsd (%rax), %xmm0
movsd %xmm0, -0x110(%rbp)
movq -0xb0(%rbp), %rsi
leaq -0xa8(%rbp), %rdi
callq 0x2ed0
movsd -0x110(%rbp), %xmm1
movsd -0x108(%rbp), %xmm0
movsd -0x100(%rbp), %xmm2
mulsd (%rax), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0xf8(%rbp)
movq -0xb0(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x2ed0
movsd -0xf8(%rbp), %xmm0
movsd %xmm0, (%rax)
movsd -0xb8(%rbp), %xmm0
movsd %xmm0, -0xf0(%rbp)
movq -0xb0(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x2ed0
movsd -0xf0(%rbp), %xmm0
movsd %xmm0, (%rax)
movq -0xb0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xb0(%rbp)
jmp 0x2862
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x2bc2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x2bb9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
jmp 0x2bad
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x2ef0
jmp 0x2bad
leaq -0x50(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x2640
jmp 0x2a74
movq $0x0, -0xc0(%rbp)
movq -0xc0(%rbp), %rax
cmpq -0x38(%rbp), %rax
jae 0x2b7a
movq -0xc0(%rbp), %rsi
leaq -0x50(%rbp), %rdi
callq 0x2ed0
movsd (%rax), %xmm0
movq -0x38(%rbp), %xmm1
movaps 0x3560(%rip), %xmm2     # 0x6010
movaps %xmm2, -0x150(%rbp)
punpckldq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1]
movapd 0x355d(%rip), %xmm2     # 0x6020
movaps %xmm2, -0x140(%rbp)
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x158(%rbp)
movq -0x28(%rbp), %rdi
movq -0xc0(%rbp), %rsi
callq 0x2ed0
movsd -0x158(%rbp), %xmm0
movsd %xmm0, (%rax)
movq -0xc0(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x2ed0
movaps -0x150(%rbp), %xmm3
movaps -0x140(%rbp), %xmm2
movsd (%rax), %xmm0
movq -0x38(%rbp), %xmm1
punpckldq %xmm3, %xmm1    # xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1]
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x130(%rbp)
movq -0x30(%rbp), %rdi
movq -0xc0(%rbp), %rsi
callq 0x2ed0
movsd -0x130(%rbp), %xmm0
movsd %xmm0, (%rax)
movq -0xc0(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xc0(%rbp)
jmp 0x2a7f
leaq -0xa8(%rbp), %rdi
callq 0x2ef0
leaq -0x90(%rbp), %rdi
callq 0x2ef0
leaq -0x68(%rbp), %rdi
callq 0x2ef0
leaq -0x50(%rbp), %rdi
callq 0x2ef0
addq $0x160, %rsp            # imm = 0x160
popq %rbp
retq
leaq -0x90(%rbp), %rdi
callq 0x2ef0
leaq -0x68(%rbp), %rdi
callq 0x2ef0
leaq -0x50(%rbp), %rdi
callq 0x2ef0
movq -0x70(%rbp), %rdi
callq 0x11a0
nopw %cs:(%rax,%rax)