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 flint_sys::{
21 fmpq_poly::fmpq_poly_sub, fmpz_mod_poly::fmpz_mod_poly_sub, fmpz_poly::fmpz_poly_sub,
22 fq::fq_sub,
23};
24use std::ops::{Sub, SubAssign};
25
26impl SubAssign<&PolyOverZ> for PolyOverZ {
27 fn sub_assign(&mut self, other: &Self) {
47 unsafe { fmpz_poly_sub(&mut self.poly, &self.poly, &other.poly) };
48 }
49}
50
51arithmetic_assign_trait_borrowed_to_owned!(SubAssign, sub_assign, PolyOverZ, PolyOverZ);
52
53impl Sub for &PolyOverZ {
54 type Output = PolyOverZ;
55 fn sub(self, other: Self) -> Self::Output {
77 let mut out = PolyOverZ::default();
78 unsafe {
79 fmpz_poly_sub(&mut out.poly, &self.poly, &other.poly);
80 }
81 out
82 }
83}
84
85arithmetic_trait_borrowed_to_owned!(Sub, sub, PolyOverZ, PolyOverZ, PolyOverZ);
86arithmetic_trait_mixed_borrowed_owned!(Sub, sub, PolyOverZ, PolyOverZ, PolyOverZ);
87
88impl Sub<&PolyOverZq> for &PolyOverZ {
89 type Output = PolyOverZq;
90 fn sub(self, other: &PolyOverZq) -> Self::Output {
110 let mut out = PolyOverZq::from(&other.modulus);
111 unsafe {
112 fmpz_mod_poly_sub(
113 &mut out.poly,
114 &PolyOverZq::from((self, &other.modulus)).poly,
115 &other.poly,
116 other.modulus.get_fmpz_mod_ctx_struct(),
117 );
118 }
119 out
120 }
121}
122
123arithmetic_trait_borrowed_to_owned!(Sub, sub, PolyOverZ, PolyOverZq, PolyOverZq);
124arithmetic_trait_mixed_borrowed_owned!(Sub, sub, PolyOverZ, PolyOverZq, PolyOverZq);
125
126impl Sub<&PolynomialRingZq> for &PolyOverZ {
127 type Output = PolynomialRingZq;
128 fn sub(self, other: &PolynomialRingZq) -> Self::Output {
151 let mut out = PolynomialRingZq::from((&PolyOverZ::default(), &other.modulus));
152 unsafe {
153 fq_sub(
154 &mut out.poly.poly,
155 &self.poly,
156 &other.poly.poly,
157 other.modulus.get_fq_ctx(),
158 );
159 }
160 out
161 }
162}
163
164arithmetic_trait_borrowed_to_owned!(Sub, sub, PolyOverZ, PolynomialRingZq, PolynomialRingZq);
165arithmetic_trait_mixed_borrowed_owned!(Sub, sub, PolyOverZ, PolynomialRingZq, PolynomialRingZq);
166
167impl Sub<&PolyOverQ> for &PolyOverZ {
168 type Output = PolyOverQ;
169 fn sub(self, other: &PolyOverQ) -> Self::Output {
189 let mut out = PolyOverQ::default();
190 unsafe {
191 fmpq_poly_sub(&mut out.poly, &PolyOverQ::from(self).poly, &other.poly);
192 }
193 out
194 }
195}
196
197arithmetic_trait_borrowed_to_owned!(Sub, sub, PolyOverZ, PolyOverQ, PolyOverQ);
198arithmetic_trait_mixed_borrowed_owned!(Sub, sub, PolyOverZ, PolyOverQ, PolyOverQ);
199
200#[cfg(test)]
201mod test_sub_assign {
202 use super::PolyOverZ;
203 use std::str::FromStr;
204
205 #[test]
207 fn correct_small() {
208 let mut a = PolyOverZ::from_str("3 -1 2 -3").unwrap();
209 let b = PolyOverZ::from_str("5 -1 -2 -5 -1 -2").unwrap();
210 let cmp = PolyOverZ::from_str("5 0 4 2 1 2").unwrap();
211
212 a -= b;
213
214 assert_eq!(cmp, a);
215 }
216
217 #[test]
219 fn correct_large() {
220 let mut a =
221 PolyOverZ::from_str(&format!("3 {} {} {}", u32::MAX, i32::MIN, i32::MAX)).unwrap();
222 let b = PolyOverZ::from_str(&format!("2 -{} -{}", u32::MAX, i32::MAX)).unwrap();
223 let cmp = PolyOverZ::from_str(&format!("3 {} -1 {}", u64::from(u32::MAX) * 2, i32::MAX))
224 .unwrap();
225
226 a -= b;
227
228 assert_eq!(cmp, a);
229 }
230
231 #[test]
233 fn availability() {
234 let mut a = PolyOverZ::from_str("3 1 2 -3").unwrap();
235 let b = PolyOverZ::from_str("3 -1 -2 3").unwrap();
236
237 a -= &b;
238 a -= b;
239 }
240}
241
242#[cfg(test)]
243mod test_sub {
244 use super::PolyOverZ;
245 use std::str::FromStr;
246
247 #[test]
249 fn sub() {
250 let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
251 let b: PolyOverZ = PolyOverZ::from_str("5 1 2 5 1 2").unwrap();
252 let c: PolyOverZ = a - b;
253 assert_eq!(c, PolyOverZ::from_str("5 0 0 -8 -1 -2").unwrap());
254 }
255
256 #[test]
258 fn sub_borrow() {
259 let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
260 let b: PolyOverZ = PolyOverZ::from_str("5 1 2 5 1 2").unwrap();
261 let c: PolyOverZ = &a - &b;
262 assert_eq!(c, PolyOverZ::from_str("5 0 0 -8 -1 -2").unwrap());
263 }
264
265 #[test]
267 fn sub_first_borrowed() {
268 let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
269 let b: PolyOverZ = PolyOverZ::from_str("5 1 2 5 1 2").unwrap();
270 let c: PolyOverZ = &a - b;
271 assert_eq!(c, PolyOverZ::from_str("5 0 0 -8 -1 -2").unwrap());
272 }
273
274 #[test]
276 fn sub_second_borrowed() {
277 let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
278 let b: PolyOverZ = PolyOverZ::from_str("5 1 2 5 1 2").unwrap();
279 let c: PolyOverZ = a - &b;
280 assert_eq!(c, PolyOverZ::from_str("5 0 0 -8 -1 -2").unwrap());
281 }
282
283 #[test]
285 fn sub_eliminating_coefficients() {
286 let a: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
287 let b: PolyOverZ = PolyOverZ::from_str("3 1 2 -3").unwrap();
288 let c: PolyOverZ = a - b;
289 assert_eq!(c, PolyOverZ::default());
290 }
291
292 #[test]
294 fn sub_large_numbers() {
295 let a: PolyOverZ =
296 PolyOverZ::from_str(&format!("3 {} {} {}", u32::MAX, i32::MIN, i32::MAX)).unwrap();
297 let b: PolyOverZ = PolyOverZ::from_str(&format!("2 {} {}", u32::MAX, i32::MAX)).unwrap();
298 let c: PolyOverZ = a - b;
299 assert_eq!(
300 c,
301 PolyOverZ::from_str(&format!(
302 "3 0 {} {}",
303 i64::from(i32::MIN) * 2 + 1,
304 i32::MAX
305 ))
306 .unwrap()
307 );
308 }
309}
310
311#[cfg(test)]
312mod test_mul_poly_over_zq {
313 use super::PolyOverZq;
314 use crate::integer::PolyOverZ;
315 use std::str::FromStr;
316
317 #[test]
319 fn borrowed_correctness() {
320 let poly_1 = PolyOverZ::from_str("2 1 2").unwrap();
321 let poly_2 = PolyOverZq::from_str(&format!("1 {} mod {}", i64::MAX, u64::MAX)).unwrap();
322
323 let poly_cmp =
324 PolyOverZq::from_str(&format!("2 {} 2 mod {}", -i64::MAX as i128 + 1, u64::MAX))
325 .unwrap();
326
327 let poly_1 = &poly_1 - &poly_2;
328
329 assert_eq!(poly_cmp, poly_1);
330 }
331
332 #[test]
334 fn availability() {
335 let poly = PolyOverZq::from_str("3 1 2 3 mod 17").unwrap();
336 let z = PolyOverZ::from(2);
337
338 _ = z.clone() - poly.clone();
339 _ = &z - &poly;
340 _ = z.clone() - &poly;
341 _ = &z - poly.clone();
342 }
343}
344
345#[cfg(test)]
346mod test_sub_poly_ring_zq {
347 use super::PolynomialRingZq;
348 use crate::integer::PolyOverZ;
349 use std::str::FromStr;
350
351 #[test]
353 fn borrowed_correctness() {
354 let poly_1 =
355 PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 4 mod {}", i64::MAX, u64::MAX))
356 .unwrap();
357 let poly_2 = PolynomialRingZq::from_str(&format!(
358 "2 -1 -{} / 4 1 2 3 4 mod {}",
359 i64::MAX as u64 - 2,
360 u64::MAX
361 ))
362 .unwrap();
363 let poly = PolyOverZ::from_str("2 1 2").unwrap();
364
365 let poly_1 = &poly - &poly_1;
366
367 assert_eq!(poly_2, poly_1);
368 }
369
370 #[test]
372 fn availability() {
373 let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 4 mod 17").unwrap();
374 let z = PolyOverZ::from(2);
375
376 _ = z.clone() - poly.clone();
377 _ = &z - &poly;
378 _ = z.clone() - &poly;
379 _ = &z - poly.clone();
380 }
381}
382
383#[cfg(test)]
384mod test_mul_poly_over_q {
385 use super::PolyOverQ;
386 use crate::integer::PolyOverZ;
387 use std::str::FromStr;
388
389 #[test]
391 fn borrowed_correctness() {
392 let poly_1 = PolyOverZ::from_str("2 1 2").unwrap();
393 let poly_2 = PolyOverQ::from_str(&format!("1 1/{}", i64::MAX)).unwrap();
394 let poly_cmp =
395 PolyOverQ::from_str(&format!("2 {}/{} 2", i64::MAX as i128 - 1, i64::MAX)).unwrap();
396
397 let poly_1 = &poly_1 - &poly_2;
398
399 assert_eq!(poly_cmp, poly_1);
400 }
401
402 #[test]
404 fn availability() {
405 let poly = PolyOverQ::from_str("3 1/2 2 3/7").unwrap();
406 let z = PolyOverZ::from(2);
407
408 _ = z.clone() - poly.clone();
409 _ = &z - &poly;
410 _ = z.clone() - &poly;
411 _ = &z - poly.clone();
412 }
413}