qfall_math/integer/mat_z/
trace.rs1use flint_sys::fmpz_mat::fmpz_mat_trace;
12
13use super::MatZ;
14use crate::{error::MathError, integer::Z, traits::MatrixDimensions};
15
16impl MatZ {
17 pub fn trace(&self) -> Result<Z, MathError> {
33 if self.get_num_rows() != self.get_num_columns() {
35 return Err(MathError::NoSquareMatrix(self.to_string()));
36 }
37
38 let mut out = Z::default();
39 unsafe {
40 fmpz_mat_trace(&mut out.value, &self.matrix);
41 }
42 Ok(out)
43 }
44}
45
46#[cfg(test)]
47mod test_trace {
48 use crate::integer::{MatZ, Z};
49 use std::str::FromStr;
50
51 #[test]
53 fn trace_works() {
54 let mat_1 = MatZ::from_str("[[5, 2, 0],[2, 1, 0],[0, 0, 1]]").unwrap();
55 let mat_2 = MatZ::from_str("[[-1, 0],[0, 1]]").unwrap();
56
57 let trace_1 = mat_1.trace().unwrap();
58 let trace_2 = mat_2.trace().unwrap();
59
60 assert_eq!(Z::from(7), trace_1);
61 assert_eq!(Z::from(0), trace_2);
62 }
63
64 #[test]
66 fn trace_large_values() {
67 let mat_1 = MatZ::from_str(&format!("[[{}, 5],[1, {}]]", i64::MAX, i64::MAX)).unwrap();
68 let mat_2 = MatZ::from_str(&format!("[[{}]]", i64::MIN)).unwrap();
69 let mat_3 = MatZ::from_str(&format!("[[{}, 5],[1, {}]]", i64::MIN, i64::MAX)).unwrap();
70
71 let trace_1 = mat_1.trace().unwrap();
72 let trace_2 = mat_2.trace().unwrap();
73 let trace_3 = mat_3.trace().unwrap();
74
75 assert_eq!(Z::from(2 * i64::MAX as u64), trace_1);
76 assert_eq!(Z::from(i64::MIN), trace_2);
77 assert_eq!(Z::from(-1), trace_3);
78 }
79
80 #[test]
82 fn trace_error_not_squared() {
83 let mat_1 = MatZ::from_str("[[1, 0, 1],[0, 1, 1]]").unwrap();
84 let mat_2 = MatZ::from_str("[[1, 0],[0, 1],[1, 0]]").unwrap();
85
86 assert!(mat_1.trace().is_err());
87 assert!(mat_2.trace().is_err());
88 }
89}