#[cfg(test)]
mod test;
use super::{Quantity, Scalar, Tensor};
#[derive(Clone, Copy, Debug, Default)]
pub enum Norm {
Chebyshev,
#[default]
Euclidean,
Manhattan,
Minkowski(Scalar),
}
impl Norm {
pub fn apply<T: Tensor>(&self, t: &T) -> Quantity<T::Unit> {
match self {
Self::Chebyshev => t.norm_inf(),
Self::Euclidean => t.norm(),
Self::Manhattan => t.norm_l1(),
Self::Minkowski(p) => t.norm_p(*p),
}
}
pub fn measure<T: Tensor>(&self, t: &T) -> Scalar {
self.apply(t).value()
}
pub fn over(&self, values: impl Iterator<Item = Scalar>) -> Scalar {
match self {
Self::Chebyshev => values.fold(0.0, |largest: Scalar, value| largest.max(value.abs())),
Self::Euclidean => values.map(|value| value * value).sum::<Scalar>().sqrt(),
Self::Manhattan => values.map(|value| value.abs()).sum(),
Self::Minkowski(p) => values
.map(|value| value.abs().powf(*p))
.sum::<Scalar>()
.powf(1.0 / p),
}
}
}