// File: xbai0624[P]dnn/src/Neuron.cpp
// Function: Neuron::UpdateDeltaCNN(int)
void Neuron::UpdateDeltaCNN(int sample_index)
{
    // back propagate delta for cnn layer
    float delta_for_current_neuron_in_current_sample = 0.; // save results.

    // sigma prime of current neuron in current sample
    if(__sigmaPrime.size()<=0)
    {
        std::cout<<"Error: computing delta needs sigma^prime computed first."<<std::endl;
        exit(0);
    }
    double _sigma_prime = __sigmaPrime[sample_index];

    // next layer delta images
    Layer* __nextLayer = __layer->GetNextLayer();
    std::vector<Images> & deltaVecNext = __nextLayer->GetImagesActiveDelta(); // for 2D layer, images are all active, drop out happens on kernel

    // next layer weight matrix
    //auto weightVecNext = __nextLayer->GetWeightMatrix(); // obsolete, moved into subsection

    // output image size for current layer
    auto output_image_size_for_current_layer = __layer->GetOutputImageSize();

    if(__nextLayer->GetType() != LayerType::cnn && __nextLayer->GetType() != LayerType::pooling)
    {
        // next layer is fc or output, 1 dimensional
        assert(deltaVecNext[sample_index].OutputImageFromKernel.size() == 1);
        // delta image from next layer
        Matrix & m_delta_next_layer = deltaVecNext[sample_index].OutputImageFromKernel[0];
        // weight matrix from next layer
        std::vector<Matrix> *v_w_next_layer = __nextLayer->GetWeightMatrix();
        // make sure dimension match
        size_t n_active_neurons_in_next_layer = m_delta_next_layer.Dimension().first;
        assert(m_delta_next_layer.Dimension().second == 1);
        assert(v_w_next_layer->size() == n_active_neurons_in_next_layer);

        /* 
        // method 1 (this method should be used in layer level, otherwise too time consuming)
        Matrix w_next_layer = Matrix::ConcatenateMatrixByI(*v_w_next_layer);
        Matrix w_next_layer_T = w_next_layer.Transpose();

        Matrix m_delta_current_layer = w_next_layer_T * m_delta_next_layer;

        Images delta_image_current_layer_cache;
        delta_image_current_layer_cache.OutputImageFromKernel.push_back(m_delta_current_layer);

        Images delta_image_current_layer = 
        delta_image_current_layer_cache.Tensorization(output_image_size_for_current_layer.first, output_image_size_for_current_layer.second);

        delta_for_current_neuron_in_current_sample = (delta_image_current_layer.OutputImageFromKernel[__coord.k])[__coord.i][__coord.j] * _sigma_prime;
        cout<<"sample id: "<<sample_index<<" delta: "<<delta_for_current_neuron_in_current_sample<<endl;
        */	

        // method 2 (compute only for current neuron, not the whole layer in method 1)
        auto mapped_coords_in_vec = mappedCoordsInVector(output_image_size_for_current_layer, __coord);
        double tmp = 0;
        for(size_t iii = 0; iii<n_active_neurons_in_next_layer; iii++)
        {
            tmp += ((*v_w_next_layer)[iii])[0][mapped_coords_in_vec.first] * m_delta_next_layer[iii][0];
        }
        delta_for_current_neuron_in_current_sample = tmp * _sigma_prime;

        // already checked: method 1 and method 2 have the same results
        //cout<<"sample id: "<<sample_index<<" delta: "<<delta_for_current_neuron_in_current_sample<<endl;
    }
    else if(__nextLayer->GetType() == LayerType::cnn )
    {
        // next layer is cnn, 2 dimensional
        // vector of delta matrix from next layer
        std::vector<Matrix> & v_m_delta_next_layer = deltaVecNext[sample_index].OutputImageFromKernel;
        // vector of weight matrix from next layer
        std::vector<Matrix> * v_w_next_layer = __nextLayer->GetWeightMatrix();

        size_t C_next = v_m_delta_next_layer.size();
        assert(C_next == v_w_next_layer->size()); // make sure number of kernels = number of delta matrix in next layer

        // back propagation
        double tmp = 0;
        for(size_t d=0;d<C_next;d++) // sum all kernels
        { 
            // get d^th delta and weight matrix of next layer
            Matrix & delta = v_m_delta_next_layer[d];
            Matrix & weight = (*v_w_next_layer)[d];

            auto weight_dimension = weight.Dimension();
            auto delta_dimension =  delta.Dimension();

            for(size_t p=0; p<weight_dimension.first;p++){
                for(size_t q=0;q<weight_dimension.second;q++)
                {
                    double tmp_d = 0;
                    int delta_index_p = __coord.i - p;
                    int delta_index_q = __coord.j - q;
                    if(delta_index_p >= 0 && delta_index_q >= 0 && delta_index_p<(int)delta_dimension.first && delta_index_q<(int)delta_dimension.second )
                        tmp_d = delta[delta_index_p][delta_index_q];
                    double tmp_w = weight[p][q];
                    tmp += tmp_d * tmp_w;
                }
            }
        }

        // multiply  sigma_prime
        delta_for_current_neuron_in_current_sample = tmp * _sigma_prime;
    }
    else if(__nextLayer->GetType() == LayerType::pooling)
    {
        // next layer is pooling 
        // number of  delta images from next layer should = number of kernels in this layer
        assert(deltaVecNext[sample_index].OutputImageFromKernel.size() == __layer->GetWeightMatrix()->size());

        // --) directly get delta image matrix in next layer for current kernel (for pooling, kernels have 1-to-1 mapping relationship)
        Matrix & m_delta_next_layer = deltaVecNext[sample_index].OutputImageFromKernel[__coord.k];

        // --) get delta value corresponds to current neuron
        //     step 1) from neuron element coord get the corresponding coord in pooling image
        auto k_dim = __nextLayer->GetKernelDimensionCNN(); // get pooling kernel dimension from next layer
        int x_coord_in_pooling = (int)__coord.i / (int) k_dim.first;
        int y_coord_in_pooling = (int)__coord.j / (int) k_dim.second;
        assert(x_coord_in_pooling < (int)m_delta_next_layer.Dimension().first);
        assert(y_coord_in_pooling < (int)m_delta_next_layer.Dimension().second);

        float delta_candidate = m_delta_next_layer[x_coord_in_pooling][y_coord_in_pooling];

        // --) then check 'A' value of current neuron,
        if(__nextLayer->GetPoolingMethod() == PoolingMethod::Max)
        {
            // check if current neuron is the max one
            auto & v_images_in_current_layer = __layer->GetImagesActiveA();
            Images & images_in_current_layer =  v_images_in_current_layer[sample_index];
            Matrix & image_current_kernel = images_in_current_layer.OutputImageFromKernel[__coord.k];

            // get the max element in the covered section
            float max_a_sec = image_current_kernel.MaxInSectionWithPadding(x_coord_in_pooling*k_dim.first, (x_coord_in_pooling+1)*k_dim.first,
                    y_coord_in_pooling*k_dim.second, (y_coord_in_pooling+1)*k_dim.second);

            float a_current_neuron = __a[sample_index];

            if(a_current_neuron >= max_a_sec) 
                delta_for_current_neuron_in_current_sample = delta_candidate; // current neuron is the max one (the one being used)
            else 
                delta_for_current_neuron_in_current_sample = 0; // current neuron is not the max one (not used)
        }
        else if(__nextLayer->GetPoolingMethod() == PoolingMethod::Average)
        {
            delta_for_current_neuron_in_current_sample = delta_candidate;
        }
        else 
        {
            std::cout<<__func__<<" Error: undefined pooling method, something is wrong."
                <<endl;
            exit(0);
        }

        //cout<<"pooling->cnn backpropagation: to be tested..."<<endl;
    }
    else
    {
        std::cout<<__func__<<" Error: CNN layer followed by unknow type of layer, something is wrong."
            <<std::endl;
        exit(0);
    }

    __delta[sample_index] = delta_for_current_neuron_in_current_sample;
}

// Assembly:
subq $0x1a8, %rsp            # imm = 0x1A8
movq %rdi, 0x1a0(%rsp)
movl %esi, 0x19c(%rsp)
movq 0x1a0(%rsp), %rdi
movq %rdi, 0x28(%rsp)
xorps %xmm0, %xmm0
movss %xmm0, 0x198(%rsp)
addq $0x60, %rdi
callq 0x21e20
cmpq $0x0, %rax
ja 0x49037
movq 0x21fc3(%rip), %rdi     # 0x6afd8
leaq 0xceff(%rip), %rsi      # 0x55f1b
callq 0x4230
movq %rax, %rdi
movq 0x21f85(%rip), %rsi     # 0x6afb0
callq 0x4260
xorl %edi, %edi
callq 0x4290
movq 0x28(%rsp), %rdi
addq $0x60, %rdi
movslq 0x19c(%rsp), %rsi
callq 0x1fd60
movq %rax, %rcx
movq 0x28(%rsp), %rax
movsd (%rcx), %xmm0
movsd %xmm0, 0x190(%rsp)
movq 0x78(%rax), %rdi
movq (%rdi), %rax
callq *0x2c0(%rax)
movq %rax, 0x188(%rsp)
movq 0x188(%rsp), %rdi
movq (%rdi), %rax
callq *0xf8(%rax)
movq %rax, %rcx
movq 0x28(%rsp), %rax
movq %rcx, 0x180(%rsp)
movq 0x78(%rax), %rdi
movq (%rdi), %rax
callq *0x270(%rax)
movq %rax, 0x170(%rsp)
movq %rdx, 0x178(%rsp)
movq 0x188(%rsp), %rdi
movq (%rdi), %rax
callq *0x250(%rax)
cmpl $0x1, %eax
je 0x49331
movq 0x188(%rsp), %rdi
movq (%rdi), %rax
callq *0x250(%rax)
cmpl $0x2, %eax
je 0x49331
movq 0x180(%rsp), %rdi
movslq 0x19c(%rsp), %rsi
callq 0x1fd40
movq %rax, %rdi
callq 0x1f9c0
cmpq $0x1, %rax
jne 0x4910e
jmp 0x4912d
leaq 0xce3f(%rip), %rdi      # 0x55f54
leaq 0xc8ba(%rip), %rsi      # 0x559d6
movl $0x28a, %edx            # imm = 0x28A
leaq 0xce69(%rip), %rcx      # 0x55f91
callq 0x4170
movq 0x180(%rsp), %rdi
movslq 0x19c(%rsp), %rsi
callq 0x1fd40
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1f9e0
movq %rax, 0x168(%rsp)
movq 0x188(%rsp), %rdi
movq (%rdi), %rax
callq *0x220(%rax)
movq %rax, 0x160(%rsp)
movq 0x168(%rsp), %rdi
callq 0x3bae0
movq %rax, 0x148(%rsp)
movq %rdx, 0x150(%rsp)
movq 0x148(%rsp), %rax
movq %rax, 0x158(%rsp)
movq 0x168(%rsp), %rdi
callq 0x3bae0
movq %rax, 0x138(%rsp)
movq %rdx, 0x140(%rsp)
cmpq $0x1, 0x140(%rsp)
jne 0x491c6
jmp 0x491e5
leaq 0xcde5(%rip), %rdi      # 0x55fb2
leaq 0xc802(%rip), %rsi      # 0x559d6
movl $0x291, %edx            # imm = 0x291
leaq 0xcdb1(%rip), %rcx      # 0x55f91
callq 0x4170
movq 0x160(%rsp), %rdi
callq 0x1f9c0
cmpq 0x158(%rsp), %rax
jne 0x491fe
jmp 0x4921d
leaq 0xcdd8(%rip), %rdi      # 0x55fdd
leaq 0xc7ca(%rip), %rsi      # 0x559d6
movl $0x292, %edx            # imm = 0x292
leaq 0xcd79(%rip), %rcx      # 0x55f91
callq 0x4170
movq 0x28(%rsp), %rsi
addq $0x88, %rsi
leaq 0x170(%rsp), %rdi
callq 0x4a0e0
movq %rax, 0x128(%rsp)
movq %rdx, 0x130(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x120(%rsp)
movq $0x0, 0x118(%rsp)
movq 0x118(%rsp), %rax
cmpq 0x158(%rsp), %rax
jae 0x4930d
movq 0x160(%rsp), %rdi
movq 0x118(%rsp), %rsi
callq 0x1f9e0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x3be50
movq %rax, %rdi
movq 0x128(%rsp), %rsi
callq 0x1fd60
movsd (%rax), %xmm0
movsd %xmm0, 0x20(%rsp)
movq 0x168(%rsp), %rdi
movq 0x118(%rsp), %rsi
callq 0x3be50
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1fd60
movsd 0x20(%rsp), %xmm0
movsd (%rax), %xmm2
movsd 0x120(%rsp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x120(%rsp)
movq 0x118(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x118(%rsp)
jmp 0x4925e
movsd 0x120(%rsp), %xmm0
mulsd 0x190(%rsp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x198(%rsp)
jmp 0x499d2
movq 0x188(%rsp), %rdi
movq (%rdi), %rax
callq *0x250(%rax)
cmpl $0x1, %eax
jne 0x4963e
movq 0x180(%rsp), %rdi
movslq 0x19c(%rsp), %rsi
callq 0x1fd40
movq %rax, 0x110(%rsp)
movq 0x188(%rsp), %rdi
movq (%rdi), %rax
callq *0x220(%rax)
movq %rax, 0x108(%rsp)
movq 0x110(%rsp), %rdi
callq 0x1f9c0
movq %rax, 0x100(%rsp)
movq 0x100(%rsp), %rax
movq %rax, 0x18(%rsp)
movq 0x108(%rsp), %rdi
callq 0x1f9c0
movq %rax, %rcx
movq 0x18(%rsp), %rax
cmpq %rcx, %rax
jne 0x493bf
jmp 0x493de
leaq 0xcc50(%rip), %rdi      # 0x56016
leaq 0xc609(%rip), %rsi      # 0x559d6
movl $0x2ba, %edx            # imm = 0x2BA
leaq 0xcbb8(%rip), %rcx      # 0x55f91
callq 0x4170
xorps %xmm0, %xmm0
movsd %xmm0, 0xf8(%rsp)
movq $0x0, 0xf0(%rsp)
movq 0xf0(%rsp), %rax
cmpq 0x100(%rsp), %rax
jae 0x4961a
movq 0x110(%rsp), %rdi
movq 0xf0(%rsp), %rsi
callq 0x1f9e0
movq %rax, 0xe8(%rsp)
movq 0x108(%rsp), %rdi
movq 0xf0(%rsp), %rsi
callq 0x1f9e0
movq %rax, 0xe0(%rsp)
movq 0xe0(%rsp), %rdi
callq 0x3bae0
movq %rax, 0xd0(%rsp)
movq %rdx, 0xd8(%rsp)
movq 0xe8(%rsp), %rdi
callq 0x3bae0
movq %rax, 0xc0(%rsp)
movq %rdx, 0xc8(%rsp)
movq $0x0, 0xb8(%rsp)
movq 0xb8(%rsp), %rax
cmpq 0xd0(%rsp), %rax
jae 0x495ff
movq $0x0, 0xb0(%rsp)
movq 0xb0(%rsp), %rax
cmpq 0xd8(%rsp), %rax
jae 0x495e4
movq 0x28(%rsp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, 0xa8(%rsp)
movq 0x88(%rax), %rcx
subq 0xb8(%rsp), %rcx
movl %ecx, 0xa4(%rsp)
movq 0x90(%rax), %rax
subq 0xb0(%rsp), %rax
movl %eax, 0xa0(%rsp)
cmpl $0x0, 0xa4(%rsp)
jl 0x4956d
cmpl $0x0, 0xa0(%rsp)
jl 0x4956d
movl 0xa4(%rsp), %eax
movq 0xc0(%rsp), %rcx
cmpl %ecx, %eax
jge 0x4956d
movl 0xa0(%rsp), %eax
movq 0xc8(%rsp), %rcx
cmpl %ecx, %eax
jge 0x4956d
movq 0xe8(%rsp), %rdi
movslq 0xa4(%rsp), %rsi
callq 0x3be50
movq %rax, %rdi
movslq 0xa0(%rsp), %rsi
callq 0x1fd60
movsd (%rax), %xmm0
movsd %xmm0, 0xa8(%rsp)
movq 0xe0(%rsp), %rdi
movq 0xb8(%rsp), %rsi
callq 0x3be50
movq %rax, %rdi
movq 0xb0(%rsp), %rsi
callq 0x1fd60
movsd (%rax), %xmm0
movsd %xmm0, 0x98(%rsp)
movsd 0xa8(%rsp), %xmm0
movsd 0x98(%rsp), %xmm2
movsd 0xf8(%rsp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0xf8(%rsp)
movq 0xb0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb0(%rsp)
jmp 0x494ae
jmp 0x495e6
movq 0xb8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb8(%rsp)
jmp 0x4948c
jmp 0x49601
movq 0xf0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xf0(%rsp)
jmp 0x493f6
movsd 0xf8(%rsp), %xmm0
mulsd 0x190(%rsp), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x198(%rsp)
jmp 0x499d0
movq 0x188(%rsp), %rdi
movq (%rdi), %rax
callq *0x250(%rax)
cmpl $0x2, %eax
jne 0x49996
movq 0x180(%rsp), %rdi
movslq 0x19c(%rsp), %rsi
callq 0x1fd40
movq %rax, %rdi
callq 0x1f9c0
movq %rax, %rcx
movq 0x28(%rsp), %rax
movq %rcx, 0x10(%rsp)
movq 0x78(%rax), %rdi
movq (%rdi), %rax
callq *0x220(%rax)
movq %rax, %rdi
callq 0x1f9c0
movq %rax, %rcx
movq 0x10(%rsp), %rax
cmpq %rcx, %rax
jne 0x496a6
jmp 0x496c5
leaq 0xc98a(%rip), %rdi      # 0x56037
leaq 0xc322(%rip), %rsi      # 0x559d6
movl $0x2dc, %edx            # imm = 0x2DC
leaq 0xc8d1(%rip), %rcx      # 0x55f91
callq 0x4170
movq 0x180(%rsp), %rdi
movslq 0x19c(%rsp), %rsi
callq 0x1fd40
movq %rax, %rdi
movq 0x28(%rsp), %rax
movq 0x98(%rax), %rsi
callq 0x1f9e0
movq %rax, 0x90(%rsp)
movq 0x188(%rsp), %rdi
movq (%rdi), %rax
callq *0x290(%rax)
movq %rax, %rcx
movq 0x28(%rsp), %rax
movq %rcx, 0x80(%rsp)
movq %rdx, 0x88(%rsp)
movq 0x88(%rax), %rax
movq 0x80(%rsp), %rcx
cltd
idivl %ecx
movl %eax, %ecx
movq 0x28(%rsp), %rax
movl %ecx, 0x7c(%rsp)
movq 0x90(%rax), %rax
movq 0x88(%rsp), %rcx
cltd
idivl %ecx
movl %eax, 0x78(%rsp)
movl 0x7c(%rsp), %eax
movl %eax, 0xc(%rsp)
movq 0x90(%rsp), %rdi
callq 0x3bae0
movq %rax, %rcx
movl 0xc(%rsp), %eax
movq %rcx, 0x68(%rsp)
movq %rdx, 0x70(%rsp)
movq 0x68(%rsp), %rcx
cmpl %ecx, %eax
jge 0x49783
jmp 0x497a2
leaq 0xc90b(%rip), %rdi      # 0x56095
leaq 0xc245(%rip), %rsi      # 0x559d6
movl $0x2e6, %edx            # imm = 0x2E6
leaq 0xc7f4(%rip), %rcx      # 0x55f91
callq 0x4170
movl 0x78(%rsp), %eax
movl %eax, 0x8(%rsp)
movq 0x90(%rsp), %rdi
callq 0x3bae0
movq %rax, %rcx
movl 0x8(%rsp), %eax
movq %rcx, 0x58(%rsp)
movq %rdx, 0x60(%rsp)
movq 0x60(%rsp), %rcx
cmpl %ecx, %eax
jge 0x497d3
jmp 0x497f2
leaq 0xc8fa(%rip), %rdi      # 0x560d4
leaq 0xc1f5(%rip), %rsi      # 0x559d6
movl $0x2e7, %edx            # imm = 0x2E7
leaq 0xc7a4(%rip), %rcx      # 0x55f91
callq 0x4170
movq 0x90(%rsp), %rdi
movslq 0x7c(%rsp), %rsi
callq 0x3be50
movq %rax, %rdi
movslq 0x78(%rsp), %rsi
callq 0x1fd60
movsd (%rax), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x54(%rsp)
movq 0x188(%rsp), %rdi
movq (%rdi), %rax
callq *0x210(%rax)
cmpl $0x0, (%rax)
jne 0x49933
movq 0x28(%rsp), %rax
movq 0x78(%rax), %rdi
movq (%rdi), %rax
callq *0xc8(%rax)
movq %rax, 0x48(%rsp)
movq 0x48(%rsp), %rdi
movslq 0x19c(%rsp), %rsi
callq 0x1fd40
movq %rax, %rcx
movq 0x28(%rsp), %rax
movq %rcx, 0x40(%rsp)
movq 0x40(%rsp), %rdi
movq 0x98(%rax), %rsi
callq 0x1f9e0
movq %rax, 0x38(%rsp)
movq 0x38(%rsp), %rdi
movslq 0x7c(%rsp), %rsi
imulq 0x80(%rsp), %rsi
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movslq %eax, %rdx
imulq 0x80(%rsp), %rdx
movslq 0x78(%rsp), %rcx
imulq 0x88(%rsp), %rcx
movl 0x78(%rsp), %eax
addl $0x1, %eax
movslq %eax, %r8
imulq 0x88(%rsp), %r8
movsd 0xc0b4(%rip), %xmm0     # 0x55988
callq 0x404c0
movq 0x28(%rsp), %rdi
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x34(%rsp)
addq $0x18, %rdi
movslq 0x19c(%rsp), %rsi
callq 0x1fd60
movsd (%rax), %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x30(%rsp)
movss 0x30(%rsp), %xmm0
ucomiss 0x34(%rsp), %xmm0
jb 0x49925
movss 0x54(%rsp), %xmm0
movss %xmm0, 0x198(%rsp)
jmp 0x49931
xorps %xmm0, %xmm0
movss %xmm0, 0x198(%rsp)
jmp 0x49994
movq 0x188(%rsp), %rdi
movq (%rdi), %rax
callq *0x210(%rax)
cmpl $0x1, (%rax)
jne 0x4995a
movss 0x54(%rsp), %xmm0
movss %xmm0, 0x198(%rsp)
jmp 0x49992
movq 0x21677(%rip), %rdi     # 0x6afd8
leaq 0xc7ac(%rip), %rsi      # 0x56114
callq 0x4230
movq %rax, %rdi
leaq 0xc7ac(%rip), %rsi      # 0x56123
callq 0x4230
movq %rax, %rdi
movq 0x2162a(%rip), %rsi     # 0x6afb0
callq 0x4260
xorl %edi, %edi
callq 0x4290
jmp 0x49994
jmp 0x499ce
movq 0x2163b(%rip), %rdi     # 0x6afd8
leaq 0xc770(%rip), %rsi      # 0x56114
callq 0x4230
movq %rax, %rdi
leaq 0xc7a6(%rip), %rsi      # 0x56159
callq 0x4230
movq %rax, %rdi
movq 0x215ee(%rip), %rsi     # 0x6afb0
callq 0x4260
xorl %edi, %edi
callq 0x4290
jmp 0x499d0
jmp 0x499d2
movq 0x28(%rsp), %rdi
movss 0x198(%rsp), %xmm0
cvtss2sd %xmm0, %xmm0
movsd %xmm0, (%rsp)
addq $0x30, %rdi
movslq 0x19c(%rsp), %rsi
callq 0x1fd60
movsd (%rsp), %xmm0
movsd %xmm0, (%rax)
addq $0x1a8, %rsp            # imm = 0x1A8
retq
nopl (%rax,%rax)