rust_numpy/
matrix.rs

1use std::slice::Iter;
2use crate::Dot;
3use crate::vector::Vector;
4use crate::Init;
5
6
7use impl_ops::*;
8use std::ops;
9
10pub struct Matrix {
11    array : Vec<Vec<f64>>,
12    m : usize, // number of lines
13    n : usize, // number of colomns
14}
15
16
17impl Matrix {
18
19    pub fn from(matrix: Vec<Vec<f64>>) -> Matrix {
20        Matrix {
21            m : matrix.len(),
22            n : matrix[0].len(),
23            array : matrix,
24        }
25    }
26
27    #[inline]
28    pub fn n(&self) -> usize {
29        self.n
30    }
31
32    #[inline]
33    pub fn m(&self) -> usize {
34        self.m
35    }
36
37    pub fn is_square(&self) -> bool {
38        self.n == self.m
39    }
40
41    pub fn transpose(&self) -> Matrix {
42        let mut tr = Self::zeros(
43            (self.n, self.m)
44        );
45        for i in 0..self.m {
46            for j in 0..self.n {
47                (&mut tr.array[j])[i] = (& self.array[i])[j];
48            }
49        }
50        return tr;
51    }
52
53    // FIX: moves lines
54    pub fn iter(&self) -> Iter<'_, Vec<f64>> {
55        self.array.iter()
56    }
57
58//    /// debug
59//    fn show_matrices(matrix1: &Matrix, matrix2: &Matrix) {
60//        for (line1, line2) in matrix1.iter().zip(matrix2.iter()) {
61//            for x in line1 {
62//                print!("{x:5.2} ");
63//            }
64//            print!("| ");
65//            for y in line2 {
66//                print!("{y:5.2} ");
67//            }
68//            println!();
69//        }
70//        println!();
71//    }
72
73    pub fn inv(&self) -> Matrix {
74        assert!(self.is_square());
75        let n = self.n;
76
77        // mutable copy of original matrix
78        let mut original = self.clone();
79        // mutable container for inverted matrix
80        let mut inv = Matrix::diagonal(
81            Vector::ones(self.m)
82        );
83
84        // forward way
85        for k in 0..n {
86
87            // first non-zero element of k line
88            let a = 1.0/original.array[k][k];
89
90            // normalize the k line
91            for j in k..n {
92                original.array[k][j] *= a;
93            }
94            for j in 0..n {
95                inv.array[k][j] *= a;
96            }
97
98            for i in k+1..n {
99                let b = original.array[i][k];
100                for j in k..n {
101                    original.array[i][j] -= original.array[k][j]*b;
102                }
103                for j in 0..n {
104                    inv.array[i][j] -= inv.array[k][j]*b;
105                }
106            }
107        }
108
109        // back way
110        for k in (0..n).rev() {
111            for i in 0..k {
112                let a = original.array[i][k];
113                for j in k..n {
114                    original.array[i][j] -= original.array[k][j]*a;
115                }
116                for j in 0..n {
117                    inv.array[i][j] -= inv.array[k][j]*a;
118                }
119            }
120        }
121
122        inv
123    } 
124
125    /// returns vector of copy of line i
126    pub fn line(&self, i: usize) -> Vector {
127        Vector::from(self.array[i].clone())
128    }
129
130    pub fn diagonal(vec: Vector) -> Matrix {
131        let mut matrix = Matrix::zeros((vec.len(), vec.len()));
132        for i in 0..vec.len() {
133            matrix[(i,i)] = vec[i];
134        }
135        matrix
136    }
137
138}
139
140
141impl Init for Matrix {
142    type Output = Matrix;
143    type Size = (usize, usize);
144
145    fn init(value: f64, size: Self::Size) -> Self::Output {
146        Matrix {
147            array : vec![vec![value; size.1]; size.0],
148            m : size.0,
149            n : size.1
150        }
151    }
152
153    fn init_func<F>(func: F, size: Self::Size) -> Self::Output where F: Fn(Self::Size) -> f64 {
154        Matrix {
155            array : (0..size.0).map(|i| {
156                (0..size.1).map(|j| func((i,j))).collect()
157            }).collect(),
158            n : size.0,
159            m : size.1,
160        }
161    }
162}
163
164
165impl std::clone::Clone for Matrix {
166
167    fn clone(&self) -> Self {
168        Matrix {
169            array : self.array.clone(),
170            m : self.m,
171            n : self.n,
172        }
173    }
174
175}
176
177
178impl Dot<Vector> for Matrix {
179    type Output = Vector;
180
181    fn dot(&self, rhs: &Vector) -> Self::Output {
182        assert_eq!(self.n, rhs.len());
183
184        let mut result = Vector::zeros(self.n);
185        for i in 0..result.len() {
186            let mut s = 0f64;
187            for k in 0..self.m {
188                s += self.array[i][k]*rhs[k]
189            }
190            result[i] = s;
191        }
192
193        result
194    }
195}
196
197impl Dot<Matrix> for Matrix {
198
199    type Output = Matrix;
200
201    fn dot(&self, rhs: &Matrix) -> Self::Output {
202        assert_eq!(self.n, rhs.m);
203
204        let mut result = Matrix::zeros((self.m, rhs.n));
205        for i in 0..result.n {
206            for j in 0..result.m {
207                let mut s = 0f64;
208                for k in 0..self.m {
209                    s += self.array[i][k]*rhs.array[k][j]
210                }
211                result.array[i][j] = s;
212            }
213        }
214        
215        result
216    }
217
218}
219
220impl std::ops::Index<usize> for Matrix {
221    type Output = Vec<f64>;
222
223    #[inline]
224    fn index(&self, index: usize) -> &Self::Output {
225        &self.array[index]
226    }
227}
228
229
230impl std::ops::Index<(usize, usize)> for Matrix {
231    type Output = f64;
232
233    #[inline]
234    fn index(&self, index: (usize, usize)) -> &Self::Output {
235        &self[index.0][index.1]
236    }
237}
238
239
240impl std::ops::IndexMut<usize> for Matrix {
241    #[inline]
242    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
243        &mut self.array[index]
244    }
245}
246
247impl std::ops::IndexMut<(usize, usize)> for Matrix {
248    #[inline]
249    fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
250        &mut self[index.0][index.1]
251    }
252}
253
254
255impl std::ops::Neg for Matrix {
256    type Output = Matrix;
257
258    // moves self !!!
259    fn neg(self) -> Self::Output {
260        Matrix::from(self.array.iter().map(|line| 
261            line.iter().map(|x| -x).collect()
262        ).collect())
263    }
264}
265
266impl std::ops::Neg for &Matrix {
267    type Output = Matrix;
268
269    // moves self !!!
270    fn neg(self) -> Self::Output {
271        Matrix::from(self.array.iter().map(|line| 
272            line.iter().map(|x| -x).collect()
273        ).collect())
274    }
275}
276
277macro_rules! impl_operator {
278    ( $($op:tt),* ) => {
279        $(
280        impl_op_ex!($op |a: &Matrix, b: &Matrix| -> Matrix {
281            Matrix::from(a.iter()
282                .zip(b.iter())
283                .map(|(line_a,line_b)| {
284                    line_a.iter().zip(line_b.iter())
285                        .map(|(x,y)| x $op y)
286                        .collect()
287                }).collect()
288            )
289        });
290
291        impl_op_ex!($op |a: &Matrix, k: &f64| -> Matrix {
292            Matrix::from(a.iter()
293                .map(|line| line.iter()
294                    .map(|x| x $op k).collect()
295                ).collect()
296            )
297        });
298                    
299        )*
300    }
301}
302
303/*
304macro_rules! impl_operator_assign {
305    ( $($op:tt),* ) => {
306    };
307}
308*/
309
310impl_operator![+, -, *, /];
311
312