qfall_math/integer/mat_poly_over_z/arithmetic/neg.rs
1// Copyright 2026 Jan Niklas Siemer
2//
3// This file is part of qFALL-math
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! Implementation of the [`Neg`] trait for [`MatPolyOverZ`] values.
10
11use super::super::MatPolyOverZ;
12use crate::traits::MatrixDimensions;
13use flint3_sys::fmpz_poly_mat_neg;
14use std::ops::Neg;
15
16impl Neg for MatPolyOverZ {
17 type Output = MatPolyOverZ;
18
19 /// Implements the [`Neg`] trait for [`MatPolyOverZ`] values.
20 /// [`Neg`] is implemented for both borrowed and owned [`MatPolyOverZ`].
21 ///
22 /// When called on owned [`MatPolyOverZ`] it will reuse the memory of `self`.
23 ///
24 /// Returns the additive inverse of `self` as a [`MatPolyOverZ`].
25 ///
26 /// # Examples
27 /// ```
28 /// use qfall_math::integer::MatPolyOverZ;
29 /// use std::str::FromStr;
30 ///
31 /// let a: MatPolyOverZ = MatPolyOverZ::from_str("[[2 1 -2, 0],[1 42, 3 1 2 3]]").unwrap();
32 ///
33 /// let b: MatPolyOverZ = -&a;
34 /// let c: MatPolyOverZ = -a;
35 /// ```
36 fn neg(mut self) -> Self::Output {
37 unsafe { fmpz_poly_mat_neg(&mut self.matrix, &self.matrix) };
38 self
39 }
40}
41
42impl Neg for &MatPolyOverZ {
43 type Output = MatPolyOverZ;
44
45 /// Documentation at [`MatPolyOverZ::neg`].
46 fn neg(self) -> Self::Output {
47 let mut out = MatPolyOverZ::new(self.get_num_rows(), self.get_num_columns());
48 unsafe { fmpz_poly_mat_neg(&mut out.matrix, &self.matrix) };
49 out
50 }
51}
52
53#[cfg(test)]
54mod test_neg {
55 use super::MatPolyOverZ;
56 use std::str::FromStr;
57
58 /// Ensure that `neg` works for small coefficients.
59 #[test]
60 fn correct_small() {
61 let a = MatPolyOverZ::from_str("[[2 1 -2, 0, 1 5],[1 -3, 3 1 0 4, 0]]").unwrap();
62 let b = MatPolyOverZ::from_str("[[2 -1 2, 0, 1 -5],[1 3, 3 -1 0 -4, 0]]").unwrap();
63 let c = MatPolyOverZ::new(2, 3);
64
65 assert_eq!(a, -(-&a));
66 assert_eq!(a, -&b);
67 assert_eq!(b, -&a);
68 assert_eq!(a, -b.clone());
69 assert_eq!(b, -a);
70 assert_eq!(c, -&c);
71 assert_eq!(c.clone(), -c);
72 }
73
74 /// Ensure that `neg` works for large coefficients.
75 #[test]
76 fn correct_large() {
77 let a =
78 MatPolyOverZ::from_str(&format!("[[2 {} {}],[1 1]]", u64::MAX, i64::MIN)).unwrap();
79 let b = MatPolyOverZ::from_str(&format!(
80 "[[2 -{} {}],[1 -1]]",
81 u64::MAX,
82 i64::MAX as u64 + 1
83 ))
84 .unwrap();
85
86 assert_eq!(a, -(-&a));
87 assert_eq!(b, -&a);
88 assert_eq!(b, -a);
89 }
90}