// File: conv2d.h
#pragma once
#include <cstdint>

// Per-definition constants for this conv2d w8a8ch (int8) specialisation.
// input_scale is a per-definition-constant dequant scalar (constant across every
// workload — checked at generation time); weight_scales is a genuine runtime
// per-output-channel tensor, passed as a regular float pointer below.
namespace conv2d_def {
constexpr int Kh       = 3;
constexpr int Kw       = 3;
constexpr int Sh       = 2;
constexpr int Sw       = 2;
constexpr int Dh       = 1;
constexpr int Dw       = 1;
constexpr int pad_top  = 1;
constexpr int pad_left = 1;
constexpr float input_scale = 0.01686;
} // namespace conv2d_def

#ifdef __cplusplus
extern "C" {
#endif
// LLM target: implement this in kernel.cpp.
// N, C_in, H, W, C_out are var dims; H_out/W_out are pre-computed by the binding harness.
// Input layout: (N, C_in, H, W); weight layout: (C_out, C_in, Kh, Kw); output layout: (N, C_out, H_out, W_out).
// Dequantization: real = int8_value * scale, where scale = input_scale * weight_scales[c_out]
// (NOT ncnn's quantization convention int8 = round(real * scale) — these are dequant multipliers).
void inner_conv2d(
    const int8_t* input, float* output,
    const int8_t* weight, const float* bias, const float* weight_scales,
    int N, int C_in, int H, int W, int C_out, int H_out, int W_out);
#ifdef __cplusplus
}
#endif