qfall_math/rational/poly_over_q/arithmetic/
sub.rs1use super::super::PolyOverQ;
12use crate::{
13 integer::PolyOverZ,
14 macros::arithmetics::{
15 arithmetic_assign_trait_borrowed_to_owned, arithmetic_trait_borrowed_to_owned,
16 arithmetic_trait_mixed_borrowed_owned,
17 },
18};
19use flint_sys::fmpq_poly::fmpq_poly_sub;
20use std::ops::{Sub, SubAssign};
21
22impl SubAssign<&PolyOverQ> for PolyOverQ {
23 fn sub_assign(&mut self, other: &Self) {
48 unsafe { fmpq_poly_sub(&mut self.poly, &self.poly, &other.poly) };
49 }
50}
51impl SubAssign<&PolyOverZ> for PolyOverQ {
52 fn sub_assign(&mut self, other: &PolyOverZ) {
54 let other = PolyOverQ::from(other);
55
56 self.sub_assign(other);
57 }
58}
59
60arithmetic_assign_trait_borrowed_to_owned!(SubAssign, sub_assign, PolyOverQ, PolyOverQ);
61arithmetic_assign_trait_borrowed_to_owned!(SubAssign, sub_assign, PolyOverQ, PolyOverZ);
62
63impl Sub for &PolyOverQ {
64 type Output = PolyOverQ;
65 fn sub(self, other: Self) -> Self::Output {
87 let mut out = PolyOverQ::default();
88 unsafe {
89 fmpq_poly_sub(&mut out.poly, &self.poly, &other.poly);
90 }
91 out
92 }
93}
94
95arithmetic_trait_borrowed_to_owned!(Sub, sub, PolyOverQ, PolyOverQ, PolyOverQ);
96arithmetic_trait_mixed_borrowed_owned!(Sub, sub, PolyOverQ, PolyOverQ, PolyOverQ);
97
98impl Sub<&PolyOverZ> for &PolyOverQ {
99 type Output = PolyOverQ;
100 fn sub(self, other: &PolyOverZ) -> Self::Output {
120 let mut out = PolyOverQ::default();
121 unsafe {
122 fmpq_poly_sub(&mut out.poly, &self.poly, &PolyOverQ::from(other).poly);
123 }
124 out
125 }
126}
127
128arithmetic_trait_borrowed_to_owned!(Sub, sub, PolyOverQ, PolyOverZ, PolyOverQ);
129arithmetic_trait_mixed_borrowed_owned!(Sub, sub, PolyOverQ, PolyOverZ, PolyOverQ);
130
131#[cfg(test)]
132mod test_sub_assign {
133 use super::PolyOverQ;
134 use crate::{integer::PolyOverZ, rational::Q};
135 use std::str::FromStr;
136
137 #[test]
139 fn correct_small() {
140 let mut a = PolyOverQ::from_str("3 1/7 2/7 -3").unwrap();
141 let b = PolyOverQ::from_str("3 -1 2/7 -3").unwrap();
142 let cmp = PolyOverQ::from_str("1 8/7").unwrap();
143
144 a -= &b;
145
146 assert_eq!(cmp, a);
147 }
148
149 #[test]
151 fn correct_large() {
152 let mut a: PolyOverQ = PolyOverQ::from_str(&format!(
153 "3 {} {}/{} {}",
154 u64::MAX,
155 i64::MIN,
156 u128::MAX,
157 i64::MAX
158 ))
159 .unwrap();
160 let b = PolyOverQ::from_str(&format!("2 -{} -{}", u64::MAX, i64::MAX)).unwrap();
161 let cmp = PolyOverQ::from_str(&format!(
162 "3 {} {} {}",
163 u128::from(u64::MAX) * 2,
164 (Q::from_str(&format!("{}/{}", i64::MIN, u128::MAX)).unwrap() + Q::from(i64::MAX)),
165 i64::MAX
166 ))
167 .unwrap();
168
169 a -= b;
170
171 assert_eq!(cmp, a);
172 }
173
174 #[test]
176 fn availability() {
177 let mut a = PolyOverQ::from_str("3 1 2 -3").unwrap();
178 let b = PolyOverQ::from_str("3 -1 -2 3").unwrap();
179 let c = PolyOverZ::from_str("4 2 -1 2 3").unwrap();
180
181 a -= &b;
182 a -= b;
183 a -= &c;
184 a -= c;
185 }
186}
187
188#[cfg(test)]
189mod test_sub {
190 use super::PolyOverQ;
191 use crate::rational::Q;
192 use std::str::FromStr;
193
194 #[test]
196 fn sub() {
197 let a: PolyOverQ = PolyOverQ::from_str("3 1/9 2 -3/7").unwrap();
198 let b: PolyOverQ = PolyOverQ::from_str("5 1/8 -2/9 5/7 1 2/9").unwrap();
199 let c: PolyOverQ = a - b;
200 assert_eq!(
201 c,
202 PolyOverQ::from_str("5 -1/72 20/9 -8/7 -1 -2/9").unwrap()
203 );
204 }
205
206 #[test]
208 fn sub_borrow() {
209 let a: PolyOverQ = PolyOverQ::from_str("3 1/9 2 -3/7").unwrap();
210 let b: PolyOverQ = PolyOverQ::from_str("5 1/8 -2/9 5/7 1 2/9").unwrap();
211 let c: PolyOverQ = &a - &b;
212 assert_eq!(
213 c,
214 PolyOverQ::from_str("5 -1/72 20/9 -8/7 -1 -2/9").unwrap()
215 );
216 }
217
218 #[test]
220 fn sub_first_borrowed() {
221 let a: PolyOverQ = PolyOverQ::from_str("3 1/9 2 -3/7").unwrap();
222 let b: PolyOverQ = PolyOverQ::from_str("5 1/8 -2/9 5/7 1 2/9").unwrap();
223 let c: PolyOverQ = &a - b;
224 assert_eq!(
225 c,
226 PolyOverQ::from_str("5 -1/72 20/9 -8/7 -1 -2/9").unwrap()
227 );
228 }
229
230 #[test]
232 fn sub_second_borrowed() {
233 let a: PolyOverQ = PolyOverQ::from_str("3 1/9 2 -3/7").unwrap();
234 let b: PolyOverQ = PolyOverQ::from_str("5 1/8 -2/9 5/7 1 2/9").unwrap();
235 let c: PolyOverQ = a - &b;
236 assert_eq!(
237 c,
238 PolyOverQ::from_str("5 -1/72 20/9 -8/7 -1 -2/9").unwrap()
239 );
240 }
241
242 #[test]
244 fn sub_eliminating_coefficients() {
245 let a: PolyOverQ = PolyOverQ::from_str("3 1/8 2/7 -3").unwrap();
246 let b: PolyOverQ = PolyOverQ::from_str("3 1/8 2/7 -3").unwrap();
247 let c: PolyOverQ = a - b;
248 assert_eq!(c, PolyOverQ::default());
249 }
250
251 #[test]
253 fn sub_large_numbers() {
254 let a: PolyOverQ = PolyOverQ::from_str(&format!(
255 "3 {} {}/{} {}",
256 u64::MAX,
257 i64::MIN,
258 u128::MAX - 126,
259 i64::MAX
260 ))
261 .unwrap();
262 let b: PolyOverQ = PolyOverQ::from_str(&format!("2 {} {}", u64::MAX, i64::MAX)).unwrap();
263 let c: PolyOverQ = a - b;
264
265 assert!(
266 c == PolyOverQ::from_str(&format!(
267 "3 0 {} {}",
268 (Q::from_str(&format!("{}/{}", i64::MIN, u128::MAX - 126)).unwrap()
269 - Q::from(i64::MAX)),
270 i64::MAX
271 ))
272 .unwrap()
273 );
274 }
275}
276
277#[cfg(test)]
278mod test_mul_poly_over_z {
279 use super::PolyOverQ;
280 use crate::integer::PolyOverZ;
281 use std::str::FromStr;
282
283 #[test]
285 fn borrowed_correctness() {
286 let poly_1 = PolyOverQ::from_str(&format!("1 1/{}", i64::MAX)).unwrap();
287 let poly_2 = PolyOverZ::from_str("2 1 2").unwrap();
288 let poly_cmp =
289 PolyOverQ::from_str(&format!("2 {}/{} -2", -i64::MAX as i128 + 1, i64::MAX)).unwrap();
290
291 let poly_1 = &poly_1 - &poly_2;
292
293 assert_eq!(poly_cmp, poly_1);
294 }
295
296 #[test]
298 fn availability() {
299 let poly = PolyOverQ::from_str("3 1/2 2 3/7").unwrap();
300 let z = PolyOverZ::from(2);
301
302 _ = poly.clone() - z.clone();
303 _ = &poly - &z;
304 _ = &poly - z.clone();
305 _ = poly.clone() - &z;
306 }
307}