use super::projection::{Projection, ProjectionId};
const EXPERT_BYTES: usize = 3 * 4;
#[derive(Debug, Clone, Copy)]
pub struct ExpertProjection {
pub intent: f32,
pub activation: f32,
pub gate: f32,
}
impl Default for ExpertProjection {
fn default() -> Self {
Self {
intent: 0.0,
activation: 0.0,
gate: 1.0, }
}
}
impl Projection for ExpertProjection {
fn byte_size() -> usize {
EXPERT_BYTES
}
fn id() -> ProjectionId {
ProjectionId::Expert
}
fn read(buf: &[u8]) -> Self {
assert!(buf.len() >= EXPERT_BYTES);
Self {
intent: f32::from_le_bytes([buf[0], buf[1], buf[2], buf[3]]),
activation: f32::from_le_bytes([buf[4], buf[5], buf[6], buf[7]]),
gate: f32::from_le_bytes([buf[8], buf[9], buf[10], buf[11]]),
}
}
fn write(&self, buf: &mut [u8]) {
assert!(buf.len() >= EXPERT_BYTES);
buf[0..4].copy_from_slice(&self.intent.to_le_bytes());
buf[4..8].copy_from_slice(&self.activation.to_le_bytes());
buf[8..12].copy_from_slice(&self.gate.to_le_bytes());
}
fn shape_hash_contribution(&self) -> u32 {
let mut hash = 0x811c_9dc5u32;
for byte in self.activation.to_bits().to_le_bytes() {
hash ^= byte as u32;
hash = hash.wrapping_mul(0x0100_0193);
}
hash
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_expert_roundtrip() {
let proj = ExpertProjection {
intent: 0.8,
activation: 0.6,
gate: 0.5,
};
let mut buf = vec![0u8; ExpertProjection::byte_size()];
proj.write(&mut buf);
let restored = ExpertProjection::read(&buf);
assert!((restored.intent - 0.8).abs() < 1e-6);
assert!((restored.activation - 0.6).abs() < 1e-6);
assert!((restored.gate - 0.5).abs() < 1e-6);
}
}