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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//! Defines linear algebra traits used for some model parameters

/// Vector whose dimension is known at runtime
///
/// Assumes the `Vector` is represented as a tuple of numbers representing its projection along
/// orthogonal base vectors
pub trait Vector: Clone {
    /// Retuns a new instance of Vector with all elements set to zero
    ///
    /// Not every possible implementation knows its dimension at compiletime, therefore a size hint
    /// is necessary to allocate the correct number of elements
    fn zero_from_dimension(dimension: usize) -> Self;
    /// Maximum allowed index for `at` and `at_mut`
    fn dimension(&self) -> usize;
    /// Length of projection along `i`-th base
    fn at(&self, i: usize) -> f64;
    /// Mutable access to length of projection along `i`-th base
    fn at_mut(&mut self, i: usize) -> &mut f64;
    /// Scalar product
    ///
    /// Default implementation using `at` and `dimension` is provided
    fn dot(&self, other: &Self) -> f64 {
        debug_assert_eq!(self.dimension(), other.dimension());
        let mut result = 0.0;
        for i in 0..self.dimension() {
            result += self.at(i) * other.at(i)
        }
        result
    }
}

/// Vector with dimension known at compile time
pub trait FixDimension {
    /// Retuns a new instance of Vector with all elements set to zero
    fn zero() -> Self;
}

impl Vector for f64 {
    fn zero_from_dimension(dimension: usize) -> f64 {
        assert!(dimension == 1);
        0.0
    }

    fn dimension(&self) -> usize {
        1
    }
    fn at(&self, i: usize) -> f64 {
        assert!(i == 0);
        *self
    }
    fn at_mut(&mut self, i: usize) -> &mut f64 {
        assert!(i == 0);
        self
    }

    fn dot(&self, other: &Self) -> f64 {
        self * other
    }
}

impl FixDimension for f64 {
    fn zero() -> Self {
        0.
    }
}

impl Vector for Vec<f64> {
    fn zero_from_dimension(dimension: usize) -> Vec<f64> {
        vec![0.; dimension]
    }

    fn dimension(&self) -> usize {
        self.len()
    }

    fn at(&self, index: usize) -> f64 {
        self[index]
    }

    fn at_mut(&mut self, index: usize) -> &mut f64 {
        &mut self[index]
    }
}

macro_rules! vec_impl_for_array {
    ($v:expr) => {
        impl Vector for [f64; $v] {
            fn zero_from_dimension(dimension: usize) -> [f64; $v] {
                assert!(dimension == $v);
                [0.0; $v]
            }

            fn dimension(&self) -> usize {
                $v
            }

            fn at(&self, index: usize) -> f64 {
                self[index]
            }

            fn at_mut(&mut self, index: usize) -> &mut f64 {
                &mut self[index]
            }
        }

        impl FixDimension for [f64; $v] {
            fn zero() -> Self {
                [0.0; $v]
            }
        }
    };
}

vec_impl_for_array! { 1 }
vec_impl_for_array! { 2 }
vec_impl_for_array! { 3 }
vec_impl_for_array! { 4 }
vec_impl_for_array! { 5 }
vec_impl_for_array! { 6 }
vec_impl_for_array! { 7 }
vec_impl_for_array! { 8 }
vec_impl_for_array! { 9 }
vec_impl_for_array! { 10 }
vec_impl_for_array! { 11 }
vec_impl_for_array! { 12 }
vec_impl_for_array! { 13 }
vec_impl_for_array! { 14 }
vec_impl_for_array! { 15 }
vec_impl_for_array! { 16 }
vec_impl_for_array! { 17 }
vec_impl_for_array! { 18 }
vec_impl_for_array! { 19 }
vec_impl_for_array! { 20 }
vec_impl_for_array! { 21 }
vec_impl_for_array! { 22 }
vec_impl_for_array! { 23 }
vec_impl_for_array! { 24 }
vec_impl_for_array! { 25 }
vec_impl_for_array! { 26 }
vec_impl_for_array! { 27 }
vec_impl_for_array! { 28 }
vec_impl_for_array! { 29 }
vec_impl_for_array! { 30 }
vec_impl_for_array! { 31 }
vec_impl_for_array! { 32 }

#[cfg(test)]
mod tests {

    #[test]
    fn dot() {
        use crate::linear_algebra::Vector;

        let a = [1.0, 2.0];
        let b = [3.0, 4.0];

        assert_eq!(11.0, a.dot(&b))
    }
}