qfall_math/integer_mod_q/polynomial_ring_zq/arithmetic/
sub.rs1use super::super::PolynomialRingZq;
12use crate::{
13 error::MathError,
14 integer::PolyOverZ,
15 integer_mod_q::PolyOverZq,
16 macros::arithmetics::{
17 arithmetic_assign_trait_borrowed_to_owned, arithmetic_trait_borrowed_to_owned,
18 arithmetic_trait_mixed_borrowed_owned,
19 },
20 traits::CompareBase,
21};
22use std::ops::{Sub, SubAssign};
23
24impl SubAssign<&PolynomialRingZq> for PolynomialRingZq {
25 fn sub_assign(&mut self, other: &Self) {
59 if !self.compare_base(other) {
60 panic!("{}", self.call_compare_base_error(other).unwrap());
61 }
62
63 self.poly -= &other.poly;
64 self.reduce();
65 }
66}
67impl SubAssign<&PolyOverZ> for PolynomialRingZq {
68 fn sub_assign(&mut self, other: &PolyOverZ) {
70 self.poly -= other;
71 self.reduce();
72 }
73}
74impl SubAssign<&PolyOverZq> for PolynomialRingZq {
75 fn sub_assign(&mut self, other: &PolyOverZq) {
80 if !self.compare_base(other) {
81 panic!("{}", self.call_compare_base_error(other).unwrap())
82 }
83 self.poly -= other.get_representative_least_nonnegative_residue();
84 self.reduce();
85 }
86}
87
88arithmetic_assign_trait_borrowed_to_owned!(
89 SubAssign,
90 sub_assign,
91 PolynomialRingZq,
92 PolynomialRingZq
93);
94arithmetic_assign_trait_borrowed_to_owned!(SubAssign, sub_assign, PolynomialRingZq, PolyOverZ);
95arithmetic_assign_trait_borrowed_to_owned!(SubAssign, sub_assign, PolynomialRingZq, PolyOverZq);
96
97impl Sub for &PolynomialRingZq {
98 type Output = PolynomialRingZq;
99 fn sub(self, other: Self) -> Self::Output {
129 self.sub_safe(other).unwrap()
130 }
131}
132
133impl Sub<&PolyOverZ> for &PolynomialRingZq {
134 type Output = PolynomialRingZq;
135 fn sub(self, other: &PolyOverZ) -> Self::Output {
158 let mut out = self.clone();
159 out -= other;
160 out
161 }
162}
163
164arithmetic_trait_borrowed_to_owned!(Sub, sub, PolynomialRingZq, PolyOverZ, PolynomialRingZq);
165arithmetic_trait_mixed_borrowed_owned!(Sub, sub, PolynomialRingZq, PolyOverZ, PolynomialRingZq);
166
167impl Sub<&PolyOverZq> for &PolynomialRingZq {
168 type Output = PolynomialRingZq;
169 fn sub(self, other: &PolyOverZq) -> Self::Output {
195 if !self.compare_base(other) {
196 panic!("{}", self.call_compare_base_error(other).unwrap())
197 }
198
199 let mut out = self.clone();
200 out -= &other.get_representative_least_nonnegative_residue();
201 out
202 }
203}
204
205arithmetic_trait_borrowed_to_owned!(Sub, sub, PolynomialRingZq, PolyOverZq, PolynomialRingZq);
206arithmetic_trait_mixed_borrowed_owned!(Sub, sub, PolynomialRingZq, PolyOverZq, PolynomialRingZq);
207
208impl PolynomialRingZq {
209 pub fn sub_safe(&self, other: &Self) -> Result<PolynomialRingZq, MathError> {
236 if !self.compare_base(other) {
237 return Err(self.call_compare_base_error(other).unwrap());
238 }
239 let mut out = self.clone();
240 out.poly -= &other.get_representative_least_nonnegative_residue();
241 out.reduce();
242 Ok(out)
243 }
244}
245
246arithmetic_trait_borrowed_to_owned!(
247 Sub,
248 sub,
249 PolynomialRingZq,
250 PolynomialRingZq,
251 PolynomialRingZq
252);
253arithmetic_trait_mixed_borrowed_owned!(
254 Sub,
255 sub,
256 PolynomialRingZq,
257 PolynomialRingZq,
258 PolynomialRingZq
259);
260
261#[cfg(test)]
262mod test_sub_assign {
263 use super::PolyOverZ;
264 use crate::integer_mod_q::{ModulusPolynomialRingZq, PolyOverZq, PolynomialRingZq};
265 use std::str::FromStr;
266
267 #[test]
269 fn correct_small() {
270 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
271 let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap();
272 let mut a = PolynomialRingZq::from((&poly_1, &modulus));
273 let poly_2 = PolyOverZ::from_str("4 -2 0 -3 1").unwrap();
274 let b = PolynomialRingZq::from((&poly_2, &modulus));
275 let cmp = PolynomialRingZq::from((&PolyOverZ::from_str("3 1 0 4").unwrap(), &modulus));
276
277 a -= b;
278
279 assert_eq!(cmp, a);
280 }
281
282 #[test]
284 fn correct_large() {
285 let modulus = ModulusPolynomialRingZq::from_str(&format!(
286 "4 {} 0 0 1 mod {}",
287 u64::MAX,
288 u64::MAX - 58
289 ))
290 .unwrap();
291 let poly_1 = PolyOverZ::from_str(&format!("4 {} 0 1 {}", u64::MAX, i64::MIN)).unwrap();
292 let mut a = PolynomialRingZq::from((&poly_1, &modulus));
293 let poly_2 = PolyOverZ::from_str(&format!("4 -{} 0 1 -{}", i64::MAX, i64::MAX)).unwrap();
294 let b = PolynomialRingZq::from((&poly_2, &modulus));
295 let cmp = PolynomialRingZq::from((
296 &PolyOverZ::from_str("1 9223372036854775923").unwrap(),
297 &modulus,
298 ));
299
300 a -= b;
301
302 assert_eq!(cmp, a);
303 }
304
305 #[test]
307 fn availability() {
308 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
309 let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap();
310 let mut a = PolynomialRingZq::from((&poly_1, &modulus));
311 let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap();
312 let b = PolynomialRingZq::from((&poly_2, &modulus));
313 let c = PolyOverZq::from((poly_2, 17));
314
315 a -= &b;
316 a -= b;
317 a -= &poly_1;
318 a -= poly_1;
319 a -= &c;
320 a -= c;
321 }
322
323 #[test]
325 #[should_panic]
326 fn mismatching_moduli() {
327 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
328 let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap();
329 let mut a = PolynomialRingZq::from((&poly_1, &modulus));
330 let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap();
331 let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap();
332 let b = PolynomialRingZq::from((&poly_2, &modulus));
333
334 a -= b;
335 }
336}
337
338#[cfg(test)]
339mod test_sub {
340 use crate::integer::PolyOverZ;
341 use crate::integer_mod_q::ModulusPolynomialRingZq;
342 use crate::integer_mod_q::PolynomialRingZq;
343 use std::str::FromStr;
344
345 #[test]
347 fn sub() {
348 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
349 let poly_1 = PolyOverZ::from_str("4 -1 0 1 2").unwrap();
350 let a = PolynomialRingZq::from((&poly_1, &modulus));
351 let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap();
352 let b = PolynomialRingZq::from((&poly_2, &modulus));
353 let c = a - b;
354 assert_eq!(
355 c,
356 PolynomialRingZq::from((&PolyOverZ::from_str("4 -3 0 -2 1").unwrap(), &modulus))
357 );
358 }
359
360 #[test]
362 fn sub_borrow() {
363 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
364 let poly_1 = PolyOverZ::from_str("4 -1 0 1 2").unwrap();
365 let a = PolynomialRingZq::from((&poly_1, &modulus));
366 let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap();
367 let b = PolynomialRingZq::from((&poly_2, &modulus));
368 let c = &a - &b;
369 assert_eq!(
370 c,
371 PolynomialRingZq::from((&PolyOverZ::from_str("4 -3 0 -2 1").unwrap(), &modulus))
372 );
373 }
374
375 #[test]
377 fn sub_first_borrowed() {
378 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
379 let poly_1 = PolyOverZ::from_str("4 -1 0 1 2").unwrap();
380 let a = PolynomialRingZq::from((&poly_1, &modulus));
381 let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap();
382 let b = PolynomialRingZq::from((&poly_2, &modulus));
383 let c = &a - b;
384 assert_eq!(
385 c,
386 PolynomialRingZq::from((&PolyOverZ::from_str("4 -3 0 -2 1").unwrap(), &modulus))
387 );
388 }
389
390 #[test]
392 fn sub_second_borrowed() {
393 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
394 let poly_1 = PolyOverZ::from_str("4 -1 0 1 2").unwrap();
395 let a = PolynomialRingZq::from((&poly_1, &modulus));
396 let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap();
397 let b = PolynomialRingZq::from((&poly_2, &modulus));
398 let c = a - &b;
399 assert_eq!(
400 c,
401 PolynomialRingZq::from((&PolyOverZ::from_str("4 -3 0 -2 1").unwrap(), &modulus))
402 );
403 }
404
405 #[test]
407 fn sub_reduce() {
408 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
409 let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap();
410 let a = PolynomialRingZq::from((&poly_1, &modulus));
411 let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap();
412 let b = PolynomialRingZq::from((&poly_2, &modulus));
413 let c = a - &b;
414 assert_eq!(
415 c,
416 PolynomialRingZq::from((&PolyOverZ::from_str("3 -3 0 -2").unwrap(), &modulus))
417 );
418 }
419
420 #[test]
422 fn sub_large_numbers() {
423 let modulus = ModulusPolynomialRingZq::from_str(&format!(
424 "4 {} 0 0 1 mod {}",
425 u64::MAX,
426 u64::MAX - 58
427 ))
428 .unwrap();
429
430 let poly_1 = PolyOverZ::from_str(&format!("4 {} 0 1 {}", u64::MAX, i64::MIN)).unwrap();
431 let a = PolynomialRingZq::from((&poly_1, &modulus));
432
433 let poly_2 = PolyOverZ::from_str(&format!("4 {} 0 -1 {}", i64::MAX, i64::MAX)).unwrap();
434 let b = PolynomialRingZq::from((&poly_2, &modulus));
435
436 let c = a - b;
437
438 assert_eq!(
439 c,
440 PolynomialRingZq::from((
441 &PolyOverZ::from_str(&format!(
442 "4 {} 0 2 {}",
443 (u64::MAX - 1) / 2 + 1,
444 -18446744073709551615_i128
445 ))
446 .unwrap(),
447 &modulus
448 ))
449 );
450 }
451
452 #[test]
454 #[should_panic]
455 fn sub_mismatching_modulus() {
456 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
457 let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap();
458 let a = PolynomialRingZq::from((&poly_1, &modulus));
459 let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap();
460 let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap();
461 let b = PolynomialRingZq::from((&poly_2, &modulus));
462 let _ = a - b;
463 }
464
465 #[test]
467 fn sub_safe_is_err() {
468 let modulus = ModulusPolynomialRingZq::from_str("4 1 0 0 1 mod 17").unwrap();
469 let poly_1 = PolyOverZ::from_str("4 -1 0 1 1").unwrap();
470 let a = PolynomialRingZq::from((&poly_1, &modulus));
471 let modulus = ModulusPolynomialRingZq::from_str("4 2 0 0 1 mod 17").unwrap();
472 let poly_2 = PolyOverZ::from_str("4 2 0 3 1").unwrap();
473 let b = PolynomialRingZq::from((&poly_2, &modulus));
474
475 assert!(&a.sub_safe(&b).is_err());
476 }
477}
478
479#[cfg(test)]
480mod test_sub_poly_over_z {
481 use super::PolynomialRingZq;
482 use crate::integer::PolyOverZ;
483 use std::str::FromStr;
484
485 #[test]
487 fn borrowed_correctness() {
488 let poly_1 =
489 PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX))
490 .unwrap();
491 let poly_2 = PolynomialRingZq::from_str(&format!(
492 "2 1 {} / 4 1 2 3 1 mod {}",
493 i64::MAX as u64 - 2,
494 u64::MAX
495 ))
496 .unwrap();
497 let poly = PolyOverZ::from_str("2 1 2").unwrap();
498
499 let poly_1 = &poly_1 - &poly;
500
501 assert_eq!(poly_2, poly_1);
502 }
503
504 #[test]
506 fn availability() {
507 let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap();
508 let z = PolyOverZ::from(2);
509
510 _ = poly.clone() - z.clone();
511 _ = &poly - &z;
512 _ = &poly - z.clone();
513 _ = poly.clone() - &z;
514 }
515}
516
517#[cfg(test)]
518mod test_sub_poly_over_zq {
519 use super::PolynomialRingZq;
520 use crate::integer_mod_q::PolyOverZq;
521 use std::str::FromStr;
522
523 #[test]
525 fn borrowed_correctness() {
526 let poly_1 =
527 PolynomialRingZq::from_str(&format!("2 2 {} / 4 1 2 3 1 mod {}", i64::MAX, u64::MAX))
528 .unwrap();
529 let poly_2 = PolynomialRingZq::from_str(&format!(
530 "2 1 {} / 4 1 2 3 1 mod {}",
531 i64::MAX as u64 - 1,
532 u64::MAX
533 ))
534 .unwrap();
535 let poly = PolyOverZq::from_str(&format!("2 1 1 mod {}", u64::MAX)).unwrap();
536
537 let poly_1 = &poly_1 - &poly;
538
539 assert_eq!(poly_2, poly_1);
540 }
541
542 #[test]
544 fn availability() {
545 let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap();
546 let zq = PolyOverZq::from((2, 17));
547
548 _ = poly.clone() - zq.clone();
549 _ = &poly - &zq;
550 _ = &poly - zq.clone();
551 _ = poly.clone() - &zq;
552 }
553
554 #[test]
556 #[should_panic]
557 fn different_moduli_panic() {
558 let poly = PolynomialRingZq::from_str("3 1 2 3 / 4 1 2 3 1 mod 17").unwrap();
559 let zq = PolyOverZq::from((2, 16));
560
561 _ = &poly - &zq;
562 }
563}