qfall_math/integer/poly_over_z/reduce.rs
1// Copyright © 2023 Marvin Beckmann
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//! This module allows to simulate functionality of the polynomial ring `Z[X]/f(x)`
10//! by reducing a [`PolyOverZ`] by a [`PolyOverZ`] that
11//! has a leading coefficient of `1`.
12
13use super::{PolyOverZ, fmpz_poly_helpers::reduce_fmpz_poly_by_poly_over_z};
14
15impl PolyOverZ {
16 /// Reduces a polynomial by a polynomial `modulus`.
17 /// The modulus must have a leading coefficient of `1`, else the function will panic.
18 ///
19 /// Parameters:
20 /// - `modulus`: Specifies the polynomial by which `self` is reduced
21 ///
22 /// # Examples
23 /// ```
24 /// use qfall_math::integer::PolyOverZ;
25 /// use std::str::FromStr;
26 ///
27 /// let mut a = PolyOverZ::from_str("4 0 0 2 3").unwrap();
28 /// let modulus = PolyOverZ::from_str("3 0 1 1").unwrap();
29 ///
30 /// a.reduce_by_poly(&modulus);
31 ///
32 /// assert_eq!(PolyOverZ::from_str("2 0 1").unwrap(), a);
33 /// ```
34 ///
35 /// # Panics ...
36 /// - if the modulus does not have a leading coefficient of `1`.
37 pub fn reduce_by_poly(&mut self, modulus: &PolyOverZ) {
38 unsafe { reduce_fmpz_poly_by_poly_over_z(&mut self.poly, modulus) }
39 }
40}
41
42#[cfg(test)]
43mod test_reduce_by_poly {
44 use crate::integer::PolyOverZ;
45 use std::str::FromStr;
46
47 /// Ensures that the reduction works properly for a fixed polynomial that has to be
48 /// reduce or more than one coefficient.
49 #[test]
50 fn reduce_more_than_once() {
51 let mut a = PolyOverZ::from_str("4 0 1 2 3").unwrap();
52 let modulus = PolyOverZ::from_str("3 0 1 1").unwrap();
53
54 a.reduce_by_poly(&modulus);
55
56 assert_eq!(PolyOverZ::from_str("2 0 2").unwrap(), a);
57 }
58
59 /// Ensures that the function panics, if the leading coefficient is not `1`.
60 #[test]
61 #[should_panic]
62 fn no_leading_zero() {
63 let mut a = PolyOverZ::from_str("3 1 2 3").unwrap();
64 let modulus = PolyOverZ::from_str("2 1 2").unwrap();
65
66 a.reduce_by_poly(&modulus);
67 }
68
69 /// Ensures that large coefficients are reduced properly.
70 #[test]
71 fn large_coefficients() {
72 let mut a = PolyOverZ::from_str(&format!("3 1 -{} -1", u64::MAX)).unwrap();
73 let modulus = PolyOverZ::from_str(&format!("2 {} 1", u64::MAX)).unwrap();
74
75 a.reduce_by_poly(&modulus);
76
77 assert_eq!(PolyOverZ::from(1), a);
78 }
79}