// File: kernel.cpp
#include "pooling_contract.h"
#include "pooling_arm.h"
#include "mat.h"
#include "option.h"
#include <cstring>

int ncnn::pooling_kernel(
    const Mat& bottom_blob, Mat& top_blob,
    int kernel_h, int kernel_w,
    int stride_h, int stride_w,
    int pad_top, int pad_left,
    const Option& opt)
{
    const int C = top_blob.c;  // pre-set by binding.cpp (== input channels)

    Pooling_arm pool;
    pool.pooling_type              = 0; // PoolMethod_MAX
    pool.kernel_w                  = kernel_w;
    pool.kernel_h                  = kernel_h;
    pool.stride_w                  = stride_w;
    pool.stride_h                  = stride_h;
    pool.pad_left                  = pad_left;
    pool.pad_right                 = pad_left;
    pool.pad_top                   = pad_top;
    pool.pad_bottom                = pad_top;
    pool.global_pooling            = 0;
    pool.pad_mode                  = 1; // "valid" — plain floor output-size formula
    pool.avgpool_count_include_pad = 0;
    pool.adaptive_pooling          = 0;
    pool.out_w                     = 0;
    pool.out_h                     = 0;

    if (pool.create_pipeline(opt) != 0) return -1;

    Mat local_top;
    if (pool.forward(bottom_blob, local_top, opt) != 0) return -1;

    for (int c = 0; c < C; ++c)
        std::memcpy((float*)top_blob.channel(c), (const float*)local_top.channel(c),
                    top_blob.h * top_blob.w * sizeof(float));
    return 0;
}