1use ndarray::*;
4use num_traits::Zero;
5
6use super::types::*;
7
8pub trait Norm {
12 type Output;
13 fn norm(&self) -> Self::Output {
15 self.norm_l2()
16 }
17 fn norm_l1(&self) -> Self::Output;
19 fn norm_l2(&self) -> Self::Output;
21 fn norm_max(&self) -> Self::Output;
23}
24
25impl<A, S, D> Norm for ArrayBase<S, D>
26where
27 A: Scalar + Lapack,
28 S: Data<Elem = A>,
29 D: Dimension,
30{
31 type Output = A::Real;
32 fn norm_l1(&self) -> Self::Output {
33 self.iter().map(|x| x.abs()).sum()
34 }
35 fn norm_l2(&self) -> Self::Output {
36 self.iter().map(|x| x.square()).sum::<A::Real>().sqrt()
37 }
38 fn norm_max(&self) -> Self::Output {
39 self.iter().fold(A::Real::zero(), |f, &val| {
40 let v = val.abs();
41 if f > v {
42 f
43 } else {
44 v
45 }
46 })
47 }
48}
49
50pub enum NormalizeAxis {
51 Row = 0,
52 Column = 1,
53}
54
55pub fn normalize<A, S>(
57 mut m: ArrayBase<S, Ix2>,
58 axis: NormalizeAxis,
59) -> (ArrayBase<S, Ix2>, Vec<A::Real>)
60where
61 A: Scalar + Lapack,
62 S: DataMut<Elem = A>,
63{
64 let mut ms = Vec::new();
65 for mut v in m.axis_iter_mut(Axis(axis as usize)) {
66 let n = v.norm();
67 ms.push(n);
68 v.map_inplace(|x| *x /= A::from_real(n))
69 }
70 (m, ms)
71}