haar_lib/linalg/mod_m/
determinant.rs1use crate::num::zz::{ZZElem, ZZ};
3
4pub fn determinant<R>(mut a: Vec<Vec<R::Element>>, ring: &R) -> R::Element
6where
7 R: ZZ + Copy,
8 R::Element: ZZElem,
9{
10 let n = a.len();
11
12 assert!(a.iter().all(|r| r.len() == n));
13
14 let mut minus = false;
15
16 for i in 0..n {
17 if a[i][i].value() == 0 {
18 if let Some(j) = (i + 1..n).find(|&j| a[j][i].value() != 0) {
19 a.swap(i, j);
20 minus = !minus;
21 } else {
22 return ring.zero();
23 }
24 }
25
26 let mut ai = a.swap_remove(i);
27
28 for aj in a.iter_mut().skip(i) {
29 let t = aj[i];
30 if t.value() == 0 {
31 continue;
32 }
33
34 loop {
35 if aj[i].value() == 0 {
36 break;
37 }
38
39 if ai[i].value() > aj[i].value() {
40 std::mem::swap(&mut ai, aj);
41 minus = !minus;
42 }
43
44 let t = ring.from_u64((aj[i].value() / ai[i].value()) as u64);
45
46 for (x, y) in aj.iter_mut().skip(i).zip(ai.iter().skip(i)) {
47 *x -= *y * t;
48 }
49 }
50 }
51
52 a.push(ai);
53 a.swap(i, n - 1);
54 }
55
56 let mut ret = ring.one();
57 for (i, ai) in a.into_iter().enumerate() {
58 ret *= ai[i];
59 }
60
61 if minus {
62 ret = -ret;
63 }
64
65 ret
66}