Documentation
use crate::vector::Vector;

pub trait Kernel<X> {
    fn call(&self, x0: &X, x1: &X) -> f64;
}

#[derive(Debug, Clone)]
pub struct GaussianKernel {
    length_scale: f64,
}
impl GaussianKernel {
    pub fn new(length_scale: f64) -> Self {
        assert!(length_scale > 0.0);
        Self { length_scale }
    }
}
impl Kernel<f64> for GaussianKernel {
    fn call(&self, &x0: &f64, &x1: &f64) -> f64 {
        let a = (x0 - x1).powi(2);
        let b = self.length_scale.powi(2);
        (-a / b).exp()
    }
}
impl Kernel<Vector> for GaussianKernel {
    fn call(&self, x0: &Vector, x1: &Vector) -> f64 {
        let a = x0
            .iter()
            .zip(x1.iter())
            .map(|(x0, x1)| (x0 - x1).powi(2))
            .sum::<f64>();
        let b = self.length_scale.powi(2);
        (-a / b).exp()
    }
}