1use std::{
2 fmt::Display,
3 ops::{Index, IndexMut},
4};
5
6use crate::{detail, Vector};
7
8use pyinrs::Fraction;
9
10#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
12pub struct Matrix {
13 rows: Vec<Vector>,
14}
15
16impl Matrix {
17 pub fn new() -> Self {
19 Self { rows: Vec::new() }
20 }
21
22 pub fn create(row: usize, col: usize, value: Fraction) -> Self {
24 let mut rows = Vec::with_capacity(row);
25 for _ in 0..row {
26 rows.push(Vector::create(col, value));
27 }
28 Self { rows }
29 }
30
31 pub fn zeros(row: usize, col: usize) -> Self {
33 Self::create(row, col, 0.into())
34 }
35
36 pub fn ones(row: usize, col: usize) -> Self {
38 Self::create(row, col, 1.into())
39 }
40
41 pub fn identity(n: usize) -> Self {
43 let mut m = Self::zeros(n, n);
44 for i in 0..n {
45 m[i][i] = 1.into();
46 }
47 m
48 }
49
50 pub fn row_size(&self) -> usize {
52 self.rows.len()
53 }
54
55 pub fn col_size(&self) -> usize {
57 if self.row_size() == 0 {
58 0
59 } else {
60 self.rows[0].size()
61 }
62 }
63
64 pub fn is_empty(&self) -> bool {
66 self.rows.is_empty()
67 }
68
69 pub fn is_symmetric(&self) -> bool {
71 if self.row_size() != self.col_size() {
72 return false;
73 }
74
75 for r in 0..self.row_size() {
76 for c in 0..r {
77 if self.rows[r][c] != self.rows[c][r] {
78 return false;
79 }
80 }
81 }
82
83 true
84 }
85
86 pub fn is_upper(&self) -> bool {
88 if self.row_size() != self.col_size() {
89 return false;
90 }
91
92 for r in 1..self.row_size() {
93 for c in 0..r {
94 if self[r][c] != 0.into() {
95 return false;
96 }
97 }
98 }
99
100 true
101 }
102
103 pub fn is_lower(&self) -> bool {
105 if self.row_size() != self.col_size() {
106 return false;
107 }
108
109 for c in 1..self.col_size() {
110 for r in 0..c {
111 if self[r][c] != 0.into() {
112 return false;
113 }
114 }
115 }
116
117 true
118 }
119
120 pub fn is_diagonal(&self) -> bool {
122 self.is_lower() && self.is_upper()
123 }
124
125 pub fn trace(&self) -> Fraction {
127 detail::check_square(self);
128
129 let mut tr = Fraction::new();
130 for i in 0..self.row_size() {
131 tr += self[i][i];
132 }
133
134 tr
135 }
136
137 pub fn transpose(&self) -> Self {
139 let mut result = Self::zeros(self.col_size(), self.row_size());
140
141 for i in 0..self.row_size() {
142 for j in 0..self.col_size() {
143 result[j][i] = self[i][j];
144 }
145 }
146 result
147 }
148
149 pub fn row_echelon_form(&self) -> Self {
151 let mut m = self.clone();
152
153 for i in 0..m.row_size() {
155 let mut j: usize = 0;
156 while j < m.col_size() && m.rows[i][j] == 0.into() {
157 j += 1;
158 }
159 for k in i + 1..m.row_size() {
160 if j < m.col_size() && m.rows[i][j] != 0.into() {
161 m.e_row_sum(k, i, -m.rows[k][j] / m.rows[i][j]);
162 }
163 }
164 }
165
166 m.rows.sort_by_key(|r| r.count_leading_zeros());
168
169 m
170 }
171
172 pub fn row_canonical_form(&self) -> Self {
174 let mut m = self.row_echelon_form();
175
176 let n = usize::min(m.row_size(), m.col_size());
177
178 for c in 0..n {
180 for r in 0..c {
181 if m[c][c] != 0.into() {
182 m.e_row_sum(r, c, -(m[r][c] / m[c][c]));
183 }
184 }
185 }
186
187 let mut i = 0;
189 while i < n && m[i][i] != 0.into() {
190 m.e_scalar_multiplication(i, Fraction::from(1) / m[i][i]);
191 i += 1;
192 }
193
194 m
195 }
196
197 pub fn det(&self) -> Fraction {
199 detail::check_square(self);
200
201 let n = self.row_size();
202 let mut a = self.clone();
203
204 let mut det = Fraction::from(1);
205 for i in 0..n {
206 let mut pivot = i;
207 for j in i + 1..n {
208 if a[j][i].abs() > a[pivot][i].abs() {
209 pivot = j;
210 }
211 }
212 if pivot != i {
213 a.e_row_swap(i, pivot);
214 det = -det;
215 }
216 if a[i][i] == 0.into() {
217 return Fraction::new();
218 }
219 det *= a[i][i];
220 for j in i + 1..n {
221 a.e_row_sum(j, i, -a[j][i] / a[i][i]);
222 }
223 }
224 det
225 }
226
227 pub fn submatrix(&self, i: usize, j: usize) -> Self {
229 let mut submatrix = Vec::with_capacity(self.row_size() - 1);
230 for r in 0..self.row_size() {
231 if r != i {
232 let mut row = Vec::with_capacity(self.col_size() - 1);
233 row.extend_from_slice(&self[r].elements[..j]);
234 row.extend_from_slice(&self[r].elements[j + 1..]);
235 submatrix.push(row);
236 }
237 }
238 Self::from(submatrix)
239 }
240
241 pub fn minor(&self) -> Self {
243 let mut m = Self::zeros(self.row_size(), self.col_size());
244 for r in 0..m.row_size() {
245 for c in 0..m.col_size() {
246 m[r][c] = self.submatrix(r, c).det();
247 }
248 }
249 m
250 }
251
252 pub fn cofactor(&self) -> Self {
254 let mut m = self.minor();
255 for r in 0..m.row_size() {
256 for c in 0..self.col_size() {
257 if (r + c) & 1 == 1 {
259 m[r][c] = -m[r][c];
260 }
261 }
262 }
263 m
264 }
265
266 pub fn adj(&self) -> Self {
268 self.cofactor().transpose()
269 }
270
271 pub fn inv(&self) -> Option<Self> {
273 detail::check_square(self);
274
275 if self.is_empty() {
277 return Some(Matrix::new());
278 }
279
280 let n = self.row_size();
282 let rref = self.clone().expand_col(Self::identity(n)).row_canonical_form().split_col(n);
283
284 if !rref.0[n - 1].is_zero() {
286 Some(rref.1)
287 } else {
288 None
289 }
290 }
291
292 pub fn rank(&self) -> usize {
294 let zeros = self.row_echelon_form().rows.iter().filter(|row| row.is_zero()).count();
295 self.row_size() - zeros
296 }
297
298 pub fn lu_decomposition(&self) -> (Self, Self) {
300 detail::check_square(self);
301
302 let n = self.row_size();
303
304 if self.is_upper() {
305 return (Matrix::zeros(n, n), self.clone());
306 } else if self.is_lower() {
307 return (self.clone(), Matrix::zeros(n, n));
308 }
309
310 let mut l = Self::identity(n);
311 let mut u = Self::zeros(n, n);
312
313 for i in 0..n {
314 for j in 0..(i + 1) {
315 let mut sum = Fraction::new();
316 for k in 0..j {
317 sum += l[j][k] * u[k][i];
318 }
319 u[j][i] = self[j][i] - sum;
320 }
321
322 for j in (i + 1)..n {
323 let mut sum = Fraction::new();
324 for k in 0..i {
325 sum += l[j][k] * u[k][i];
326 }
327 l[j][i] = (self[j][i] - sum) / u[i][i];
328 }
329 }
330
331 (l, u)
332 }
333
334 pub fn split_row(&self, n: usize) -> (Self, Self) {
336 detail::check_bounds(n, 0, self.row_size());
337
338 let (mut first, mut second) = (Self::new(), Self::new());
339 first.rows = self.rows[0..n].to_vec();
340 second.rows = self.rows[n..].to_vec();
341
342 (first, second)
343 }
344
345 pub fn split_col(&self, n: usize) -> (Self, Self) {
347 detail::check_bounds(n, 0, self.col_size());
348
349 let (mut first, mut second) = (Self::new(), Self::new());
350 first.rows.resize(self.row_size(), Default::default());
351 second.rows.resize(self.row_size(), Default::default());
352 for r in 0..self.row_size() {
353 first.rows[r].elements = self.rows[r].elements[..n].to_vec();
354 second.rows[r].elements = self.rows[r].elements[n..].to_vec();
355 }
356
357 (first, second)
358 }
359
360 pub fn expand_row(&mut self, mut matrix: Self) -> &Self {
362 detail::check_size(self.col_size(), matrix.col_size());
363
364 self.rows.append(&mut matrix.rows);
365 self
366 }
367
368 pub fn expand_col(&mut self, mut matrix: Self) -> &Self {
370 detail::check_size(self.row_size(), matrix.row_size());
371
372 for i in 0..self.row_size() {
373 self.rows[i].elements.append(&mut matrix[i].elements);
374 }
375 self
376 }
377
378 pub fn e_row_swap(&mut self, i: usize, j: usize) -> &Self {
380 self.rows.swap(i, j);
381 self
382 }
383
384 pub fn e_scalar_multiplication(&mut self, i: usize, k: Fraction) -> &Self {
386 self.rows[i] *= k;
387 self
388 }
389
390 pub fn e_row_sum(&mut self, i: usize, j: usize, k: Fraction) -> &Self {
392 let row = self[j].clone();
393 self.rows[i] += row * k;
394 self
395 }
396}
397
398impl<const R: usize, const C: usize> From<[[Fraction; C]; R]> for Matrix {
399 fn from(value: [[Fraction; C]; R]) -> Self {
400 let rows = Vec::from(value.map(Vector::from));
401 Self { rows }
402 }
403}
404
405impl<const R: usize, const C: usize> From<[[i32; C]; R]> for Matrix {
406 fn from(value: [[i32; C]; R]) -> Self {
407 let rows = Vec::from(value.map(Vector::from));
408 Self { rows }
409 }
410}
411
412impl From<Vec<Vec<Fraction>>> for Matrix {
413 fn from(value: Vec<Vec<Fraction>>) -> Self {
414 let rows = value.into_iter().map(Vector::from).collect();
415 Self { rows }
416 }
417}
418
419impl From<Vec<Vec<i32>>> for Matrix {
420 fn from(value: Vec<Vec<i32>>) -> Self {
421 let rows = value.into_iter().map(Vector::from).collect();
422 Self { rows }
423 }
424}
425
426impl Index<usize> for Matrix {
427 type Output = Vector;
428
429 fn index(&self, index: usize) -> &Self::Output {
430 &self.rows[index]
431 }
432}
433
434impl IndexMut<usize> for Matrix {
435 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
436 &mut self.rows[index]
437 }
438}
439
440impl Display for Matrix {
441 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
442 writeln!(f, "[")?;
443
444 let mut width = 0;
446 for i in 0..self.row_size() {
447 for j in 0..self.col_size() {
448 width = width.max(format!("{}", self[i][j]).len());
449 }
450 }
451
452 for i in 0..self.row_size() {
454 for j in 0..self.col_size() {
455 if j != 0 {
456 write!(f, " ")?;
457 }
458 write!(f, "{:>width$}", format!("{}", self[i][j]))?;
459 }
460 writeln!(f)?;
461 }
462
463 write!(f, "]")
464 }
465}
466
467auto_ops::impl_op_ex!(+=|a: &mut Matrix, b: &Matrix| {
468 detail::check_size(a.row_size(), b.row_size());
469 detail::check_size(a.col_size(), b.col_size());
470
471 for r in 0..a.row_size() {
472 a[r] += &b[r];
473 }
474});
475
476auto_ops::impl_op_ex!(+|a: &Matrix, b: &Matrix| -> Matrix {
477 let mut a = a.clone();
478 a += b;
479 a
480});
481
482auto_ops::impl_op_ex!(-=|a: &mut Matrix, b: &Matrix| {
483 detail::check_size(a.row_size(), b.row_size());
484 detail::check_size(a.col_size(), b.col_size());
485
486 for r in 0..a.row_size() {
487 a[r] -= &b[r];
488 }
489});
490
491auto_ops::impl_op_ex!(-|a: &Matrix, b: &Matrix| -> Matrix {
492 let mut a = a.clone();
493 a -= b;
494 a
495});
496
497auto_ops::impl_op_ex!(*=|a: &mut Matrix, b: Fraction| {
498 for r in 0..a.row_size() {
499 a.rows[r] *= b;
500 }
501});
502
503auto_ops::impl_op_ex_commutative!(*|a: Matrix, b: Fraction| -> Matrix {
504 let mut a = a;
505 a *= b;
506 a
507});
508
509auto_ops::impl_op_ex!(*=|a: &mut Matrix, b: i32| {
510 for r in 0..a.row_size() {
511 a.rows[r] *= b;
512 }
513});
514
515auto_ops::impl_op_ex_commutative!(*|a: Matrix, b: i32| -> Matrix {
516 let mut a = a;
517 a *= b;
518 a
519});
520
521auto_ops::impl_op_ex!(*|a: &Matrix, b: &Matrix| -> Matrix {
522 detail::check_size(a.col_size(), b.row_size());
523
524 let mut result = Matrix::zeros(a.row_size(), b.col_size());
525 let rt = b.transpose();
526 for r in 0..a.row_size() {
527 for c in 0..b.col_size() {
528 result[r][c] = &a[r] * &rt[c];
529 }
530 }
531 result
532});
533
534impl IntoIterator for Matrix {
535 type Item = Vector;
536 type IntoIter = std::vec::IntoIter<Self::Item>;
537
538 fn into_iter(self) -> Self::IntoIter {
539 self.rows.into_iter()
540 }
541}