abd-clam 0.11.1

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

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

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

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

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

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

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