qfall_math/integer/poly_over_z/arithmetic/
sub.rs1use super::super::PolyOverZ;
12use crate::{
13 integer_mod_q::{PolyOverZq, PolynomialRingZq},
14 macros::arithmetics::{
15 arithmetic_assign_trait_borrowed_to_owned, arithmetic_trait_borrowed_to_owned,
16 arithmetic_trait_mixed_borrowed_owned,
17 },
18 rational::PolyOverQ,
19};
20use flint3_sys::{fmpq_poly_sub, fmpz_mod_poly_sub, fmpz_poly_sub};
21use std::ops::{Sub, SubAssign};
22
23impl SubAssign<&PolyOverZ> for PolyOverZ {
24 fn sub_assign(&mut self, other: &Self) {
44 unsafe { fmpz_poly_sub(&mut self.poly, &self.poly, &other.poly) };
45 }
46}
47
48arithmetic_assign_trait_borrowed_to_owned!(SubAssign, sub_assign, PolyOverZ, PolyOverZ);
49
50impl Sub for &PolyOverZ {
51 type Output = PolyOverZ;
52 fn sub(self, other: Self) -> Self::Output {
74 let mut out = PolyOverZ::default();
75 unsafe {
76 fmpz_poly_sub(&mut out.poly, &self.poly, &other.poly);
77 }
78 out
79 }
80}
81
82arithmetic_trait_borrowed_to_owned!(Sub, sub, PolyOverZ, PolyOverZ, PolyOverZ);
83arithmetic_trait_mixed_borrowed_owned!(Sub, sub, PolyOverZ, PolyOverZ, PolyOverZ);
84
85impl Sub<&PolyOverZq> for &PolyOverZ {
86 type Output = PolyOverZq;
87 fn sub(self, other: &PolyOverZq) -> Self::Output {
107 let mut out = PolyOverZq::from(&other.modulus);
108 unsafe {
109 fmpz_mod_poly_sub(
110 &mut out.poly,
111 &PolyOverZq::from((self, &other.modulus)).poly,
112 &other.poly,
113 other.modulus.get_fmpz_mod_ctx_struct(),
114 );
115 }
116 out
117 }
118}
119
120arithmetic_trait_borrowed_to_owned!(Sub, sub, PolyOverZ, PolyOverZq, PolyOverZq);
121arithmetic_trait_mixed_borrowed_owned!(Sub, sub, PolyOverZ, PolyOverZq, PolyOverZq);
122
123impl Sub<&PolynomialRingZq> for &PolyOverZ {
124 type Output = PolynomialRingZq;
125 fn sub(self, other: &PolynomialRingZq) -> Self::Output {
148 let mut out = PolynomialRingZq::from((self, &other.modulus));
149 out -= other;
150 out
151 }
152}
153
154arithmetic_trait_borrowed_to_owned!(Sub, sub, PolyOverZ, PolynomialRingZq, PolynomialRingZq);
155arithmetic_trait_mixed_borrowed_owned!(Sub, sub, PolyOverZ, PolynomialRingZq, PolynomialRingZq);
156
157impl Sub<&PolyOverQ> for &PolyOverZ {
158 type Output = PolyOverQ;
159 fn sub(self, other: &PolyOverQ) -> Self::Output {
179 let mut out = PolyOverQ::default();
180 unsafe {
181 fmpq_poly_sub(&mut out.poly, &PolyOverQ::from(self).poly, &other.poly);
182 }
183 out
184 }
185}
186
187arithmetic_trait_borrowed_to_owned!(Sub, sub, PolyOverZ, PolyOverQ, PolyOverQ);
188arithmetic_trait_mixed_borrowed_owned!(Sub, sub, PolyOverZ, PolyOverQ, PolyOverQ);
189
190#[cfg(test)]
191mod test_sub_assign {
192 use super::PolyOverZ;
193 use std::str::FromStr;
194
195 #[test]
197 fn correct_small() {
198 let mut a = PolyOverZ::from_str("3 -1 2 -3").unwrap();
199 let b = PolyOverZ::from_str("5 -1 -2 -5 -1 -2").unwrap();
200 let cmp = PolyOverZ::from_str("5 0 4 2 1 2").unwrap();
201
202 a -= b;
203
204 assert_eq!(cmp, a);
205 }
206
207 #[test]
209 fn correct_large() {
210 let mut a =
211 PolyOverZ::from_str(&format!("3 {} {} {}", u32::MAX, i32::MIN, i32::MAX)).unwrap();
212 let b = PolyOverZ::from_str(&format!("2 -{} -{}", u32::MAX, i32::MAX)).unwrap();
213 let cmp = PolyOverZ::from_str(&format!("3 {} -1 {}", u64::from(u32::MAX) * 2, i32::MAX))
214 .unwrap();
215
216 a -= b;
217
218 assert_eq!(cmp, a);
219 }
220
221 #[test]
223 fn availability() {
224 let mut a = PolyOverZ::from_str("3 1 2 -3").unwrap();
225 let b = PolyOverZ::from_str("3 -1 -2 3").unwrap();
226
227 a -= &b;
228 a -= b;
229 }
230}
231
232#[cfg(test)]
233mod test_sub {
234 use super::PolyOverZ;
235 use std::str::FromStr;
236
237 #[test]
239 fn sub() {
240 let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
241 let b: PolyOverZ = PolyOverZ::from_str("5 1 2 5 1 2").unwrap();
242 let c: PolyOverZ = a - b;
243 assert_eq!(c, PolyOverZ::from_str("5 0 0 -8 -1 -2").unwrap());
244 }
245
246 #[test]
248 fn sub_borrow() {
249 let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
250 let b: PolyOverZ = PolyOverZ::from_str("5 1 2 5 1 2").unwrap();
251 let c: PolyOverZ = &a - &b;
252 assert_eq!(c, PolyOverZ::from_str("5 0 0 -8 -1 -2").unwrap());
253 }
254
255 #[test]
257 fn sub_first_borrowed() {
258 let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
259 let b: PolyOverZ = PolyOverZ::from_str("5 1 2 5 1 2").unwrap();
260 let c: PolyOverZ = &a - b;
261 assert_eq!(c, PolyOverZ::from_str("5 0 0 -8 -1 -2").unwrap());
262 }
263
264 #[test]
266 fn sub_second_borrowed() {
267 let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
268 let b: PolyOverZ = PolyOverZ::from_str("5 1 2 5 1 2").unwrap();
269 let c: PolyOverZ = a - &b;
270 assert_eq!(c, PolyOverZ::from_str("5 0 0 -8 -1 -2").unwrap());
271 }
272
273 #[test]
275 fn sub_eliminating_coefficients() {
276 let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
277 let b: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
278 let c: PolyOverZ = a - b;
279 assert_eq!(c, PolyOverZ::default());
280 }
281
282 #[test]
284 fn sub_large_numbers() {
285 let a: PolyOverZ =
286 PolyOverZ::from_str(&format!("3 {} {} {}", u32::MAX, i32::MIN, i32::MAX)).unwrap();
287 let b: PolyOverZ = PolyOverZ::from_str(&format!("2 {} {}", u32::MAX, i32::MAX)).unwrap();
288 let c: PolyOverZ = a - b;
289 assert_eq!(
290 c,
291 PolyOverZ::from_str(&format!(
292 "3 0 {} {}",
293 i64::from(i32::MIN) * 2 + 1,
294 i32::MAX
295 ))
296 .unwrap()
297 );
298 }
299}
300
301#[cfg(test)]
302mod test_mul_poly_over_zq {
303 use super::PolyOverZq;
304 use crate::integer::PolyOverZ;
305 use std::str::FromStr;
306
307 #[test]
309 fn borrowed_correctness() {
310 let poly_1 = PolyOverZ::from_str("2 1 2").unwrap();
311 let poly_2 = PolyOverZq::from_str(&format!("1 {} mod {}", i64::MAX, u64::MAX)).unwrap();
312
313 let poly_cmp =
314 PolyOverZq::from_str(&format!("2 {} 2 mod {}", -i64::MAX as i128 + 1, u64::MAX))
315 .unwrap();
316
317 let poly_1 = &poly_1 - &poly_2;
318
319 assert_eq!(poly_cmp, poly_1);
320 }
321
322 #[test]
324 fn availability() {
325 let poly = PolyOverZq::from_str("3 1 2 3 mod 17").unwrap();
326 let z = PolyOverZ::from(2);
327
328 _ = z.clone() - poly.clone();
329 _ = &z - &poly;
330 _ = z.clone() - &poly;
331 _ = &z - poly.clone();
332 }
333}
334
335#[cfg(test)]
336mod test_sub_poly_ring_zq {
337 use super::PolynomialRingZq;
338 use crate::integer::PolyOverZ;
339 use std::str::FromStr;
340
341 #[test]
343 fn borrowed_correctness() {
344 let poly_1 =
345 PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX))
346 .unwrap();
347 let poly_2 = PolynomialRingZq::from_str(&format!(
348 "2 -1 -{} / 4 1 2 3 1 mod {}",
349 i64::MAX as u64 - 2,
350 u64::MAX
351 ))
352 .unwrap();
353 let poly = PolyOverZ::from_str("2 1 2").unwrap();
354
355 let poly_1 = &poly - &poly_1;
356
357 assert_eq!(poly_2, poly_1);
358 }
359
360 #[test]
362 fn availability() {
363 let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap();
364 let z = PolyOverZ::from(2);
365
366 _ = z.clone() - poly.clone();
367 _ = &z - &poly;
368 _ = z.clone() - &poly;
369 _ = &z - poly.clone();
370 }
371}
372
373#[cfg(test)]
374mod test_mul_poly_over_q {
375 use super::PolyOverQ;
376 use crate::integer::PolyOverZ;
377 use std::str::FromStr;
378
379 #[test]
381 fn borrowed_correctness() {
382 let poly_1 = PolyOverZ::from_str("2 1 2").unwrap();
383 let poly_2 = PolyOverQ::from_str(&format!("1 1/{}", i64::MAX)).unwrap();
384 let poly_cmp =
385 PolyOverQ::from_str(&format!("2 {}/{} 2", i64::MAX as i128 - 1, i64::MAX)).unwrap();
386
387 let poly_1 = &poly_1 - &poly_2;
388
389 assert_eq!(poly_cmp, poly_1);
390 }
391
392 #[test]
394 fn availability() {
395 let poly = PolyOverQ::from_str("3 1/2 2 3/7").unwrap();
396 let z = PolyOverZ::from(2);
397
398 _ = z.clone() - poly.clone();
399 _ = &z - &poly;
400 _ = z.clone() - &poly;
401 _ = &z - poly.clone();
402 }
403}