abd-clam 0.11.1

Clustered Learning of Approximate Manifolds
Documentation
use std::f32::EPSILON;

#[allow(clippy::type_complexity)]
pub const METRICS: [(&str, fn(&[f32], &[f32]) -> f32); 4] = [
    ("euclidean", euclidean),
    ("euclidean_sq", euclidean_sq),
    ("manhattan", manhattan),
    ("cosine", cosine),
];

#[inline(always)]
pub fn euclidean(x: &[f32], y: &[f32]) -> f32 {
    euclidean_sq(x, y).sqrt()
}

#[inline(always)]
pub fn euclidean_sq(x: &[f32], y: &[f32]) -> f32 {
    x.iter().zip(y.iter()).map(|(&a, &b)| (a - b).powi(2)).sum()
}

#[inline(always)]
pub fn manhattan(x: &[f32], y: &[f32]) -> f32 {
    x.iter().zip(y.iter()).map(|(&a, &b)| (a - b).abs()).sum()
}

#[inline(always)]
pub fn cosine(x: &[f32], y: &[f32]) -> f32 {
    let [xx, yy, xy] = x
        .iter()
        .zip(y.iter())
        .fold([0.; 3], |[xx, yy, xy], (&a, &b)| [xx + a * a, yy + b * b, xy + a * b]);

    if xx <= EPSILON || yy <= EPSILON || xy <= EPSILON {
        1.
    } else {
        let d = 1. - xy / (xx * yy).sqrt();
        if d < EPSILON {
            0.
        } else {
            d
        }
    }
}