// File: kernel.cpp
// Reference-scalar gemm bf16 (fc-style: C = A @ B^T, fp32 accumulate/output).
// LLM target: replace this file with an optimised inner_gemm.
// All per-definition constants live in gemm_def:: (gemm.h).
#include "gemm.h"
#include <cstring>
using namespace gemm_def;

namespace {
// bf16 shares fp32's exponent field, so widening is an exact bit-shift — no
// rounding/subnormal handling needed (unlike fp16->fp32).
inline float bf16_to_f32(uint16_t bits) {
    uint32_t b = (uint32_t)bits << 16;
    float f;
    std::memcpy(&f, &b, sizeof(f));
    return f;
}
} // namespace

extern "C" void inner_gemm(const uint16_t* A, float* output, const uint16_t* B, int M)
{
    for (int m = 0; m < M; ++m) {
        const uint16_t* a_row = A + (long)m * K;
        float*          out_row = output + (long)m * N;
        for (int n = 0; n < N; ++n) {
            const uint16_t* b_row = B + (long)n * K;
            float sum = 0.0f;
            for (int k = 0; k < K; ++k) {
                sum += bf16_to_f32(a_row[k]) * bf16_to_f32(b_row[k]);
            }
            out_row[n] = sum;
        }
    }
}