// File: kebwi[P]Trifid/src/SteerablePyramid.cpp
// Function: SteerablePyramid::findCorrelations(SteerablePyramid const&, std::vector<double, std::allocator<double>>&) const
void SteerablePyramid::findCorrelations(const SteerablePyramid &sp, vector<Float_t> &lvlCorrs) const
{
	assert(width_ == sp.width_ && height_ == sp.height_ && numLevels_ == sp.numLevels_);
	
	lvlCorrs.resize(numLevels_);
	for (int level = 0; level < numLevels_; level++)
	{
		int totalPixels = (width_ * height_) / (int)(pow(4, level));
		int totalCoeffs = totalPixels * ((level == 0) ? 5 : 4);
		
		lvlCorrs[level] = 0;
		
		//This algorithm is from http://en.wikipedia.org/wiki/Correlation
		Float_t sum_sq_x = 0;
		Float_t sum_sq_y = 0;
		Float_t sum_coproduct = 0;
		Float_t mean_x = b1Coeffs_[level][0];
		Float_t mean_y = sp.b1Coeffs_[level][0];
		Float_t sweep, delta_x, delta_y;
		for (int i = 1; i < totalCoeffs; i++)
		{
			sweep = (i - 1.0) / i;
			
			if (i / totalPixels == 0)
			{
				delta_x = b1Coeffs_[level][i % totalPixels] - mean_x;
				delta_y = sp.b1Coeffs_[level][i % totalPixels] - mean_y;
			}
			else if (i / totalPixels == 1)
			{
				delta_x = b2Coeffs_[level][i % totalPixels] - mean_x;
				delta_y = sp.b2Coeffs_[level][i % totalPixels] - mean_y;
			}
			else if (i / totalPixels == 2)
			{
				delta_x = b3Coeffs_[level][i % totalPixels] - mean_x;
				delta_y = sp.b3Coeffs_[level][i % totalPixels] - mean_y;
			}
			else if (i / totalPixels == 3)
			{
				delta_x = b4Coeffs_[level][i % totalPixels] - mean_x;
				delta_y = sp.b4Coeffs_[level][i % totalPixels] - mean_y;
			}
			else if (i / totalPixels == 4)
			{
				delta_x = h0Coeffs_[i % totalPixels] - mean_x;
				delta_y = sp.h0Coeffs_[i % totalPixels] - mean_y;
			}
			else assert(false);
			
			sum_sq_x += delta_x * delta_x * sweep;
			sum_sq_y += delta_y * delta_y * sweep;
			sum_coproduct += delta_x * delta_y * sweep;
			mean_x += delta_x / i;
			mean_y += delta_y / i;
		}
		Float_t pop_sd_x = sqrt(sum_sq_x / totalPixels);
		Float_t pop_sd_y = sqrt(sum_sq_y / totalPixels);
		Float_t cov_x_y = sum_coproduct / totalPixels;
		Float_t denom = pop_sd_x * pop_sd_y;
		Float_t correlation = 1;
		if (denom != 0)
			correlation = cov_x_y / denom;
		else assert(cov_x_y == 0);	//So long as both numerator and denominator are 0, call the correlation 0/0, or 1...sorta kinda.
		
		if (isnan(correlation) || isinf(correlation) || correlation < -1 || correlation > 1)
			cout << "Correlation: " << correlation << endl;
		assert(!isnan(correlation));
		assert(!isinf(correlation));
		assert(correlation >= -1 && correlation <= 1);
		
		lvlCorrs[level] = correlation;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xa8(%rbp)
movl 0x30(%rax), %ecx
movq -0x10(%rbp), %rdx
xorl %eax, %eax
cmpl 0x30(%rdx), %ecx
movb %al, -0x99(%rbp)
jne 0x2f34b
movq -0xa8(%rbp), %rax
movl 0x34(%rax), %ecx
movq -0x10(%rbp), %rdx
xorl %eax, %eax
cmpl 0x34(%rdx), %ecx
movb %al, -0x99(%rbp)
jne 0x2f34b
movq -0xa8(%rbp), %rax
movl 0x38(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x38(%rcx), %eax
sete %al
movb %al, -0x99(%rbp)
movb -0x99(%rbp), %al
testb $0x1, %al
jne 0x2f357
jmp 0x2f359
jmp 0x2f378
leaq 0x1df3e(%rip), %rdi     # 0x4d29e
leaq 0x1cfef(%rip), %rsi     # 0x4c356
movl $0x672, %edx            # imm = 0x672
leaq 0x1df77(%rip), %rcx     # 0x4d2ea
callq 0x4240
movq -0xa8(%rbp), %rax
movq -0x18(%rbp), %rdi
movslq 0x38(%rax), %rsi
callq 0xe5e0
movl $0x0, -0x1c(%rbp)
movq -0xa8(%rbp), %rcx
movl -0x1c(%rbp), %eax
cmpl 0x38(%rcx), %eax
jge 0x2fa16
movq -0xa8(%rbp), %rcx
movl 0x30(%rcx), %eax
imull 0x34(%rcx), %eax
movl %eax, -0xac(%rbp)
movl -0x1c(%rbp), %esi
movl $0x4, %edi
callq 0x1d7f0
movl -0xac(%rbp), %eax
cvttsd2si %xmm0, %ecx
cltd
idivl %ecx
movl %eax, -0x20(%rbp)
movl -0x20(%rbp), %eax
movl -0x1c(%rbp), %esi
movl $0x4, %ecx
movl $0x5, %edx
cmpl $0x0, %esi
cmovel %edx, %ecx
imull %ecx, %eax
movl %eax, -0x24(%rbp)
movq -0x18(%rbp), %rdi
movslq -0x1c(%rbp), %rsi
callq 0xe670
movq %rax, %rcx
movq -0xa8(%rbp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, (%rcx)
xorps %xmm0, %xmm0
movsd %xmm0, -0x30(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x38(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x40(%rbp)
movq 0x8(%rax), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x48(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x50(%rbp)
movl $0x1, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x2f7c6
cvtsi2sdl -0x6c(%rbp), %xmm0
movsd 0x19ba9(%rip), %xmm1    # 0x49020
subsd %xmm1, %xmm0
cvtsi2sdl -0x6c(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x58(%rbp)
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
cmpl $0x0, %eax
jne 0x2f50b
movq -0xa8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xc0(%rbp)
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
movq -0xc0(%rbp), %rax
movslq %edx, %rcx
movsd (%rax,%rcx,8), %xmm0
subsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x60(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xb8(%rbp)
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
movq -0xb8(%rbp), %rax
movslq %edx, %rcx
movsd (%rax,%rcx,8), %xmm0
subsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x68(%rbp)
jmp 0x2f725
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
cmpl $0x1, %eax
jne 0x2f58d
movq -0xa8(%rbp), %rax
movq 0x10(%rax), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xd0(%rbp)
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
movq -0xd0(%rbp), %rax
movslq %edx, %rcx
movsd (%rax,%rcx,8), %xmm0
subsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x60(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xc8(%rbp)
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
movq -0xc8(%rbp), %rax
movslq %edx, %rcx
movsd (%rax,%rcx,8), %xmm0
subsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x68(%rbp)
jmp 0x2f723
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
cmpl $0x2, %eax
jne 0x2f60f
movq -0xa8(%rbp), %rax
movq 0x18(%rax), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xe0(%rbp)
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
movq -0xe0(%rbp), %rax
movslq %edx, %rcx
movsd (%rax,%rcx,8), %xmm0
subsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x60(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xd8(%rbp)
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
movq -0xd8(%rbp), %rax
movslq %edx, %rcx
movsd (%rax,%rcx,8), %xmm0
subsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x68(%rbp)
jmp 0x2f721
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
cmpl $0x3, %eax
jne 0x2f691
movq -0xa8(%rbp), %rax
movq 0x20(%rax), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xf0(%rbp)
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
movq -0xf0(%rbp), %rax
movslq %edx, %rcx
movsd (%rax,%rcx,8), %xmm0
subsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x60(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movslq -0x1c(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xe8(%rbp)
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
movq -0xe8(%rbp), %rax
movslq %edx, %rcx
movsd (%rax,%rcx,8), %xmm0
subsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x68(%rbp)
jmp 0x2f71f
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
cmpl $0x4, %eax
jne 0x2f6fe
movq -0xa8(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x100(%rbp)
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
movq -0x100(%rbp), %rax
movslq %edx, %rcx
movsd (%rax,%rcx,8), %xmm0
subsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x60(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xf8(%rbp)
movl -0x6c(%rbp), %eax
cltd
idivl -0x20(%rbp)
movq -0xf8(%rbp), %rax
movslq %edx, %rcx
movsd (%rax,%rcx,8), %xmm0
subsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x68(%rbp)
jmp 0x2f71d
leaq 0x1c5bf(%rip), %rdi     # 0x4bcc4
leaq 0x1cc4a(%rip), %rsi     # 0x4c356
movl $0x6a0, %edx            # imm = 0x6A0
leaq 0x1dbd2(%rip), %rcx     # 0x4d2ea
callq 0x4240
jmp 0x2f71f
jmp 0x2f721
jmp 0x2f723
jmp 0x2f725
movsd -0x60(%rbp), %xmm0
mulsd -0x60(%rbp), %xmm0
movsd -0x58(%rbp), %xmm2
movsd -0x30(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x30(%rbp)
movsd -0x68(%rbp), %xmm0
mulsd -0x68(%rbp), %xmm0
movsd -0x58(%rbp), %xmm2
movsd -0x38(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x38(%rbp)
movsd -0x60(%rbp), %xmm0
mulsd -0x68(%rbp), %xmm0
movsd -0x58(%rbp), %xmm2
movsd -0x40(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x40(%rbp)
movsd -0x60(%rbp), %xmm0
cvtsi2sdl -0x6c(%rbp), %xmm1
divsd %xmm1, %xmm0
addsd -0x48(%rbp), %xmm0
movsd %xmm0, -0x48(%rbp)
movsd -0x68(%rbp), %xmm0
cvtsi2sdl -0x6c(%rbp), %xmm1
divsd %xmm1, %xmm0
addsd -0x50(%rbp), %xmm0
movsd %xmm0, -0x50(%rbp)
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x2f45e
movsd -0x30(%rbp), %xmm0
cvtsi2sdl -0x20(%rbp), %xmm1
divsd %xmm1, %xmm0
callq 0x42c0
movsd %xmm0, -0x78(%rbp)
movsd -0x38(%rbp), %xmm0
cvtsi2sdl -0x20(%rbp), %xmm1
divsd %xmm1, %xmm0
callq 0x42c0
movsd %xmm0, -0x80(%rbp)
movsd -0x40(%rbp), %xmm0
cvtsi2sdl -0x20(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0x88(%rbp)
movsd -0x78(%rbp), %xmm0
mulsd -0x80(%rbp), %xmm0
movsd %xmm0, -0x90(%rbp)
movsd 0x197fa(%rip), %xmm0    # 0x49020
movsd %xmm0, -0x98(%rbp)
movsd -0x90(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x2f843
jp 0x2f843
jmp 0x2f85d
movsd -0x88(%rbp), %xmm0
divsd -0x90(%rbp), %xmm0
movsd %xmm0, -0x98(%rbp)
jmp 0x2f893
movsd -0x88(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x2f872
jp 0x2f872
jmp 0x2f891
leaq 0x1dacc(%rip), %rdi     # 0x4d345
leaq 0x1cad6(%rip), %rsi     # 0x4c356
movl $0x6af, %edx            # imm = 0x6AF
leaq 0x1da5e(%rip), %rcx     # 0x4d2ea
callq 0x4240
jmp 0x2f893
movsd -0x98(%rbp), %xmm0
callq 0x29330
testb $0x1, %al
jne 0x2f8dd
movsd -0x98(%rbp), %xmm0
callq 0x32f80
testb $0x1, %al
jne 0x2f8dd
movsd 0x1977b(%rip), %xmm0    # 0x49038
ucomisd -0x98(%rbp), %xmm0
ja 0x2f8dd
movsd -0x98(%rbp), %xmm0
movsd 0x19749(%rip), %xmm1    # 0x49020
ucomisd %xmm1, %xmm0
jbe 0x2f90f
movq 0x2a6ec(%rip), %rdi     # 0x59fd0
leaq 0x1da67(%rip), %rsi     # 0x4d352
callq 0x4390
movq %rax, %rdi
movsd -0x98(%rbp), %xmm0
callq 0x4670
movq %rax, %rdi
movq 0x2a6ae(%rip), %rsi     # 0x59fb8
callq 0x43d0
movsd -0x98(%rbp), %xmm0
callq 0x29330
xorb $-0x1, %al
testb $0x1, %al
jne 0x2f924
jmp 0x2f926
jmp 0x2f945
leaq 0x1da33(%rip), %rdi     # 0x4d360
leaq 0x1ca22(%rip), %rsi     # 0x4c356
movl $0x6b3, %edx            # imm = 0x6B3
leaq 0x1d9aa(%rip), %rcx     # 0x4d2ea
callq 0x4240
movsd -0x98(%rbp), %xmm0
callq 0x32f80
xorb $-0x1, %al
testb $0x1, %al
jne 0x2f95a
jmp 0x2f95c
jmp 0x2f97b
leaq 0x1da11(%rip), %rdi     # 0x4d374
leaq 0x1c9ec(%rip), %rsi     # 0x4c356
movl $0x6b4, %edx            # imm = 0x6B4
leaq 0x1d974(%rip), %rcx     # 0x4d2ea
callq 0x4240
movsd -0x98(%rbp), %xmm0
xorl %eax, %eax
movsd 0x196ab(%rip), %xmm1    # 0x49038
ucomisd %xmm1, %xmm0
movb %al, -0x101(%rbp)
jb 0x2f9b2
movsd 0x1967f(%rip), %xmm0    # 0x49020
ucomisd -0x98(%rbp), %xmm0
setae %al
movb %al, -0x101(%rbp)
movb -0x101(%rbp), %al
testb $0x1, %al
jne 0x2f9be
jmp 0x2f9c0
jmp 0x2f9df
leaq 0x1d9c1(%rip), %rdi     # 0x4d388
leaq 0x1c988(%rip), %rsi     # 0x4c356
movl $0x6b5, %edx            # imm = 0x6B5
leaq 0x1d910(%rip), %rcx     # 0x4d2ea
callq 0x4240
movsd -0x98(%rbp), %xmm0
movsd %xmm0, -0x110(%rbp)
movq -0x18(%rbp), %rdi
movslq -0x1c(%rbp), %rsi
callq 0xe670
movsd -0x110(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x2f393
addq $0x110, %rsp            # imm = 0x110
popq %rbp
retq
nop