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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use crate::structure::matrix::Matrix;

/// Mathematical Vector
///
/// # Description
/// Vector has two operations : addition, scalar multiplication.
/// And a space of the vector should closed for that operations.
pub trait Vector {
    type Scalar;
    fn add_vec(&self, rhs: &Self) -> Self;
    fn sub_vec(&self, rhs: &Self) -> Self;
    fn mul_scalar(&self, rhs: Self::Scalar) -> Self;
}

/// Kinds of Vector & Matrix norm
///
/// # Kinds of Vector norm
/// * `l1`
/// * `l2`
/// * `lp`
/// * `lInf`
///
/// # Kinds of Matrix norm
/// * `F`: Frobenius norm
/// * `lpq`: Element-wise pq norm
#[derive(Debug, Copy, Clone)]
pub enum Norm {
    L1,
    L2,
    Lp(f64),
    LInf,
    F,
    Lpq(f64, f64),
}

/// Normed Vector
pub trait Normed: Vector {
    type UnsignedScalar;
    fn norm(&self, kind: Norm) -> Self::UnsignedScalar;
    fn normalize(&self, kind: Norm) -> Self
    where
        Self: Sized;
}

/// Inner product Vector
pub trait InnerProduct: Normed {
    fn dot(&self, rhs: &Self) -> Self::Scalar;
}

/// Linear operation for Vector
pub trait LinearOp<T: Vector, S: Vector> {
    fn apply(&self, rhs: &T) -> S;
}

/// Vector Products
pub trait VectorProduct: Vector {
    fn cross(&self, other: &Self) -> Self;
    fn outer(&self, other: &Self) -> Matrix;
}

/// Matrix Products
pub trait MatrixProduct {
    fn kronecker(&self, other: &Self) -> Self;
    fn hadamard(&self, other: &Self) -> Self;
}

// =============================================================================
// Implementation for primitive types
// =============================================================================

impl Vector for f64 {
    type Scalar = Self;

    fn add_vec(&self, rhs: &Self) -> Self {
        self + rhs
    }

    fn sub_vec(&self, rhs: &Self) -> Self {
        self - rhs
    }

    fn mul_scalar(&self, rhs: Self::Scalar) -> Self {
        self * rhs
    }
}

impl Normed for f64 {
    type UnsignedScalar = f64;
    fn norm(&self, _kind: Norm) -> Self::Scalar {
        self.abs()
    }

    fn normalize(&self, _kind: Norm) -> Self
    where
        Self: Sized,
    {
        self / self.abs()
    }
}

// =============================================================================
// Implementation for parallel traits
// =============================================================================

/// Mathematical Vector in Parallel
#[cfg(feature = "parallel")]
pub trait ParallelVector {
    type Scalar;
    fn par_add_vec(&self, rhs: &Self) -> Self;
    fn par_sub_vec(&self, rhs: &Self) -> Self;
    fn par_mul_scalar(&self, rhs: Self::Scalar) -> Self;
}

/// Normed Vector in Parallel
#[cfg(feature = "parallel")]
pub trait ParallelNormed: Vector {
    type UnsignedScalar;
    fn par_norm(&self, kind: Norm) -> Self::UnsignedScalar;
}

/// Inner product Vector in Parallel
#[cfg(feature = "parallel")]
pub trait ParallelInnerProduct: ParallelNormed {
    fn par_dot(&self, rhs: &Self) -> Self::Scalar;
}

/// Matrix Products in Parallel
#[cfg(feature = "parallel")]
pub trait ParallelMatrixProduct {
    fn par_hadamard(&self, other: &Self) -> Self;
}

/// Vector Products in Parallel
#[cfg(feature = "parallel")]
pub trait ParallelVectorProduct: Vector {
    fn par_cross(&self, other: &Self) -> Self;
}