use crate::math::{point::Point, FloatNumber};
#[derive(Debug, Clone, Default, PartialEq)]
pub enum DistanceMetric {
#[default]
Euclidean,
SquaredEuclidean,
}
impl DistanceMetric {
#[inline]
#[must_use]
pub fn measure<T, const N: usize>(&self, point1: &Point<T, N>, point2: &Point<T, N>) -> T
where
T: FloatNumber,
{
match self {
DistanceMetric::Euclidean => square_euclidean(point1, point2).sqrt(),
DistanceMetric::SquaredEuclidean => square_euclidean(point1, point2),
}
}
}
#[inline]
#[must_use]
fn square_euclidean<T, const N: usize>(point1: &Point<T, N>, point2: &Point<T, N>) -> T
where
T: FloatNumber,
{
point1
.iter()
.zip(point2.iter())
.map(|(value1, value2)| (*value1 - *value2).powi(2))
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_euclidean_distance() {
let point1 = [0.0, 1.0];
let point2 = [1.0, 0.0];
let distance = DistanceMetric::Euclidean.measure(&point1, &point2);
assert_eq!(distance, 2.0_f32.sqrt());
}
#[test]
fn test_square_euclidean_distance() {
let point1 = [0.0, 1.0];
let point2 = [1.0, 0.0];
let distance = DistanceMetric::SquaredEuclidean.measure(&point1, &point2);
assert_eq!(distance, 2.0);
}
}