// RLX — versatile ML compiler + runtime.
// Copyright (C) 2026 Eugene Hauptmann, Nataliya Kosmyna.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

// Auto-generated by rlx-cortexm-trainer.
// Weights live in the sibling `model_weights.bin` (RLXM v1 format,
// see trainer/src/blob.rs). This file is just the Rust-visible
// surface: per-tensor static slice references and per-channel mults.
// fp32 test accuracy at training: 0.9700
#![allow(clippy::approx_constant, clippy::excessive_precision)]

#[repr(C, align(4))]
struct AlignedBlob([u8; 6456]);
const ALIGNED: AlignedBlob = AlignedBlob(*include_bytes!("model_weights.bin"));
const BLOB: &[u8] = &ALIGNED.0;

// Each slice into BLOB is at an offset chosen by the encoder so the
// byte boundary is element-aligned (f32 → i32 → i8 region order).

pub static CONV1_W: &[i8] =
    unsafe { core::slice::from_raw_parts(BLOB.as_ptr().add(448) as *const i8, 72) };
pub static CONV1_B: &[i32] =
    unsafe { core::slice::from_raw_parts(BLOB.as_ptr().add(312) as *const i32, 8) };
pub static CONV2_W: &[i8] =
    unsafe { core::slice::from_raw_parts(BLOB.as_ptr().add(520) as *const i8, 1152) };
pub static CONV2_B: &[i32] =
    unsafe { core::slice::from_raw_parts(BLOB.as_ptr().add(344) as *const i32, 16) };
pub static FC_W: &[i8] =
    unsafe { core::slice::from_raw_parts(BLOB.as_ptr().add(1672) as *const i8, 4000) };
pub static FC_B: &[i32] =
    unsafe { core::slice::from_raw_parts(BLOB.as_ptr().add(408) as *const i32, 10) };
pub static CONV1_MULT: &[f32] =
    unsafe { core::slice::from_raw_parts(BLOB.as_ptr().add(176) as *const f32, 8) };
pub static CONV2_MULT: &[f32] =
    unsafe { core::slice::from_raw_parts(BLOB.as_ptr().add(208) as *const f32, 16) };
pub static FC_MULT: &[f32] =
    unsafe { core::slice::from_raw_parts(BLOB.as_ptr().add(272) as *const f32, 10) };

pub const X_SCALE: f32 = 7.874015719e-3;
pub const C1_SCALE: f32 = 3.048744425e-2;
pub const P1_SCALE: f32 = 3.048744425e-2;
pub const C2_SCALE: f32 = 6.619077176e-2;
pub const P2_SCALE: f32 = 6.619077176e-2;
pub const FC_OUT_SCALE: f32 = 1.967357248e-1;

/// Bits per logical weight (8, 4, or 2). Kernel reads each
/// weight via `read_weight(w, idx, WEIGHT_BITS)` which unpacks
/// the byte at the right lane.
pub const WEIGHT_BITS: u8 = 8;

// One MNIST test image (i8, symmetric) for the e2e test.
pub const TEST_LABEL: u8 = 7;
pub static TEST_IMAGE: &[i8] =
    unsafe { core::slice::from_raw_parts(BLOB.as_ptr().add(5672) as *const i8, 784) };
