use super::MetricElem; use serde::{Deserialize, Serialize}; pub trait VecMetric: MetricElem + From> {} #[derive(Deserialize, Serialize)] pub struct CosineSimilarity(pub Vec); #[derive(Deserialize, Serialize)] pub struct EuclidianDistance(pub Vec); #[derive(Deserialize, Serialize)] pub struct ManhattenDistance(pub Vec); impl VecMetric for CosineSimilarity {} impl VecMetric for EuclidianDistance {} impl VecMetric for ManhattenDistance {} #[rustfmt::skip] impl From> for CosineSimilarity { fn from(value: Vec) -> Self { Self(value) } } #[rustfmt::skip] impl From> for EuclidianDistance { fn from(value: Vec) -> Self { Self(value) } } #[rustfmt::skip] impl From> for ManhattenDistance { fn from(value: Vec) -> Self { Self(value) } } impl MetricElem for CosineSimilarity { fn dist(&self, other: &Self) -> f64 { let x = self .0 .iter() .zip(other.0.iter()) .map(|(a, b)| *a * *b) .sum::(); let mag_a = self.0.iter().map(|x| x.powi(2)).sum::(); let mag_b = other.0.iter().map(|x| x.powi(2)).sum::(); (x / (mag_a * mag_b).sqrt()) as f64 } } impl MetricElem for EuclidianDistance { fn dist(&self, other: &Self) -> f64 { self.0 .iter() .zip(other.0.iter()) .map(|(a, b)| (a - b).powf(2.)) .sum::() .sqrt() as f64 } } impl MetricElem for ManhattenDistance { fn dist(&self, other: &Self) -> f64 { self.0 .iter() .zip(other.0.iter()) .map(|(a, b)| (a - b).abs()) .sum::() as f64 } }