pub trait Distance: Send + Sync + 'static {
fn distance(&self, a: &[f32], b: &[f32]) -> f32;
}
#[derive(Clone, Copy, Debug, Default)]
pub struct SquaredEuclidean;
impl Distance for SquaredEuclidean {
#[inline]
fn distance(&self, a: &[f32], b: &[f32]) -> f32 {
a.iter()
.zip(b.iter())
.map(|(x, y)| (x - y) * (x - y))
.sum()
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Euclidean;
impl Distance for Euclidean {
#[inline]
fn distance(&self, a: &[f32], b: &[f32]) -> f32 {
a.iter()
.zip(b.iter())
.map(|(x, y)| (x - y) * (x - y))
.sum::<f32>()
.sqrt()
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Cosine;
impl Distance for Cosine {
#[inline]
fn distance(&self, a: &[f32], b: &[f32]) -> f32 {
let dot: f32 = a.iter().zip(b.iter()).map(|(x, y)| x * y).sum();
let na: f32 = a.iter().map(|x| x * x).sum::<f32>().sqrt();
let nb: f32 = b.iter().map(|x| x * x).sum::<f32>().sqrt();
if na == 0.0 || nb == 0.0 {
return 1.0;
}
let cos = (dot / (na * nb)).clamp(-1.0, 1.0);
1.0 - cos
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct DotProduct;
impl Distance for DotProduct {
#[inline]
fn distance(&self, a: &[f32], b: &[f32]) -> f32 {
let dot: f32 = a.iter().zip(b.iter()).map(|(x, y)| x * y).sum();
1.0 - dot
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Manhattan;
impl Distance for Manhattan {
#[inline]
fn distance(&self, a: &[f32], b: &[f32]) -> f32 {
a.iter().zip(b.iter()).map(|(x, y)| (x - y).abs()).sum()
}
}