// File: xbai0624[P]dnn/src/Matrix.cpp
// Function: Matrix::Correlation(Matrix&, unsigned long, bool, double)
Matrix Matrix::Correlation(Matrix &T, size_t stride, bool pad_front, double padding_value)
{
    // matrix correlation
    auto l_dim = Dimension();
    auto r_dim = T.Dimension();

    if(l_dim.first < r_dim.first || l_dim.second < r_dim.second) {
        std::cout<<"Error: matrix correlation dimension not match."<<std::endl;
        exit(0);
    }

    Matrix M = (*this); // left operand
    size_t row, col;
    row = (l_dim.first - r_dim.first + 1) / stride;
    col = (l_dim.second - r_dim.second + 1) / stride;

    if(stride > 1) { // check if padding needed
        row += 1; col+=1;
        size_t extra_row = row*stride - l_dim.first;
        size_t extra_col = col*stride - l_dim.second;

        if( extra_row > 0  || extra_col > 0) {
            M = (*this).Padding(l_dim.first + extra_row, l_dim.second+extra_col, pad_front, padding_value);
        }
    }

    l_dim = M.Dimension();

    Matrix res(row, col);
    for(size_t i=0;i<row;i++){
        for(size_t j=0;j<col;j++){
            Matrix l = M.GetSection(i*stride, i*stride + r_dim.first, j*stride, j*stride + r_dim.second);
            Matrix _t = l^T;
            auto __D = _t.Dimension();
            res[i][j] = _t.SumInSection(0, __D.first, 0, __D.second);
        }
    }
    return res;
}

// Assembly:
subq $0x168, %rsp            # imm = 0x168
movq %rdi, 0x38(%rsp)
movb %r8b, %al
movq %rdi, %r8
movq %r8, 0x40(%rsp)
movq %rdi, 0x160(%rsp)
movq %rsi, 0x158(%rsp)
movq %rdx, 0x150(%rsp)
movq %rcx, 0x148(%rsp)
andb $0x1, %al
movb %al, 0x147(%rsp)
movsd %xmm0, 0x138(%rsp)
movq 0x158(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x3bae0
movq %rax, 0x128(%rsp)
movq %rdx, 0x130(%rsp)
movq 0x150(%rsp), %rdi
callq 0x3bae0
movq %rax, 0x118(%rsp)
movq %rdx, 0x120(%rsp)
movq 0x128(%rsp), %rax
cmpq 0x118(%rsp), %rax
jb 0x4118c
movq 0x130(%rsp), %rax
cmpq 0x120(%rsp), %rax
jae 0x411b5
movq 0x29e45(%rip), %rdi     # 0x6afd8
leaq 0x14469(%rip), %rsi     # 0x55603
callq 0x4230
movq %rax, %rdi
movq 0x29e07(%rip), %rsi     # 0x6afb0
callq 0x4260
xorl %edi, %edi
callq 0x4290
movq 0x48(%rsp), %rsi
leaq 0x100(%rsp), %rdi
callq 0x3b810
movq 0x128(%rsp), %rax
subq 0x118(%rsp), %rax
addq $0x1, %rax
xorl %ecx, %ecx
movl %ecx, %edx
divq 0x148(%rsp)
movq %rax, 0xf8(%rsp)
movq 0x130(%rsp), %rax
subq 0x120(%rsp), %rax
addq $0x1, %rax
xorl %ecx, %ecx
movl %ecx, %edx
divq 0x148(%rsp)
movq %rax, 0xf0(%rsp)
cmpq $0x1, 0x148(%rsp)
jbe 0x41361
movq 0xf8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xf8(%rsp)
movq 0xf0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xf0(%rsp)
movq 0xf8(%rsp), %rax
imulq 0x148(%rsp), %rax
subq 0x128(%rsp), %rax
movq %rax, 0xe8(%rsp)
movq 0xf0(%rsp), %rax
imulq 0x148(%rsp), %rax
subq 0x130(%rsp), %rax
movq %rax, 0xe0(%rsp)
cmpq $0x0, 0xe8(%rsp)
ja 0x412aa
cmpq $0x0, 0xe0(%rsp)
jbe 0x4135f
movq 0x48(%rsp), %rsi
movq 0xe8(%rsp), %rax
movq 0x128(%rsp), %rdx
movq 0x130(%rsp), %rcx
addq %rax, %rdx
movq 0xe0(%rsp), %rax
addq %rax, %rcx
movsd 0x138(%rsp), %xmm0
movzbl 0x147(%rsp), %r8d
andl $0x1, %r8d
leaq 0xc8(%rsp), %rdi
callq 0x3f100
jmp 0x412fa
leaq 0x100(%rsp), %rdi
leaq 0xc8(%rsp), %rsi
callq 0x1fa20
jmp 0x41311
leaq 0xc8(%rsp), %rdi
callq 0x3bb80
jmp 0x4135f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc0(%rsp)
movl %eax, 0xbc(%rsp)
jmp 0x415e0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc0(%rsp)
movl %eax, 0xbc(%rsp)
leaq 0xc8(%rsp), %rdi
callq 0x3bb80
jmp 0x415e0
jmp 0x41361
leaq 0x100(%rsp), %rdi
callq 0x3bae0
movq %rdx, 0x28(%rsp)
movq %rax, 0x30(%rsp)
jmp 0x4137a
movq 0x28(%rsp), %rax
movq 0x30(%rsp), %rcx
movq %rcx, 0xa8(%rsp)
movq %rax, 0xb0(%rsp)
leaq 0x128(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x42910
movq 0x38(%rsp), %rdi
movb $0x0, 0xa7(%rsp)
movq 0xf8(%rsp), %rsi
movq 0xf0(%rsp), %rdx
callq 0x3b3b0
jmp 0x413cd
movq $0x0, 0x98(%rsp)
movq 0x98(%rsp), %rax
cmpq 0xf8(%rsp), %rax
jae 0x415a0
movq $0x0, 0x90(%rsp)
movq 0x90(%rsp), %rax
cmpq 0xf0(%rsp), %rax
jae 0x41585
movq 0x98(%rsp), %rdx
movq 0x148(%rsp), %rsi
imulq %rsi, %rdx
movq 0x118(%rsp), %rdi
movq 0x120(%rsp), %rax
movq %rdx, %rcx
addq %rdi, %rcx
movq 0x90(%rsp), %r8
imulq %rsi, %r8
movq %r8, %r9
addq %rax, %r9
movq %rsp, %rax
movl $0x0, (%rax)
leaq 0x78(%rsp), %rdi
leaq 0x100(%rsp), %rsi
xorps %xmm0, %xmm0
callq 0x3ee40
jmp 0x4146d
movq 0x150(%rsp), %rdx
leaq 0x60(%rsp), %rdi
leaq 0x78(%rsp), %rsi
callq 0x3c680
jmp 0x41486
leaq 0x60(%rsp), %rdi
callq 0x3bae0
movq %rdx, 0x18(%rsp)
movq %rax, 0x20(%rsp)
jmp 0x4149c
movq 0x18(%rsp), %rax
movq 0x20(%rsp), %rcx
movq %rcx, 0x50(%rsp)
movq %rax, 0x58(%rsp)
movq 0x50(%rsp), %rdx
movq 0x58(%rsp), %r8
xorl %eax, %eax
movl %eax, %ecx
leaq 0x60(%rsp), %rdi
movq %rcx, %rsi
callq 0x407f0
movsd %xmm0, 0x10(%rsp)
jmp 0x414d3
movq 0x38(%rsp), %rdi
movq 0x98(%rsp), %rsi
callq 0x3be50
movq %rax, %rdi
movq 0x90(%rsp), %rsi
callq 0x1fd60
movsd 0x10(%rsp), %xmm0
movsd %xmm0, (%rax)
leaq 0x60(%rsp), %rdi
callq 0x3bb80
leaq 0x78(%rsp), %rdi
callq 0x3bb80
movq 0x90(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x90(%rsp)
jmp 0x413fb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc0(%rsp)
movl %eax, 0xbc(%rsp)
jmp 0x415d6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc0(%rsp)
movl %eax, 0xbc(%rsp)
jmp 0x41579
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc0(%rsp)
movl %eax, 0xbc(%rsp)
leaq 0x60(%rsp), %rdi
callq 0x3bb80
leaq 0x78(%rsp), %rdi
callq 0x3bb80
jmp 0x415d6
jmp 0x41587
movq 0x98(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x98(%rsp)
jmp 0x413d9
movb $0x1, 0xa7(%rsp)
testb $0x1, 0xa7(%rsp)
jne 0x415bc
movq 0x38(%rsp), %rdi
callq 0x3bb80
leaq 0x100(%rsp), %rdi
callq 0x3bb80
movq 0x40(%rsp), %rax
addq $0x168, %rsp            # imm = 0x168
retq
movq 0x38(%rsp), %rdi
callq 0x3bb80
leaq 0x100(%rsp), %rdi
callq 0x3bb80
movq 0xc0(%rsp), %rdi
callq 0x43f0
nopw (%rax,%rax)