// File: kebwi[P]Trifid/src/FourierTransform.cpp
// Function: convolveImages(ImageReal const&, ImageReal const&, ImageReal&)
bool convolveImages(const ImageReal &img1, const ImageReal &img2, ImageReal &imgConv)
{
	int maxWidth = max(img1.width(), img2.width());
	int maxHeight = max(img1.height(), img2.height());
	int maxHalfWidth = maxWidth / 2, maxHalfHeight = maxHeight / 2;
	
	if (!assertValidDims(maxWidth, maxHeight))
		return false;
	
	ImageReal img1Temp;
	int offsetX, offsetY;
	assert(embedImageInPow2Bounds(img1, maxWidth, maxHeight, img1Temp, offsetX, offsetY));
	ImageReal img2Temp;
	assert(embedImageInPow2Bounds(img2, maxWidth, maxHeight, img2Temp, offsetX, offsetY));
	
	//Half shift the second image
	ImageReal img2Shifted(maxWidth, maxHeight);
	for (int y = 0; y < maxHeight; y++)
		for (int x = 0; x < maxWidth; x++)
			img2Shifted(x, y) =
				img2Temp((x + maxHalfWidth) % maxWidth, (y + maxHalfHeight) % maxHeight);
	
	//Get the Fourier Transform of the images
	ImageReal img1Ft(maxWidth, maxHeight);
	assert(doFourierAnalysis(img1Temp, img1Ft));
	ImageReal img2Ft(maxWidth, maxHeight);
	assert(doFourierAnalysis(img2Shifted, img2Ft));
	
	//Multiplty the Fourier Transforms
	imgConv.resize(maxWidth, maxHeight);
	rspect2dprod(img1Ft.img(), img2Ft.img(), imgConv.img(), maxHeight, maxWidth);
	
	int err = fft2dInit(log2(maxHeight), log2(maxWidth));
	if (err != 0)
		return false;
	
	//Invert the Fourier Transform
	rifft2d(imgConv.img(), log2(maxHeight), log2(maxWidth));
	
	return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x240, %rsp            # imm = 0x240
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rdi
callq 0xedd0
movl %eax, -0x28(%rbp)
movq -0x18(%rbp), %rdi
callq 0xedd0
movl %eax, -0x2c(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x2c(%rbp), %rsi
callq 0x29370
movl (%rax), %eax
movl %eax, -0x24(%rbp)
movq -0x10(%rbp), %rdi
callq 0xedf0
movl %eax, -0x34(%rbp)
movq -0x18(%rbp), %rdi
callq 0xedf0
movl %eax, -0x38(%rbp)
leaq -0x34(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x29370
movl (%rax), %eax
movl %eax, -0x30(%rbp)
movl -0x24(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, -0x3c(%rbp)
movl -0x30(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, -0x40(%rbp)
movl -0x24(%rbp), %edi
movl -0x30(%rbp), %esi
callq 0x26640
testb $0x1, %al
jne 0x2840f
movb $0x0, -0x1(%rbp)
jmp 0x288da
leaq -0x80(%rbp), %rdi
movq %rdi, -0x1b8(%rbp)
callq 0x155e0
movq -0x1b8(%rbp), %rcx
movq -0x10(%rbp), %rdi
movl -0x24(%rbp), %esi
movl -0x30(%rbp), %edx
leaq -0x84(%rbp), %r8
leaq -0x88(%rbp), %r9
callq 0x27b60
movb %al, -0x1a9(%rbp)
jmp 0x2844b
movb -0x1a9(%rbp), %al
testb $0x1, %al
jne 0x28457
jmp 0x28459
jmp 0x2848f
leaq 0x23a5d(%rip), %rdi     # 0x4bebd
leaq 0x237e8(%rip), %rsi     # 0x4bc4f
movl $0x18a, %edx            # imm = 0x18A
leaq 0x23a98(%rip), %rcx     # 0x4bf0b
callq 0x4240
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x288cf
leaq -0xd8(%rbp), %rdi
callq 0x155e0
jmp 0x2849d
movq -0x18(%rbp), %rdi
movl -0x24(%rbp), %esi
movl -0x30(%rbp), %edx
leaq -0xd8(%rbp), %rcx
leaq -0x84(%rbp), %r8
leaq -0x88(%rbp), %r9
callq 0x27b60
movb %al, -0x1b9(%rbp)
jmp 0x284c9
movb -0x1b9(%rbp), %al
testb $0x1, %al
jne 0x284d5
jmp 0x284d7
jmp 0x2850d
leaq 0x23a74(%rip), %rdi     # 0x4bf52
leaq 0x2376a(%rip), %rsi     # 0x4bc4f
movl $0x18c, %edx            # imm = 0x18C
leaq 0x23a1a(%rip), %rcx     # 0x4bf0b
callq 0x4240
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x288c3
movl -0x24(%rbp), %esi
movl -0x30(%rbp), %edx
leaq -0x118(%rbp), %rdi
callq 0x15710
jmp 0x28521
movl $0x0, -0x11c(%rbp)
movl -0x11c(%rbp), %eax
cmpl -0x30(%rbp), %eax
jge 0x28614
movl $0x0, -0x120(%rbp)
movl -0x120(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x285fe
movl -0x120(%rbp), %eax
movl -0x3c(%rbp), %ecx
addl %ecx, %eax
movl -0x24(%rbp), %ecx
cltd
idivl %ecx
movl %edx, %esi
movl -0x11c(%rbp), %eax
movl -0x40(%rbp), %ecx
addl %ecx, %eax
movl -0x30(%rbp), %ecx
cltd
idivl %ecx
leaq -0xd8(%rbp), %rdi
callq 0x16fd0
movq %rax, -0x1c8(%rbp)
jmp 0x2858c
movq -0x1c8(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x1d8(%rbp)
movl -0x120(%rbp), %esi
movl -0x11c(%rbp), %edx
leaq -0x118(%rbp), %rdi
callq 0x16fd0
movq %rax, -0x1d0(%rbp)
jmp 0x285c0
movq -0x1d0(%rbp), %rax
movsd -0x1d8(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x120(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x120(%rbp)
jmp 0x28544
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x288b7
jmp 0x28600
movl -0x11c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x11c(%rbp)
jmp 0x2852b
movl -0x24(%rbp), %esi
movl -0x30(%rbp), %edx
leaq -0x160(%rbp), %rdi
callq 0x15710
jmp 0x28628
leaq -0x80(%rbp), %rdi
leaq -0x160(%rbp), %rsi
callq 0x27870
movb %al, -0x1d9(%rbp)
jmp 0x28640
movb -0x1d9(%rbp), %al
testb $0x1, %al
jne 0x2864c
jmp 0x2864e
jmp 0x28684
leaq 0x2394b(%rip), %rdi     # 0x4bfa0
leaq 0x235f3(%rip), %rsi     # 0x4bc4f
movl $0x197, %edx            # imm = 0x197
leaq 0x238a3(%rip), %rcx     # 0x4bf0b
callq 0x4240
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x288ab
movl -0x24(%rbp), %esi
movl -0x30(%rbp), %edx
leaq -0x1a0(%rbp), %rdi
callq 0x15710
jmp 0x28698
leaq -0x118(%rbp), %rdi
leaq -0x1a0(%rbp), %rsi
callq 0x27870
movb %al, -0x1da(%rbp)
jmp 0x286b3
movb -0x1da(%rbp), %al
testb $0x1, %al
jne 0x286bf
jmp 0x286c1
jmp 0x28703
leaq 0x238fc(%rip), %rdi     # 0x4bfc4
leaq 0x23580(%rip), %rsi     # 0x4bc4f
movl $0x199, %edx            # imm = 0x199
leaq 0x23830(%rip), %rcx     # 0x4bf0b
callq 0x4240
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x157e0
jmp 0x288ab
movq -0x20(%rbp), %rdi
movl -0x24(%rbp), %esi
movl -0x30(%rbp), %edx
movq (%rdi), %rax
movq 0x28(%rax), %rax
callq *%rax
jmp 0x28718
leaq -0x160(%rbp), %rdi
callq 0xf2c0
movq %rax, -0x1e8(%rbp)
jmp 0x2872d
leaq -0x1a0(%rbp), %rdi
callq 0xf2c0
movq %rax, -0x1f0(%rbp)
jmp 0x28742
movq -0x20(%rbp), %rdi
callq 0xf2c0
movq %rax, -0x1f8(%rbp)
jmp 0x28754
movq -0x1f8(%rbp), %rdx
movq -0x1f0(%rbp), %rsi
movq -0x1e8(%rbp), %rdi
movslq -0x30(%rbp), %rcx
movslq -0x24(%rbp), %r8
callq 0x3a280
jmp 0x28778
movl -0x30(%rbp), %edi
callq 0x29350
movsd %xmm0, -0x200(%rbp)
jmp 0x2878a
movsd -0x200(%rbp), %xmm0
cvttsd2si %xmm0, %rax
movq %rax, -0x210(%rbp)
movl -0x24(%rbp), %edi
callq 0x29350
movsd %xmm0, -0x208(%rbp)
jmp 0x287b0
movq -0x210(%rbp), %rdi
movsd -0x208(%rbp), %xmm0
cvttsd2si %xmm0, %rsi
callq 0x384c0
movl %eax, -0x214(%rbp)
jmp 0x287d1
movl -0x214(%rbp), %eax
movl %eax, -0x1a4(%rbp)
cmpl $0x0, -0x1a4(%rbp)
je 0x287f6
movb $0x0, -0x1(%rbp)
movl $0x1, -0x1a8(%rbp)
jmp 0x28870
movq -0x20(%rbp), %rdi
callq 0xf2c0
movq %rax, -0x220(%rbp)
jmp 0x28808
movl -0x30(%rbp), %edi
callq 0x29350
movsd %xmm0, -0x228(%rbp)
jmp 0x2881a
movsd -0x228(%rbp), %xmm0
cvttsd2si %xmm0, %rax
movq %rax, -0x238(%rbp)
movl -0x24(%rbp), %edi
callq 0x29350
movsd %xmm0, -0x230(%rbp)
jmp 0x28840
movq -0x238(%rbp), %rsi
movq -0x220(%rbp), %rdi
movsd -0x230(%rbp), %xmm0
cvttsd2si %xmm0, %rdx
callq 0x39be0
jmp 0x28862
movb $0x1, -0x1(%rbp)
movl $0x1, -0x1a8(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x157e0
leaq -0x160(%rbp), %rdi
callq 0x157e0
leaq -0x118(%rbp), %rdi
callq 0x157e0
leaq -0xd8(%rbp), %rdi
callq 0x157e0
leaq -0x80(%rbp), %rdi
callq 0x157e0
jmp 0x288da
leaq -0x160(%rbp), %rdi
callq 0x157e0
leaq -0x118(%rbp), %rdi
callq 0x157e0
leaq -0xd8(%rbp), %rdi
callq 0x157e0
leaq -0x80(%rbp), %rdi
callq 0x157e0
jmp 0x288e8
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x240, %rsp            # imm = 0x240
popq %rbp
retq
movq -0x90(%rbp), %rdi
callq 0x4620
nopw %cs:(%rax,%rax)