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