// File: /workspace/github_cpp_makefile_star2_O3/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x168, %rsp            # imm = 0x168
movq %rdx, %rbx
movq %rsi, %r15
movq %rdi, %r12
movl 0x28(%rdi), %eax
movl 0x2c(%rdi), %ecx
movl 0x28(%rsi), %ebp
cmpl %ebp, %eax
cmovgl %eax, %ebp
movl 0x2c(%rsi), %r14d
cmpl %r14d, %ecx
cmovgl %ecx, %r14d
movl %ebp, %edi
movl %r14d, %esi
callq 0x18d74
testb %al, %al
je 0x1a06a
leaq 0x128(%rsp), %r13
movq %r13, %rdi
callq 0xcf0c
leaq 0x1c(%rsp), %r8
leaq 0x18(%rsp), %r9
movq %r12, %rdi
movl %ebp, %esi
movl %r14d, %edx
movq %r13, %rcx
callq 0x19814
testb %al, %al
je 0x1a080
leaq 0x68(%rsp), %rdi
callq 0xcf0c
leaq 0x68(%rsp), %rcx
leaq 0x1c(%rsp), %r8
leaq 0x18(%rsp), %r9
movq %r15, %rdi
movl %ebp, %esi
movl %r14d, %edx
callq 0x19814
testb %al, %al
je 0x1a09f
movq %rbx, 0x20(%rsp)
leaq 0x28(%rsp), %rdi
movl %ebp, %esi
movl %r14d, %edx
callq 0xcfba
testl %r14d, %r14d
jle 0x19f32
movl %ebp, %edi
shrl $0x1f, %edi
addl %ebp, %edi
sarl %edi
movl %r14d, %r8d
shrl $0x1f, %r8d
addl %r14d, %r8d
sarl %r8d
movq 0xa0(%rsp), %r9
movl 0x90(%rsp), %eax
movl %eax, 0x10(%rsp)
movq 0x60(%rsp), %r11
movl 0x50(%rsp), %r15d
movl %ebp, %eax
movq %rax, 0x8(%rsp)
xorl %r10d, %r10d
xorl %ebx, %ebx
testl %ebp, %ebp
jle 0x19f28
leal (%rbx,%r8), %eax
xorl %edx, %edx
divl %r14d
movl %edx, %ecx
imull 0x10(%rsp), %ecx
movq 0x8(%rsp), %r12
movl %r10d, %r13d
movl %edi, %esi
movl %esi, %eax
xorl %edx, %edx
divl %ebp
addl %ecx, %edx
movsd (%r9,%rdx,8), %xmm0
movl %r13d, %eax
movsd %xmm0, (%r11,%rax,8)
incl %esi
incl %r13d
decq %r12
jne 0x19f07
incl %ebx
addl %r15d, %r10d
cmpl %r14d, %ebx
jne 0x19ee9
leaq 0xe8(%rsp), %rdi
movl %ebp, %esi
movl %r14d, %edx
callq 0xcfba
leaq 0x128(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x195c0
movq 0x20(%rsp), %rbx
testb %al, %al
je 0x1a0be
leaq 0xa8(%rsp), %rdi
movl %ebp, %esi
movl %r14d, %edx
callq 0xcfba
leaq 0x28(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x195c0
testb %al, %al
je 0x1a0dd
movq (%rbx), %rax
movq %rbx, %rdi
movl %ebp, %esi
movl %r14d, %edx
callq *0x28(%rax)
movq 0x120(%rsp), %rdi
movq 0xe0(%rsp), %rsi
movq 0x38(%rbx), %rdx
movslq %r14d, %rcx
movslq %ebp, %r8
callq 0x24487
xorps %xmm0, %xmm0
cvtsi2sd %r14d, %xmm0
movsd %xmm0, 0x10(%rsp)
callq 0x3510
cvttsd2si %xmm0, %r14
xorps %xmm0, %xmm0
cvtsi2sd %ebp, %xmm0
movsd %xmm0, 0x8(%rsp)
callq 0x3510
cvttsd2si %xmm0, %rsi
movq %r14, %rdi
callq 0x233f4
testl %eax, %eax
sete %bpl
jne 0x1a02d
movq 0x38(%rbx), %rbx
movsd 0x10(%rsp), %xmm0
callq 0x3510
cvttsd2si %xmm0, %r14
movsd 0x8(%rsp), %xmm0
callq 0x3510
cvttsd2si %xmm0, %rdx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x24141
leaq 0xa8(%rsp), %rdi
callq 0xd038
leaq 0xe8(%rsp), %rdi
callq 0xd038
leaq 0x28(%rsp), %rdi
callq 0xd038
leaq 0x68(%rsp), %rdi
callq 0xd038
leaq 0x128(%rsp), %rdi
callq 0xd038
jmp 0x1a06c
xorl %ebp, %ebp
movl %ebp, %eax
addq $0x168, %rsp            # imm = 0x168
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x12dcc(%rip), %rdi     # 0x2ce53
leaq 0x12b5d(%rip), %rsi     # 0x2cbeb
leaq 0x12e0c(%rip), %rcx     # 0x2cea1
movl $0x18a, %edx            # imm = 0x18A
callq 0x31c0
leaq 0x12e42(%rip), %rdi     # 0x2cee8
leaq 0x12b3e(%rip), %rsi     # 0x2cbeb
leaq 0x12ded(%rip), %rcx     # 0x2cea1
movl $0x18c, %edx            # imm = 0x18C
callq 0x31c0
leaq 0x12e71(%rip), %rdi     # 0x2cf36
leaq 0x12b1f(%rip), %rsi     # 0x2cbeb
leaq 0x12dce(%rip), %rcx     # 0x2cea1
movl $0x197, %edx            # imm = 0x197
callq 0x31c0
leaq 0x12e76(%rip), %rdi     # 0x2cf5a
leaq 0x12b00(%rip), %rsi     # 0x2cbeb
leaq 0x12daf(%rip), %rcx     # 0x2cea1
movl $0x199, %edx            # imm = 0x199
callq 0x31c0
jmp 0x1a0fe
movq %rax, %rbx
jmp 0x1a128
movq %rax, %rbx
jmp 0x1a135
jmp 0x1a10a
movq %rax, %rbx
jmp 0x1a13f
jmp 0x1a111
movq %rax, %rbx
jmp 0x1a149
jmp 0x1a118
movq %rax, %rbx
leaq 0xa8(%rsp), %rdi
callq 0xd038
leaq 0xe8(%rsp), %rdi
callq 0xd038
leaq 0x28(%rsp), %rdi
callq 0xd038
leaq 0x68(%rsp), %rdi
callq 0xd038
leaq 0x128(%rsp), %rdi
callq 0xd038
movq %rbx, %rdi
callq 0x3500