1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
//! Define trait for vectors

use std::iter::Sum;
use ndarray::{LinalgScalar, ArrayBase, Data, Dimension};
use num_traits::float::Float;

/// Methods for vectors
pub trait Vector {
    type Scalar;
    /// rename of norm_l2
    fn norm(&self) -> Self::Scalar {
        self.norm_l2()
    }
    /// L-1 norm
    fn norm_l1(&self) -> Self::Scalar;
    /// L-2 norm
    fn norm_l2(&self) -> Self::Scalar;
    /// maximum norm
    fn norm_max(&self) -> Self::Scalar;
}

impl<A, S, D, T> Vector for ArrayBase<S, D>
    where A: LinalgScalar + Squared<Output = T>,
          T: Float + Sum,
          S: Data<Elem = A>,
          D: Dimension
{
    type Scalar = T;
    fn norm_l1(&self) -> Self::Scalar {
        self.iter().map(|x| x.sq_abs()).sum()
    }
    fn norm_l2(&self) -> Self::Scalar {
        self.iter().map(|x| x.squared()).sum::<T>().sqrt()
    }
    fn norm_max(&self) -> Self::Scalar {
        self.iter().fold(T::zero(), |f, &val| {
            let v = val.sq_abs();
            if f > v { f } else { v }
        })
    }
}

pub trait Squared {
    type Output;
    fn squared(&self) -> Self::Output;
    fn sq_abs(&self) -> Self::Output;
}

impl<A: Float> Squared for A {
    type Output = A;
    fn squared(&self) -> A {
        *self * *self
    }
    fn sq_abs(&self) -> A {
        self.abs()
    }
}