mod simd;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub enum Distance {
Cosine,
Euclidean,
DotProduct,
Manhattan,
}
impl Distance {
#[inline]
pub fn calculate(&self, a: &[f32], b: &[f32]) -> f32 {
match self {
Distance::Cosine => simd::cosine_distance(a, b),
Distance::Euclidean => simd::euclidean_distance(a, b),
Distance::DotProduct => simd::dot_product_distance(a, b),
Distance::Manhattan => simd::manhattan_distance(a, b),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cosine_identical_vectors() {
let a = vec![1.0, 2.0, 3.0];
let b = vec![1.0, 2.0, 3.0];
let dist = Distance::Cosine.calculate(&a, &b);
assert!((dist - 0.0).abs() < 1e-6);
}
#[test]
fn test_cosine_orthogonal_vectors() {
let a = vec![1.0, 0.0];
let b = vec![0.0, 1.0];
let dist = Distance::Cosine.calculate(&a, &b);
assert!((dist - 1.0).abs() < 1e-6);
}
#[test]
fn test_euclidean_identical_vectors() {
let a = vec![1.0, 2.0, 3.0];
let b = vec![1.0, 2.0, 3.0];
let dist = Distance::Euclidean.calculate(&a, &b);
assert!((dist - 0.0).abs() < 1e-6);
}
#[test]
fn test_euclidean_known_distance() {
let a = vec![0.0, 0.0];
let b = vec![3.0, 4.0];
let dist = Distance::Euclidean.calculate(&a, &b);
assert!((dist - 5.0).abs() < 1e-6);
}
#[test]
fn test_manhattan_identical_vectors() {
let a = vec![1.0, 2.0, 3.0];
let b = vec![1.0, 2.0, 3.0];
let dist = Distance::Manhattan.calculate(&a, &b);
assert!((dist - 0.0).abs() < 1e-6);
}
#[test]
fn test_manhattan_known_distance() {
let a = vec![0.0, 0.0];
let b = vec![3.0, 4.0];
let dist = Distance::Manhattan.calculate(&a, &b);
assert!((dist - 7.0).abs() < 1e-6); }
#[test]
fn test_dot_product() {
let a = vec![1.0, 2.0, 3.0];
let b = vec![4.0, 5.0, 6.0];
let dist = Distance::DotProduct.calculate(&a, &b);
assert!((dist - (-32.0)).abs() < 1e-6);
}
}