// File: xbai0624[P]dnn/src/Neuron.cpp
// Function: Neuron::UpdateZCNN(int)
void Neuron::UpdateZCNN(int sample_index)
{
    // cnn layer
    // every single output image needs input from all input images
    Layer *__previousLayer = __layer->GetPrevLayer();
    auto & inputImage = __previousLayer->GetImagesActiveA(); // no tensorization needed; b/c "fc->cnn" type connection is not used at the moment

    auto w_dim = __w->Dimension();
    int stride = __layer->GetCNNStride();

    size_t i_start = __coord.i*stride;
    size_t j_start = __coord.j*stride;
    size_t i_end = i_start + w_dim.first;
    size_t j_end = j_start + w_dim.second;

    //auto &current_sample_image = (inputImage.back()).OutputImageFromKernel;
    auto &current_sample_image = (inputImage[sample_index]).OutputImageFromKernel;
    auto image_dim = current_sample_image[0].Dimension();
    if(i_end > image_dim.first || j_end > image_dim.second)
    {
        std::cout<<"Error: cnn z update: matrix dimension not match, probably due to wrong padding."<<std::endl;
        exit(0);
    }

    // compute z
    double res = 0;
    for(auto &m: current_sample_image)
    {
        for(size_t i=0;i<w_dim.first;i++){
            for(size_t j=0;j<w_dim.second;j++){
                res += m[i+i_start][j+j_start] * (*__w)[i][j];
            }
        }
    }
    double z = res + (*__b)[0][0];
    __z[sample_index] = z;
}

// Assembly:
subq $0xd8, %rsp
movq %rdi, 0xd0(%rsp)
movl %esi, 0xcc(%rsp)
movq 0xd0(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x78(%rax), %rdi
movq (%rdi), %rax
callq *0x2c8(%rax)
movq %rax, 0xc0(%rsp)
movq 0xc0(%rsp), %rdi
movq (%rdi), %rax
callq *0xc8(%rax)
movq %rax, %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0xb8(%rsp)
movq 0x8(%rax), %rdi
callq 0x3bae0
movq %rax, %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0xa8(%rsp)
movq %rdx, 0xb0(%rsp)
movq 0x78(%rax), %rdi
movq (%rdi), %rax
callq *0x218(%rax)
movl %eax, %ecx
movq 0x20(%rsp), %rax
movl %ecx, 0xa4(%rsp)
movq 0x88(%rax), %rcx
movslq 0xa4(%rsp), %rdx
imulq %rdx, %rcx
movq %rcx, 0x98(%rsp)
movq 0x90(%rax), %rax
movslq 0xa4(%rsp), %rcx
imulq %rcx, %rax
movq %rax, 0x90(%rsp)
movq 0x98(%rsp), %rax
addq 0xa8(%rsp), %rax
movq %rax, 0x88(%rsp)
movq 0x90(%rsp), %rax
addq 0xb0(%rsp), %rax
movq %rax, 0x80(%rsp)
movq 0xb8(%rsp), %rdi
movslq 0xcc(%rsp), %rsi
callq 0x1fd40
movq %rax, 0x78(%rsp)
movq 0x78(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1f9e0
movq %rax, %rdi
callq 0x3bae0
movq %rax, 0x68(%rsp)
movq %rdx, 0x70(%rsp)
movq 0x88(%rsp), %rax
cmpq 0x68(%rsp), %rax
ja 0x48603
movq 0x80(%rsp), %rax
cmpq 0x70(%rsp), %rax
jbe 0x4862c
movq 0x229ce(%rip), %rdi     # 0x6afd8
leaq 0xd518(%rip), %rsi      # 0x55b29
callq 0x4230
movq %rax, %rdi
movq 0x22990(%rip), %rsi     # 0x6afb0
callq 0x4260
xorl %edi, %edi
callq 0x4290
xorps %xmm0, %xmm0
movsd %xmm0, 0x60(%rsp)
movq 0x78(%rsp), %rax
movq %rax, 0x58(%rsp)
movq 0x58(%rsp), %rdi
callq 0x1fe00
movq %rax, 0x50(%rsp)
movq 0x58(%rsp), %rdi
callq 0x1fe30
movq %rax, 0x48(%rsp)
leaq 0x50(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x1fe60
testb $0x1, %al
jne 0x48675
jmp 0x4876c
leaq 0x50(%rsp), %rdi
callq 0x1fea0
movq %rax, 0x40(%rsp)
movq $0x0, 0x38(%rsp)
movq 0x38(%rsp), %rax
cmpq 0xa8(%rsp), %rax
jae 0x4875b
movq $0x0, 0x30(%rsp)
movq 0x30(%rsp), %rax
cmpq 0xb0(%rsp), %rax
jae 0x48746
movq 0x40(%rsp), %rdi
movq 0x38(%rsp), %rsi
addq 0x98(%rsp), %rsi
callq 0x3be50
movq %rax, %rdi
movq 0x30(%rsp), %rsi
addq 0x90(%rsp), %rsi
callq 0x1fd60
movq %rax, %rcx
movq 0x20(%rsp), %rax
movsd (%rcx), %xmm0
movsd %xmm0, 0x18(%rsp)
movq 0x8(%rax), %rdi
movq 0x38(%rsp), %rsi
callq 0x3be50
movq %rax, %rdi
movq 0x30(%rsp), %rsi
callq 0x1fd60
movsd 0x18(%rsp), %xmm0
movsd (%rax), %xmm2
movsd 0x60(%rsp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x60(%rsp)
movq 0x30(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x30(%rsp)
jmp 0x486a9
jmp 0x48748
movq 0x38(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x38(%rsp)
jmp 0x4868d
jmp 0x4875d
leaq 0x50(%rsp), %rdi
callq 0x1ff20
jmp 0x4865d
movq 0x20(%rsp), %rax
movsd 0x60(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
movq 0x10(%rax), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x3be50
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1fd60
movsd 0x8(%rsp), %xmm0
movq 0x20(%rsp), %rdi
addsd (%rax), %xmm0
movsd %xmm0, 0x28(%rsp)
movsd 0x28(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
addq $0x48, %rdi
movslq 0xcc(%rsp), %rsi
callq 0x1fd60
movsd 0x10(%rsp), %xmm0
movsd %xmm0, (%rax)
addq $0xd8, %rsp
retq
nopw (%rax,%rax)