// File: 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:
subq $0x78, %rsp
movq %rdi, 0x70(%rsp)
movl %esi, 0x6c(%rsp)
movq 0x70(%rsp), %rdi
movq %rdi, 0x28(%rsp)
addq $0x60, %rdi
callq 0x21e20
cmpq $0x0, %rax
ja 0x48ac3
movq 0x225b7(%rip), %rdi     # 0x6afd8
leaq 0xd340(%rip), %rsi      # 0x55d68
callq 0x4230
movq %rax, %rdi
movq 0x22579(%rip), %rsi     # 0x6afb0
callq 0x4260
movq 0x22595(%rip), %rdi     # 0x6afd8
leaq 0xd378(%rip), %rsi      # 0x55dc2
callq 0x4230
movq 0x28(%rsp), %rdi
movq %rax, 0x18(%rsp)
addq $0x30, %rdi
callq 0x21e20
movq 0x18(%rsp), %rdi
movq %rax, %rsi
callq 0x4080
movq %rax, %rdi
leaq 0xd352(%rip), %rsi      # 0x55dcb
callq 0x4230
movq 0x28(%rsp), %rdi
movq %rax, 0x20(%rsp)
addq $0x60, %rdi
callq 0x21e20
movq 0x20(%rsp), %rdi
movq %rax, %rsi
callq 0x4080
movq %rax, %rdi
leaq 0xd32d(%rip), %rsi      # 0x55dd5
callq 0x4230
movq %rax, %rdi
movq 0x224f9(%rip), %rsi     # 0x6afb0
callq 0x4260
xorl %edi, %edi
callq 0x4290
movq 0x28(%rsp), %rdi
addq $0x18, %rdi
callq 0x21e20
movq 0x28(%rsp), %rdi
movq %rax, 0x10(%rsp)
addq $0x60, %rdi
callq 0x21e20
movq %rax, %rcx
movq 0x10(%rsp), %rax
cmpq %rcx, %rax
jne 0x48af3
jmp 0x48b12
leaq 0xd2e9(%rip), %rdi      # 0x55de3
leaq 0xced5(%rip), %rsi      # 0x559d6
movl $0x1df, %edx            # imm = 0x1DF
leaq 0xd2f8(%rip), %rcx      # 0x55e05
callq 0x4170
movq 0x28(%rsp), %rax
movq 0x78(%rax), %rdi
movq (%rdi), %rax
callq *0x2b8(%rax)
movq %rax, %rdi
callq 0x1fd90
movq %rax, 0x60(%rsp)
movq 0x60(%rsp), %rdi
callq 0x1f9c0
movq 0x28(%rsp), %rdi
movq %rax, 0x8(%rsp)
addq $0x18, %rdi
callq 0x21e20
movq %rax, %rcx
movq 0x8(%rsp), %rax
cmpq %rcx, %rax
jne 0x48b5d
jmp 0x48b7c
leaq 0xd2ca(%rip), %rdi      # 0x55e2e
leaq 0xce6b(%rip), %rsi      # 0x559d6
movl $0x1e1, %edx            # imm = 0x1E1
leaq 0xd28e(%rip), %rcx      # 0x55e05
callq 0x4170
movq 0x60(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1f9e0
movq %rax, %rdi
callq 0x3bae0
movq %rax, %rcx
movq 0x28(%rsp), %rax
movq %rcx, 0x50(%rsp)
movq %rdx, 0x58(%rsp)
movq 0x88(%rax), %rax
cmpq 0x50(%rsp), %rax
jae 0x48bb4
jmp 0x48bd3
leaq 0xd28f(%rip), %rdi      # 0x55e4a
leaq 0xce14(%rip), %rsi      # 0x559d6
movl $0x1e7, %edx            # imm = 0x1E7
leaq 0xd237(%rip), %rcx      # 0x55e05
callq 0x4170
cmpq $0x1, 0x58(%rsp)
jne 0x48bdd
jmp 0x48bfc
leaq 0x9f5e(%rip), %rdi      # 0x52b42
leaq 0xcdeb(%rip), %rsi      # 0x559d6
movl $0x1e8, %edx            # imm = 0x1E8
leaq 0xd20e(%rip), %rcx      # 0x55e05
callq 0x4170
movq 0x28(%rsp), %rax
movq 0x78(%rax), %rdi
movq (%rdi), %rax
callq *0x2a8(%rax)
movl %eax, 0x4c(%rsp)
movq 0x60(%rsp), %rdi
movslq 0x6c(%rsp), %rsi
callq 0x1f9e0
movq %rax, %rcx
movq 0x28(%rsp), %rax
movq %rcx, 0x40(%rsp)
movq 0x40(%rsp), %rdi
movq 0x88(%rax), %rsi
callq 0x3be50
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1fd60
movq 0x28(%rsp), %rdi
movsd (%rax), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x3c(%rsp)
addq $0x18, %rdi
movslq 0x6c(%rsp), %rsi
callq 0x1fd60
movsd (%rax), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x38(%rsp)
xorps %xmm0, %xmm0
movss %xmm0, 0x34(%rsp)
cmpl $0x0, 0x4c(%rsp)
jne 0x48c9e
movss 0x38(%rsp), %xmm0
subss 0x3c(%rsp), %xmm0
movss %xmm0, 0x34(%rsp)
jmp 0x48cb0
movss 0x38(%rsp), %xmm0
subss 0x3c(%rsp), %xmm0
movss %xmm0, 0x34(%rsp)
movq 0x28(%rsp), %rdi
movss 0x34(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, (%rsp)
addq $0x30, %rdi
movslq 0x6c(%rsp), %rsi
callq 0x1fd60
movsd (%rsp), %xmm0
movsd %xmm0, (%rax)
addq $0x78, %rsp
retq