haar_lib/linalg/mod_p/
gaussian_elim.rs1use crate::num::ff::FFElem;
3
4pub fn gaussian_elim<T>(mut a: Vec<Vec<T>>) -> (usize, Vec<Vec<T>>)
6where
7 T: FFElem + Copy,
8{
9 let n = a.len();
10 let Some(m) = a.first().map(|a| a.len()) else {
11 return (0, a);
12 };
13
14 assert!(a.iter().all(|r| r.len() == m));
15 let mut rank = 0;
16
17 for j in 0..m {
18 let mut pivot = None;
19
20 for (i, ai) in a.iter().enumerate().skip(rank) {
21 if ai[j].value() != 0 {
22 pivot = Some(i);
23 break;
24 }
25 }
26
27 if let Some(pivot) = pivot {
28 a.swap(pivot, rank);
29
30 let mut ar = a.swap_remove(rank);
31 let d = ar[j].inv();
32 for x in ar.iter_mut() {
33 *x *= d;
34 }
35
36 for ai in a.iter_mut() {
37 let d = ai[j];
38 if d.value() != 0 {
39 for (aij, arj) in ai.iter_mut().zip(ar.iter()) {
40 *aij -= *arj * d;
41 }
42 }
43 }
44
45 a.push(ar);
46 a.swap(rank, n - 1);
47
48 rank += 1;
49 } else {
50 continue;
51 }
52 }
53
54 (rank, a)
55}