// File: kernel.cpp
// Reference-scalar conv2d_depthwise w8a8ch (int8 activations + weights, per-channel dequant).
// LLM target: replace this file with an optimised inner_conv2d_depthwise.
// All per-definition constants live in conv2d_depthwise_def:: (conv2d_depthwise.h).
#include "conv2d_depthwise.h"
using namespace conv2d_depthwise_def;

extern "C" void inner_conv2d_depthwise(
    const int8_t* input, float* output,
    const int8_t* weight, const float* bias,
    const float* input_scales, const float* weight_scales,
    int N, int C, int H, int W, int H_out, int W_out)
{
    for (int n = 0; n < N; ++n) {
        const int8_t* in_n  = input  + (long)n * C * H * W;
        float*        out_n = output + (long)n * C * H_out * W_out;
        for (int c = 0; c < C; ++c) {
            const int8_t* in_c  = in_n  + (long)c * H * W;
            float*        out_c = out_n + (long)c * H_out * W_out;
            const int8_t* w_c   = weight + (long)c * Kh * Kw;
            const double scale = (double)input_scales[c] * (double)weight_scales[c];
            for (int oh = 0; oh < H_out; ++oh) {
                for (int ow = 0; ow < W_out; ++ow) {
                    int64_t acc = 0;
                    for (int kh = 0; kh < Kh; ++kh) {
                        for (int kw = 0; kw < Kw; ++kw) {
                            int ih = oh * Sh - pad + kh * Dh;
                            int iw = ow * Sw - pad + kw * Dw;
                            if (ih >= 0 && ih < H && iw >= 0 && iw < W)
                                acc += (int64_t)in_c[ih * W + iw] * (int64_t)w_c[kh * Kw + kw];
                        }
                    }
                    double val = (double)acc * scale + (double)bias[c];
                    out_c[oh * W_out + ow] = (float)val;
                }
            }
        }
    }
}