// File: /workspace/github_cpp_makefile_star2_O1/xbai0624[P]dnn/src/Neuron.cpp
// Function: Neuron::UpdateZFC(int)
void Neuron::UpdateZFC(int sample_index)
{
    // for fully connected layer, matrix reform are also done in here
    Layer* __previousLayer = __layer->GetPrevLayer();
    std::vector<Images>& _t = __previousLayer -> GetImagesActiveA(); // this line with '&' is 5 times faster than the following line without '&'

    //cout<<"batch size: "<<_t.size()<<endl;
    //cout<<"kernel number: "<<_t[0].GetNumberOfKernels()<<endl;
    //cout<<" image dimension: "<<_t[0].OutputImageFromKernel[0].Dimension()<<endl;
    if(_t.size() < 1 || _t.size() < (size_t)sample_index) 
    {
        std::cout<<"Error: previous layer has not 'A' image."<<std::endl;
        exit(0);
    }
    //Images &images = _t[sample_index]; // get images for current sample


    double z_for_current_neuron = 0;
    // get images for current sample
    Images images;
    if(__previousLayer->GetType() != LayerType::fullyConnected/* && __previousLayer->GetType() != LayerType::input*/ )
    {
        // need vectorization 2D->1D
        // input layer vectorization is already done in DataInterface class
        images = _t[sample_index].Vectorization(); // get images for current sample
    }
    else
    {
        // previous layer is fc, no need to do anything
        images = _t[sample_index];
    }

    if(images.OutputImageFromKernel.size() != 1) 
    {
        std::cout<<"Eroor: layer type not match, expecting FC layer, FC layer should only have 1 kernel."<<std::endl;
        exit(0);
    }

    Matrix &image = images.OutputImageFromKernel[0]; // FC layer has only one "kernel" (equivalent kernel)
    //cout<<"neuron id: "<<__neuron_id<<", image A debug:"<<endl;
    //cout<<image<<endl;


    //cout<<__func__<<" CHECKING HERE!!!! weight matrix dimension: "<<(*__w).Dimension()<<endl;
    //cout<<(*__w)<<endl;
    Matrix res = (*__w) * image;
    //cout<<"res matrix: "<<endl;
    //cout<<res<<endl;
    auto dim = res.Dimension();
    if(dim.first != 1 || dim.second != 1) 
    {
        std::cout<<"Error: wrong dimension, expecting 1D matrix."<<std::endl;
    }
    z_for_current_neuron = res[0][0];

    z_for_current_neuron = z_for_current_neuron + (*__b)[0][0];

    __z[sample_index] = z_for_current_neuron;
    //cout<<__func__<<" finished."<<endl;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x60, %rsp
movl %esi, %ebp
movq %rdi, %rbx
movq 0x78(%rdi), %rdi
movq (%rdi), %rax
callq *0x2c8(%rax)
movq %rax, %r15
movq (%rax), %rax
movq %r15, %rdi
callq *0xc8(%rax)
movq %rax, %r14
movq 0x8(%rax), %rax
subq (%r14), %rax
je 0x20c0f
sarq $0x3, %rax
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
imulq %rax, %rcx
movslq %ebp, %r12
cmpq %r12, %rcx
jb 0x20c0f
xorps %xmm0, %xmm0
movaps %xmm0, (%rsp)
movq $0x0, 0x10(%rsp)
movq (%r15), %rax
movq %r15, %rdi
callq *0x250(%rax)
leaq (%r12,%r12,2), %rsi
shlq $0x3, %rsi
testl %eax, %eax
je 0x20b29
addq (%r14), %rsi
leaq 0x40(%rsp), %rdi
callq 0x143f4
xorps %xmm0, %xmm0
leaq 0x20(%rsp), %rdi
movaps %xmm0, (%rdi)
movaps (%rsp), %xmm0
movq 0x10(%rsp), %rax
leaq 0x40(%rsp), %r14
movaps (%r14), %xmm1
movaps %xmm1, (%rsp)
movq 0x10(%r14), %rcx
movq %rcx, 0x10(%rsp)
movq %rax, 0x10(%rdi)
movaps (%rdi), %xmm1
movaps %xmm0, (%rdi)
movaps %xmm1, (%r14)
movq $0x0, 0x10(%r14)
callq 0x136aa
movq %r14, %rdi
callq 0x136aa
jmp 0x20b34
addq (%r14), %rsi
movq %rsp, %rdi
callq 0x1429e
movq (%rsp), %rdx
movq 0x8(%rsp), %rax
subq %rdx, %rax
cmpq $0x18, %rax
jne 0x20c31
movq 0x8(%rbx), %rsi
leaq 0x20(%rsp), %rdi
callq 0x1acc8
leaq 0x20(%rsp), %rdi
callq 0x1ac7c
xorq $0x1, %rax
xorq $0x1, %rdx
orq %rax, %rdx
je 0x20bb5
movq 0x16462(%rip), %r14     # 0x36fd8
leaq 0xa13f(%rip), %rsi      # 0x2acbc
movl $0x2c, %edx
movq %r14, %rdi
callq 0x4280
movq (%r14), %rax
addq -0x18(%rax), %r14
movq %r14, %rdi
movl $0xa, %esi
callq 0x4250
movsbl %al, %esi
movq 0x16430(%rip), %rdi     # 0x36fd8
callq 0x4030
movq %rax, %rdi
callq 0x4190
leaq 0x20(%rsp), %rdi
xorl %esi, %esi
callq 0x1ae76
movq (%rax), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x38(%rsp)
movq 0x10(%rbx), %rdi
xorl %esi, %esi
callq 0x1ae76
movq (%rax), %rax
movsd 0x38(%rsp), %xmm0
addsd (%rax), %xmm0
movq 0x48(%rbx), %rax
movsd %xmm0, (%rax,%r12,8)
leaq 0x20(%rsp), %rdi
callq 0x1acb6
movq %rsp, %rdi
callq 0x136aa
addq $0x60, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
movq 0x163c2(%rip), %rdi     # 0x36fd8
leaq 0xa021(%rip), %rsi      # 0x2ac3e
callq 0x4260
movq %rax, %rdi
callq 0x4100
xorl %edi, %edi
callq 0x4290
movq 0x163a0(%rip), %rdi     # 0x36fd8
leaq 0xa028(%rip), %rsi      # 0x2ac67
movl $0x54, %edx
callq 0x4280
movq 0x16388(%rip), %rdi     # 0x36fd8
callq 0x4100
jmp 0x20c2a
jmp 0x20c5b
jmp 0x20c5b
movq %rax, %rbx
jmp 0x20c6d
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x1acb6
movq %rsp, %rdi
callq 0x136aa
movq %rbx, %rdi
callq 0x43e0
nop