vikos/
linear_algebra.rs

1//! Defines linear algebra traits used for some model parameters
2
3/// Vector whose dimension is known at runtime
4///
5/// Assumes the `Vector` is represented as a tuple of numbers representing its projection along
6/// orthogonal base vectors
7pub trait Vector: Clone {
8    /// Retuns a new instance of Vector with all elements set to zero
9    ///
10    /// Not every possible implementation knows its dimension at compiletime, therefore a size hint
11    /// is necessary to allocate the correct number of elements
12    fn zero_from_dimension(dimension: usize) -> Self;
13    /// Maximum allowed index for `at` and `at_mut`
14    fn dimension(&self) -> usize;
15    /// Length of projection along `i`-th base
16    fn at(&self, i: usize) -> f64;
17    /// Mutable access to length of projection along `i`-th base
18    fn at_mut(&mut self, i: usize) -> &mut f64;
19    /// Scalar product
20    ///
21    /// Default implementation using `at` and `dimension` is provided
22    fn dot(&self, other: &Self) -> f64 {
23        debug_assert_eq!(self.dimension(), other.dimension());
24        let mut result = 0.0;
25        for i in 0..self.dimension() {
26            result += self.at(i) * other.at(i)
27        }
28        result
29    }
30}
31
32/// Vector with dimension known at compile time
33pub trait FixDimension {
34    /// Retuns a new instance of Vector with all elements set to zero
35    fn zero() -> Self;
36}
37
38impl Vector for f64 {
39    fn zero_from_dimension(dimension: usize) -> f64 {
40        assert!(dimension == 1);
41        0.0
42    }
43
44    fn dimension(&self) -> usize {
45        1
46    }
47    fn at(&self, i: usize) -> f64 {
48        assert!(i == 0);
49        *self
50    }
51    fn at_mut(&mut self, i: usize) -> &mut f64 {
52        assert!(i == 0);
53        self
54    }
55
56    fn dot(&self, other: &Self) -> f64 {
57        self * other
58    }
59}
60
61impl FixDimension for f64 {
62    fn zero() -> Self {
63        0.
64    }
65}
66
67impl Vector for Vec<f64> {
68    fn zero_from_dimension(dimension: usize) -> Vec<f64> {
69        vec![0.; dimension]
70    }
71
72    fn dimension(&self) -> usize {
73        self.len()
74    }
75
76    fn at(&self, index: usize) -> f64 {
77        self[index]
78    }
79
80    fn at_mut(&mut self, index: usize) -> &mut f64 {
81        &mut self[index]
82    }
83}
84
85macro_rules! vec_impl_for_array {
86    ($v:expr) => {
87        impl Vector for [f64; $v] {
88            fn zero_from_dimension(dimension: usize) -> [f64; $v] {
89                assert!(dimension == $v);
90                [0.0; $v]
91            }
92
93            fn dimension(&self) -> usize {
94                $v
95            }
96
97            fn at(&self, index: usize) -> f64 {
98                self[index]
99            }
100
101            fn at_mut(&mut self, index: usize) -> &mut f64 {
102                &mut self[index]
103            }
104        }
105
106        impl FixDimension for [f64; $v] {
107            fn zero() -> Self {
108                [0.0; $v]
109            }
110        }
111    };
112}
113
114vec_impl_for_array! { 1 }
115vec_impl_for_array! { 2 }
116vec_impl_for_array! { 3 }
117vec_impl_for_array! { 4 }
118vec_impl_for_array! { 5 }
119vec_impl_for_array! { 6 }
120vec_impl_for_array! { 7 }
121vec_impl_for_array! { 8 }
122vec_impl_for_array! { 9 }
123vec_impl_for_array! { 10 }
124vec_impl_for_array! { 11 }
125vec_impl_for_array! { 12 }
126vec_impl_for_array! { 13 }
127vec_impl_for_array! { 14 }
128vec_impl_for_array! { 15 }
129vec_impl_for_array! { 16 }
130vec_impl_for_array! { 17 }
131vec_impl_for_array! { 18 }
132vec_impl_for_array! { 19 }
133vec_impl_for_array! { 20 }
134vec_impl_for_array! { 21 }
135vec_impl_for_array! { 22 }
136vec_impl_for_array! { 23 }
137vec_impl_for_array! { 24 }
138vec_impl_for_array! { 25 }
139vec_impl_for_array! { 26 }
140vec_impl_for_array! { 27 }
141vec_impl_for_array! { 28 }
142vec_impl_for_array! { 29 }
143vec_impl_for_array! { 30 }
144vec_impl_for_array! { 31 }
145vec_impl_for_array! { 32 }
146
147#[cfg(test)]
148mod tests {
149
150    #[test]
151    fn dot() {
152        use crate::linear_algebra::Vector;
153
154        let a = [1.0, 2.0];
155        let b = [3.0, 4.0];
156
157        assert_eq!(11.0, a.dot(&b))
158    }
159}