kodama 0.3.0

Agglomerative hierarchical clustering.
Documentation
use crate::float::Float;

#[inline]
pub fn single<T: Float>(a: T, b: &mut T) {
    if a < *b {
        *b = a;
    }
}

#[inline]
pub fn complete<T: Float>(a: T, b: &mut T) {
    if a > *b {
        *b = a;
    }
}

#[inline]
pub fn average<T: Float>(a: T, b: &mut T, size_a: usize, size_b: usize) {
    let size_a = T::from_usize(size_a);
    let size_b = T::from_usize(size_b);
    *b = (size_a * a + size_b * *b) / (size_a + size_b);
}

#[inline]
pub fn weighted<T: Float>(a: T, b: &mut T) {
    *b = T::from_float(0.5) * (a + *b);
}

#[inline]
pub fn ward<T: Float>(
    a: T,
    b: &mut T,
    merged_dist: T,
    size_a: usize,
    size_b: usize,
    size_x: usize,
) {
    let size_a = T::from_usize(size_a);
    let size_b = T::from_usize(size_b);
    let size_x = T::from_usize(size_x);

    let numerator = ((size_x + size_a) * a) + ((size_x + size_b) * *b)
        - (size_x * merged_dist);
    let denom = size_a + size_b + size_x;
    *b = numerator / denom;
}

#[inline]
pub fn centroid<T: Float>(
    a: T,
    b: &mut T,
    merged_dist: T,
    size_a: usize,
    size_b: usize,
) {
    let size_a = T::from_usize(size_a);
    let size_b = T::from_usize(size_b);
    let size_ab = size_a + size_b;

    *b = (((size_a * a) + (size_b * *b)) / size_ab)
        - ((size_a * size_b * merged_dist) / (size_ab * size_ab));
}

#[inline]
pub fn median<T: Float>(a: T, b: &mut T, merged_dist: T) {
    let half = T::from_float(0.5);
    let quarter = T::from_float(0.25);

    *b = (half * (a + *b)) - (merged_dist * quarter);
}