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