Skip to main content

conspire/math/tensor/norm/
mod.rs

1#[cfg(test)]
2mod test;
3
4use super::{Quantity, Scalar, Tensor};
5
6/// Different norms for tensors.
7#[derive(Clone, Copy, Debug, Default)]
8pub enum Norm {
9    Chebyshev,
10    #[default]
11    Euclidean,
12    Manhattan,
13    Minkowski(Scalar),
14}
15
16impl Norm {
17    /// The norm of a whole tensor with units.
18    pub fn apply<T: Tensor>(&self, t: &T) -> Quantity<T::Unit> {
19        match self {
20            Self::Chebyshev => t.norm_inf(),
21            Self::Euclidean => t.norm(),
22            Self::Manhattan => t.norm_l1(),
23            Self::Minkowski(p) => t.norm_p(*p),
24        }
25    }
26    /// The norm of a whole tensor as a number.
27    pub fn measure<T: Tensor>(&self, t: &T) -> Scalar {
28        self.apply(t).value()
29    }
30    /// The norm of some values of a tensor.
31    pub fn over(&self, values: impl Iterator<Item = Scalar>) -> Scalar {
32        match self {
33            Self::Chebyshev => values.fold(0.0, |largest: Scalar, value| largest.max(value.abs())),
34            Self::Euclidean => values.map(|value| value * value).sum::<Scalar>().sqrt(),
35            Self::Manhattan => values.map(|value| value.abs()).sum(),
36            Self::Minkowski(p) => values
37                .map(|value| value.abs().powf(*p))
38                .sum::<Scalar>()
39                .powf(1.0 / p),
40        }
41    }
42}