// File: xbai0624[P]dnn/src/Neuron.cpp
// Function: Neuron::UpdateSigmaPrime(int)
void Neuron::UpdateSigmaPrime(int sample_index)
{
    // update sigma^prime
    //if(__sigmaPrime.size() != __z.size()-1) 
    //{
    //std::cout<<"Error: computing sigma^prime needs z computed first."<<std::endl;
    //exit(0);
    //}
    //if(__sigmaPrime.size() != __a.size()-1) 
    //{
    //std::cout<<"Error: computing sigma^prime needs a computed first."<<std::endl;
    //exit(0);
    //}

    //double a = __a.back();
    //double z = __z.back();
    double a = __a[sample_index];
    double z = __z[sample_index];
    double sigma_prime = -100; // theoretically, it must between [0, 1]

    if(__funcType == ActuationFuncType::Sigmoid || __funcType == ActuationFuncType::SoftMax) 
    {
        // the \partial a over \partial z is the same for sigmoid and softmax
        // one can easily prove it
        double diff = 1. - a;
        if( diff < 1e-10) diff = 0.; // to get rid of float number precision issues
        sigma_prime = diff*a;
    }
    else if(__funcType == ActuationFuncType::Tanh) 
    {
        sigma_prime = ( 2. / (exp(z) + exp(-z)) ) * ( 2. / (exp(z) + exp(-z)) );
    }
    else if(__funcType == ActuationFuncType::Relu) 
    {
        if( z > 0) sigma_prime = 1.;
        else sigma_prime = 0;
    }
    else
        std::cout<<"Error: unsupported actuation function type in direvative."<<std::endl;

    if(sigma_prime < 0.)
    {
        std::cout<<"Error: Neuron::UpdateSigmaPrime: sigma_prime<0? something wrong."
            <<endl;
        std::cout<<"    Actuation function type: "<<__funcType<<std::endl;
        std::cout<<"    Z: "<<z<<std::endl;
        std::cout<<"    a: "<<a<<std::endl;
        std::cout<<"    sigma prime: "<<sigma_prime<<std::endl;
        exit(0);
    }

    //__sigmaPrime.push_back(sigma_prime);
    __sigmaPrime[sample_index] = sigma_prime;
}

// Assembly:
subq $0x58, %rsp
movq %rdi, 0x50(%rsp)
movl %esi, 0x4c(%rsp)
movq 0x50(%rsp), %rdi
movq %rdi, 0x20(%rsp)
addq $0x18, %rdi
movslq 0x4c(%rsp), %rsi
callq 0x1fd60
movq 0x20(%rsp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, 0x40(%rsp)
addq $0x48, %rdi
movslq 0x4c(%rsp), %rsi
callq 0x1fd60
movq %rax, %rcx
movq 0x20(%rsp), %rax
movsd (%rcx), %xmm0
movsd %xmm0, 0x38(%rsp)
movsd 0xdfe4(%rip), %xmm0     # 0x55980
movsd %xmm0, 0x30(%rsp)
cmpl $0x0, 0x84(%rax)
je 0x479b9
movq 0x20(%rsp), %rax
cmpl $0x1, 0x84(%rax)
jne 0x479fd
movsd 0xa647(%rip), %xmm0     # 0x52008
subsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
movsd 0xa66b(%rip), %xmm0     # 0x52040
ucomisd 0x28(%rsp), %xmm0
jbe 0x479e6
xorps %xmm0, %xmm0
movsd %xmm0, 0x28(%rsp)
movsd 0x28(%rsp), %xmm0
mulsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
jmp 0x47b1a
movq 0x20(%rsp), %rax
cmpl $0x2, 0x84(%rax)
jne 0x47abc
movsd 0x38(%rsp), %xmm0
callq 0x4420
movsd %xmm0, 0x8(%rsp)
movsd 0x38(%rsp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
callq 0x4420
movsd 0x8(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd 0xa5c4(%rip), %xmm0     # 0x52018
divsd %xmm1, %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x38(%rsp), %xmm0
callq 0x4420
movsd %xmm0, 0x10(%rsp)
movsd 0x38(%rsp), %xmm0
movq %xmm0, %rax
movabsq $-0x8000000000000000, %rcx # imm = 0x8000000000000000
xorq %rcx, %rax
movq %rax, %xmm0
callq 0x4420
movsd 0x10(%rsp), %xmm2
movaps %xmm0, %xmm1
movsd 0x18(%rsp), %xmm0
addsd %xmm1, %xmm2
movsd 0xa56c(%rip), %xmm1     # 0x52018
divsd %xmm2, %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, 0x30(%rsp)
jmp 0x47b18
movq 0x20(%rsp), %rax
cmpl $0x3, 0x84(%rax)
jne 0x47af4
movsd 0x38(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x47ae9
movsd 0xa527(%rip), %xmm0     # 0x52008
movsd %xmm0, 0x30(%rsp)
jmp 0x47af2
xorps %xmm0, %xmm0
movsd %xmm0, 0x30(%rsp)
jmp 0x47b16
movq 0x234dd(%rip), %rdi     # 0x6afd8
leaq 0xe1ab(%rip), %rsi      # 0x55cad
callq 0x4230
movq %rax, %rdi
movq 0x2349f(%rip), %rsi     # 0x6afb0
callq 0x4260
jmp 0x47b18
jmp 0x47b1a
xorps %xmm0, %xmm0
ucomisd 0x30(%rsp), %xmm0
jbe 0x47c18
movq 0x234a8(%rip), %rdi     # 0x6afd8
leaq 0xe1b0(%rip), %rsi      # 0x55ce7
callq 0x4230
movq %rax, %rdi
movq 0x2346a(%rip), %rsi     # 0x6afb0
callq 0x4260
movq 0x23486(%rip), %rdi     # 0x6afd8
leaq 0xe1cf(%rip), %rsi      # 0x55d28
callq 0x4230
movq 0x20(%rsp), %rsi
movq %rax, %rdi
addq $0x84, %rsi
callq 0x3aaf0
movq %rax, %rdi
movq 0x23434(%rip), %rsi     # 0x6afb0
callq 0x4260
movq 0x23450(%rip), %rdi     # 0x6afd8
leaq 0xe1b7(%rip), %rsi      # 0x55d46
callq 0x4230
movq %rax, %rdi
movsd 0x38(%rsp), %xmm0
callq 0x4440
movq %rax, %rdi
movq 0x23404(%rip), %rsi     # 0x6afb0
callq 0x4260
movq 0x23420(%rip), %rdi     # 0x6afd8
leaq 0xe18f(%rip), %rsi      # 0x55d4e
callq 0x4230
movq %rax, %rdi
movsd 0x40(%rsp), %xmm0
callq 0x4440
movq %rax, %rdi
movq 0x233d4(%rip), %rsi     # 0x6afb0
callq 0x4260
movq 0x233f0(%rip), %rdi     # 0x6afd8
leaq 0xe167(%rip), %rsi      # 0x55d56
callq 0x4230
movq %rax, %rdi
movsd 0x30(%rsp), %xmm0
callq 0x4440
movq %rax, %rdi
movq 0x233a4(%rip), %rsi     # 0x6afb0
callq 0x4260
xorl %edi, %edi
callq 0x4290
movq 0x20(%rsp), %rdi
movsd 0x30(%rsp), %xmm0
movsd %xmm0, (%rsp)
addq $0x60, %rdi
movslq 0x4c(%rsp), %rsi
callq 0x1fd60
movsd (%rsp), %xmm0
movsd %xmm0, (%rax)
addq $0x58, %rsp
retq
nopw %cs:(%rax,%rax)