// File: /workspace/github_cpp_makefile_star2_O2/xbai0624[P]dnn/src/Neuron.cpp
// Function: Neuron::UpdateDeltaOutputLayer(int)
void Neuron::UpdateDeltaOutputLayer(int sample_index)
{
    // back propagation delta for output layer
    if(__sigmaPrime.size() <= 0) 
    {
        std::cout<<"Error: Neuron::UpdateDeltaOutputLayer() computing delta needs sigma^prime computed first."<<std::endl;
        std::cout<<"        "<<__delta.size()<<" deltas, "<<__sigmaPrime.size()<<" sigma^primes"<<endl;
        exit(0);
    }
    assert(__a.size() == __sigmaPrime.size()); // make sure all have been updated
    auto & labels = __layer->GetDataInterface()->GetCurrentBatchLabel();
    assert(labels.size() == __a.size()); // make sure all samples have been processed

    //size_t batch_size = __a.size();

    // check
    auto dim = labels[0].Dimension(); // dim.first is neuron row number, dim.second is neuron collum number
    assert(__coord.i < dim.first);
    assert(dim.second == 1);
    //cout<<"neuron coord: "<<__coord<<endl;
    //assert(__coord.j == 0);

    //cout<<"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<<endl;
    //cout<<"sample index: "<<sample_index<<endl;
    //cout<<"neuron id: "<<__neuron_id<<endl;
    //Print();

    auto cost_func_type = __layer->GetCostFuncType(); // for $\partial C over \partial a$

    // label for current sample
    Matrix & label_for_current_sample = labels[sample_index]; 
    //cout<<label_for_current_sample<<endl;
    // expected value for current sample current neuron
    float y_i = label_for_current_sample[__coord.i][0];
    //cout<<"---"<<y_i<<endl;

    // a value for current sample
    float a_i = __a[sample_index];
    //cout<<a_i<<endl;

    // sigma^\prime for current sample
    //float sigma_prime_i = __sigmaPrime[sample_index]; // obsolete
    //cout<<"---"<<sigma_prime_i<<endl;

    // solve for dC/da, which is dependent on the type of cost function
    float delta = 0;
    if(cost_func_type == CostFuncType::cross_entropy)
    {
        delta = a_i  - y_i;
    }
    else 
    {
        // other types of cost function: to be implemented
        delta = a_i - y_i; 
    }

    // save delta for this batch this neuron
    __delta[sample_index] = delta;
    //cout<<"here..."<<endl;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq 0x68(%rdi), %rax
subq 0x60(%rdi), %rax
je 0x1c879
movq 0x20(%rbx), %rcx
subq 0x18(%rbx), %rcx
cmpq %rax, %rcx
jne 0x1c8fb
movl %esi, %ebp
movq 0x78(%rbx), %rdi
movq (%rdi), %rax
callq *0x2b8(%rax)
movq %rax, %r14
movq 0x28(%rax), %rdi
movq 0x30(%rax), %rax
subq %rdi, %rax
pushq $0x18
popq %rcx
cqto
idivq %rcx
movq 0x20(%rbx), %rcx
subq 0x18(%rbx), %rcx
sarq $0x3, %rcx
cmpq %rcx, %rax
jne 0x1c91a
callq 0x17a6a
cmpq %rax, 0x88(%rbx)
jae 0x1c939
cmpq $0x1, %rdx
jne 0x1c958
movq 0x78(%rbx), %rdi
movq (%rdi), %rax
callq *0x2a8(%rax)
movslq %ebp, %r15
imulq $0x18, %r15, %rdi
addq 0x28(%r14), %rdi
movq 0x88(%rbx), %rsi
callq 0x17c46
movq (%rax), %rax
cvtsd2ss (%rax), %xmm0
movq 0x18(%rbx), %rax
cvtsd2ss (%rax,%r15,8), %xmm1
movq 0x30(%rbx), %rax
subss %xmm0, %xmm1
cvtss2sd %xmm1, %xmm0
movsd %xmm0, (%rax,%r15,8)
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movq 0x16758(%rip), %r14     # 0x32fd8
leaq 0x8611(%rip), %rsi      # 0x24e98
movq %r14, %rdi
callq 0x4240
movq %rax, %rdi
callq 0x4130
leaq 0x8654(%rip), %rsi      # 0x24ef2
movq %r14, %rdi
callq 0x4240
movq 0x38(%rbx), %rsi
subq 0x30(%rbx), %rsi
sarq $0x3, %rsi
movq %rax, %rdi
callq 0x4090
leaq 0x863a(%rip), %rsi      # 0x24efb
movq %rax, %rdi
callq 0x4240
movq 0x68(%rbx), %rsi
subq 0x60(%rbx), %rsi
sarq $0x3, %rsi
movq %rax, %rdi
callq 0x4090
leaq 0x8621(%rip), %rsi      # 0x24f05
movq %rax, %rdi
callq 0x4240
movq %rax, %rdi
callq 0x4130
xorl %edi, %edi
callq 0x4260
leaq 0x8611(%rip), %rdi      # 0x24f13
leaq 0x81fd(%rip), %rsi      # 0x24b06
leaq 0x8625(%rip), %rcx      # 0x24f35
movl $0x1df, %edx            # imm = 0x1DF
callq 0x4180
leaq 0x863d(%rip), %rdi      # 0x24f5e
leaq 0x81de(%rip), %rsi      # 0x24b06
leaq 0x8606(%rip), %rcx      # 0x24f35
movl $0x1e1, %edx            # imm = 0x1E1
callq 0x4180
leaq 0x863a(%rip), %rdi      # 0x24f7a
leaq 0x81bf(%rip), %rsi      # 0x24b06
leaq 0x85e7(%rip), %rcx      # 0x24f35
movl $0x1e7, %edx            # imm = 0x1E7
callq 0x4180
leaq 0x56ac(%rip), %rdi      # 0x2200b
leaq 0x81a0(%rip), %rsi      # 0x24b06
leaq 0x85c8(%rip), %rcx      # 0x24f35
movl $0x1e8, %edx            # imm = 0x1E8
callq 0x4180
nop