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, n : usize, }
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 pub fn iter(&self) -> Iter<'_, Vec<f64>> {
55 self.array.iter()
56 }
57
58pub fn inv(&self) -> Matrix {
74 assert!(self.is_square());
75 let n = self.n;
76
77 let mut original = self.clone();
79 let mut inv = Matrix::diagonal(
81 Vector::ones(self.m)
82 );
83
84 for k in 0..n {
86
87 let a = 1.0/original.array[k][k];
89
90 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 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 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 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 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
303impl_operator![+, -, *, /];
311
312