use crate::ops::blas::{matvec_forward, sgemm_forward};
#[inline]
pub fn embed_lookup(embed: &[f32], token_id: u32, d_model: usize, vocab_size: usize) -> &[f32] {
let id = token_id as usize;
assert!(
id < vocab_size,
"token_id {id} out of range (vocab_size={vocab_size})"
);
&embed[id * d_model..(id + 1) * d_model]
}
pub fn lm_head_logits(
logits: &mut [f32],
hidden: &[f32],
embed: &[f32],
vocab_size: usize,
vocab_size_padded: usize,
d_model: usize,
scratch: &mut [f32],
) {
debug_assert!(scratch.len() >= vocab_size_padded);
sgemm_forward(
&mut scratch[..vocab_size_padded],
embed,
hidden,
None,
vocab_size_padded,
d_model,
1,
);
logits[..vocab_size].copy_from_slice(&scratch[..vocab_size]);
}
pub fn lm_head_logits_untied(
logits: &mut [f32],
hidden: &[f32],
lm_head_w: &[f32],
vocab_size: usize,
d_model: usize,
) {
matvec_forward(logits, hidden, lm_head_w, None, d_model, vocab_size);
}