use crate::config::FfnActivation;
use crate::ops::{gelu, sigmoid};
use crate::quant::QuantizedWeight;
use alloc::vec;
pub struct FfnWeights {
pub gate_proj: QuantizedWeight, pub up_proj: QuantizedWeight, pub down_proj: QuantizedWeight, }
pub fn ffn_forward(
x: &[f32],
out: &mut [f32],
w: &FfnWeights,
d_ff: usize,
activation: &FfnActivation,
) {
debug_assert_eq!(out.len(), x.len());
let mut gate = vec![0.0f32; d_ff];
let mut up = vec![0.0f32; d_ff];
w.gate_proj.matvec(x, &mut gate);
w.up_proj.matvec(x, &mut up);
match activation {
FfnActivation::SwiGLU => {
for (g, u) in gate.iter_mut().zip(up.iter()) {
*g = *g * sigmoid(*g) * u;
}
}
FfnActivation::GeGLU => {
for (g, u) in gate.iter_mut().zip(up.iter()) {
*g = gelu(*g) * u;
}
}
FfnActivation::DRelu => {
for (g, u) in gate.iter_mut().zip(up.iter()) {
let rg = if *g > 0.0 { *g } else { 0.0 };
let ru = if *u > 0.0 { *u } else { 0.0 };
*g = rg * ru;
}
}
}
w.down_proj.matvec(&gate, out);
}