// File: xbai0624[P]dnn/src/Neuron.cpp
// Function: Neuron::UpdateZPooling(int)
void Neuron::UpdateZPooling(int sample_index)
{
    // pooling layer
    // should be with cnn layer, just kernel matrix all elements=1, bias = 0;
    Layer* __previousLayer = __layer->GetPrevLayer();
    auto & inputImage = __previousLayer->GetImagesActiveA(); // no tensorization needed, b/c "fc->pooling" type connection is not used at the moment
    //if(inputImage.back().OutputImageFromKernel.size() < __coord.k)
    if(inputImage[sample_index].OutputImageFromKernel.size() < __coord.k)
    {
        // output image for current sample
        // pooling layer is different with cnn layer
        // in pooling layer, kernel and 'A' images has a 1-to-1 mapping relationship
        // for pooling layer, number of kernels (previous layer)  = number of kernels (current layer)
        std::cout<<"Error: pooling operation matrix dimension not match"<<std::endl;
        exit(0);
    }
    //Images image = inputImage.back(); // images for current training sample
    Images & image = inputImage[sample_index]; // images for current training sample
    std::vector<Matrix> & images = image.OutputImageFromKernel;
    //for(auto &i: images)cout<<i<<endl;
    Matrix & kernel_image = images[__coord.k];
    //std::cout<<kernel_image<<std::endl;

    auto dim = __w->Dimension();
    size_t i_size = dim.first, j_size = dim.second;

    size_t i_start = __coord.i * i_size;
    size_t j_start = __coord.j * j_size;

    // get pooling method
    PoolingMethod __poolingMethod = __layer->GetPoolingMethod();

    double z;
    if(__poolingMethod == PoolingMethod::Max) 
    {
        z = kernel_image.MaxInSectionWithPadding(i_start, i_start + i_size, j_start, j_start+j_size);
    } 
    else if(__poolingMethod == PoolingMethod::Average) 
    {
        z = kernel_image.AverageInSectionWithPadding(i_start, i_start + i_size, j_start, j_start+j_size);
    }
    else 
    {
        std::cout<<"Error: unspported pooling method, only max and average supported."<<std::endl;
        exit(0);
    }

    //__z.push_back(z);
    __z[sample_index] = z;
}

// Assembly:
subq $0x88, %rsp
movq %rdi, 0x80(%rsp)
movl %esi, 0x7c(%rsp)
movq 0x80(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x78(%rax), %rdi
movq (%rdi), %rax
callq *0x2c8(%rax)
movq %rax, 0x70(%rsp)
movq 0x70(%rsp), %rdi
movq (%rdi), %rax
callq *0xc8(%rax)
movq %rax, 0x68(%rsp)
movq 0x68(%rsp), %rdi
movslq 0x7c(%rsp), %rsi
callq 0x1fd40
movq %rax, %rdi
callq 0x1f9c0
movq 0x8(%rsp), %rcx
cmpq 0x98(%rcx), %rax
jae 0x48873
movq 0x22787(%rip), %rdi     # 0x6afd8
leaq 0xd321(%rip), %rsi      # 0x55b79
callq 0x4230
movq %rax, %rdi
movq 0x22749(%rip), %rsi     # 0x6afb0
callq 0x4260
xorl %edi, %edi
callq 0x4290
movq 0x68(%rsp), %rdi
movslq 0x7c(%rsp), %rsi
callq 0x1fd40
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x60(%rsp)
movq 0x60(%rsp), %rcx
movq %rcx, 0x58(%rsp)
movq 0x58(%rsp), %rdi
movq 0x98(%rax), %rsi
callq 0x1f9e0
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x50(%rsp)
movq 0x8(%rax), %rdi
callq 0x3bae0
movq %rax, %rcx
movq 0x8(%rsp), %rax
movq %rcx, 0x40(%rsp)
movq %rdx, 0x48(%rsp)
movq 0x40(%rsp), %rcx
movq %rcx, 0x38(%rsp)
movq 0x48(%rsp), %rcx
movq %rcx, 0x30(%rsp)
movq 0x88(%rax), %rcx
imulq 0x38(%rsp), %rcx
movq %rcx, 0x28(%rsp)
movq 0x90(%rax), %rcx
imulq 0x30(%rsp), %rcx
movq %rcx, 0x20(%rsp)
movq 0x78(%rax), %rdi
movq (%rdi), %rax
callq *0x210(%rax)
movl (%rax), %eax
movl %eax, 0x1c(%rsp)
cmpl $0x0, 0x1c(%rsp)
jne 0x4895c
movq 0x50(%rsp), %rdi
movq 0x28(%rsp), %rsi
movq 0x28(%rsp), %rdx
addq 0x38(%rsp), %rdx
movq 0x20(%rsp), %rcx
movq 0x20(%rsp), %r8
addq 0x30(%rsp), %r8
movsd 0xd039(%rip), %xmm0     # 0x55988
callq 0x404c0
movsd %xmm0, 0x10(%rsp)
jmp 0x489be
cmpl $0x1, 0x1c(%rsp)
jne 0x48993
movq 0x50(%rsp), %rdi
movq 0x28(%rsp), %rsi
movq 0x28(%rsp), %rdx
addq 0x38(%rsp), %rdx
movq 0x20(%rsp), %rcx
movq 0x20(%rsp), %r8
addq 0x30(%rsp), %r8
callq 0x40cc0
movsd %xmm0, 0x10(%rsp)
jmp 0x489bc
movq 0x2263e(%rip), %rdi     # 0x6afd8
leaq 0xd20c(%rip), %rsi      # 0x55bad
callq 0x4230
movq %rax, %rdi
movq 0x22600(%rip), %rsi     # 0x6afb0
callq 0x4260
xorl %edi, %edi
callq 0x4290
jmp 0x489be
movq 0x8(%rsp), %rdi
movsd 0x10(%rsp), %xmm0
movsd %xmm0, (%rsp)
addq $0x48, %rdi
movslq 0x7c(%rsp), %rsi
callq 0x1fd60
movsd (%rsp), %xmm0
movsd %xmm0, (%rax)
addq $0x88, %rsp
retq
nopl (%rax)