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

// Harness contract for the llama.cpp (ggml) moe baseline.
// Called by armbench_entry_moe (binding.cpp); implemented by kernel.cpp.
// SwiGLU MoE with softmax-then-top-k routing and normalized top-k weights:
//   probs = softmax(hidden @ router^T); top-k experts; w /= sum(w)
//   out   = sum_k w_k * down_e @ (silu(gate_e @ x) * (up_e @ x))
// hidden_states is row-major [T, n_embd] bf16 (raw bit pattern -- NOT
// quantized; weight-only Q4_K design). router_weight is fp32
// [n_expert, n_embd] (also not quantized -- routing decisions are
// categorical and must not flip from quantization rounding). gate_proj/
// up_proj [n_expert, n_ff, n_embd] and down_proj [n_expert, n_embd, n_ff]
// are ggml block_q4_K rows over their last axis (144-byte blocks, repacked
// by the Python adapter). out fp32 [T, n_embd].
int armbench_llamacpp_moe(const void* hidden_states, const float* router_weight,
                          const void* gate_proj, const void* up_proj,
                          const void* down_proj, float* out,
                          int64_t n_tokens, int64_t n_embd, int64_t n_ff,
                          int64_t n_expert, int64_t n_expert_used);