1use ark_ff::PrimeField;
4
5pub fn mat_inverse<F: PrimeField>(mat: &[Vec<F>]) -> Vec<Vec<F>> {
11 let n = mat.len();
12 assert!(mat[0].len() == n);
13
14 let mut m = mat.to_owned();
15 let mut inv = vec![vec![F::zero(); n]; n];
16 for (i, invi) in inv.iter_mut().enumerate() {
17 invi[i] = F::one();
18 }
19
20 for row in 0..n {
22 for j in 0..row {
23 let el = m[row][j];
25 for col in 0..n {
26 if col < j {
28 m[row][col] = F::zero();
29 } else {
30 let mut tmp = m[j][col];
31 tmp.mul_assign(&el);
32 m[row][col].sub_assign(&tmp);
33 }
34 if col > row {
35 inv[row][col] = F::zero();
36 } else {
37 let mut tmp = inv[j][col];
38 tmp.mul_assign(&el);
39 inv[row][col].sub_assign(&tmp);
40 }
41 }
42 }
43 let el_inv = m[row][row].inverse().unwrap();
45 for col in 0..n {
46 match col.cmp(&row) {
47 std::cmp::Ordering::Less => inv[row][col].mul_assign(&el_inv),
48 std::cmp::Ordering::Equal => {
49 m[row][col] = F::one();
50 inv[row][col].mul_assign(&el_inv)
51 }
52 std::cmp::Ordering::Greater => m[row][col].mul_assign(&el_inv),
53 }
54 }
55 }
56
57 for row in (0..n).rev() {
59 for j in (row + 1..n).rev() {
60 let el = m[row][j];
62 for col in 0..n {
63 #[cfg(debug_assertions)]
66 {
67 if col >= j {
68 m[row][col] = F::zero();
69 }
70 }
71 let mut tmp = inv[j][col];
72 tmp.mul_assign(&el);
73 inv[row][col].sub_assign(&tmp);
74 }
75 }
76 }
77
78 #[cfg(debug_assertions)]
79 {
80 for (row, mrow) in m.iter().enumerate() {
81 for (col, v) in mrow.iter().enumerate() {
82 if row == col {
83 debug_assert!(*v == F::one());
84 } else {
85 debug_assert!(*v == F::zero());
86 }
87 }
88 }
89 }
90
91 inv
92}
93
94pub fn mat_transpose<F: PrimeField>(mat: &[Vec<F>]) -> Vec<Vec<F>> {
95 let rows = mat.len();
96 let cols = mat[0].len();
97 let mut transpose = vec![vec![F::zero(); rows]; cols];
98
99 for (row, matrow) in mat.iter().enumerate() {
100 for col in 0..cols {
101 transpose[col][row] = matrow[col];
102 }
103 }
104 transpose
105}