Skip to main content

malachite_nz/integer_polynomial/arithmetic/
div_exact.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::integer::Integer;
10use crate::integer_polynomial::IntegerPolynomial;
11use crate::natural::Natural;
12use malachite_base::num::arithmetic::traits::{DivExact, DivExactAssign, NegAssign};
13use malachite_base::num::basic::traits::One;
14use malachite_base::polynomial::Polynomial;
15
16impl DivExact<Integer> for IntegerPolynomial {
17    type Output = Self;
18
19    /// Divides an [`IntegerPolynomial`] by an [`Integer`], taking both by value. Every coefficient
20    /// of the polynomial must be exactly divisible by the [`Integer`]. If one isn't, this function
21    /// may panic or return a meaningless result.
22    ///
23    /// $$
24    /// f(p, c) = \frac{p}{c}.
25    /// $$
26    ///
27    /// A polynomial is divisible by $c$ exactly when $|c|$ divides its
28    /// [`content`](malachite_base::polynomial::Content::content), so that is how to check
29    /// beforehand.
30    ///
31    /// # Worst-case complexity
32    /// $T(n) = O(n \log n \log\log n)$
33    ///
34    /// $M(n) = O(n \log n)$
35    ///
36    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits in the
37    /// polynomial's coefficients.
38    ///
39    /// # Panics
40    /// Panics if `c` is zero. May panic if a coefficient of the polynomial is not divisible by `c`.
41    ///
42    /// # Examples
43    /// ```
44    /// use core::str::FromStr;
45    /// use malachite_base::num::arithmetic::traits::DivExact;
46    /// use malachite_base::num::basic::traits::Zero;
47    /// use malachite_nz::integer::Integer;
48    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
49    ///
50    /// let p = IntegerPolynomial::from_str("6*x^2-3*x+9").unwrap();
51    /// assert_eq!(
52    ///     p.clone().div_exact(Integer::from(3)).to_string(),
53    ///     "2*x^2-x+3"
54    /// );
55    /// assert_eq!(
56    ///     p.clone().div_exact(Integer::from(-3)).to_string(),
57    ///     "-2*x^2+x-3"
58    /// );
59    /// assert_eq!(
60    ///     IntegerPolynomial::ZERO.div_exact(Integer::from(5)),
61    ///     IntegerPolynomial::ZERO
62    /// );
63    /// ```
64    ///
65    /// This is equivalent to `fmpz_poly_scalar_divexact_fmpz` from
66    /// `fmpz_poly/scalar_divexact_fmpz.c`, FLINT 3.6.0.
67    #[inline]
68    fn div_exact(mut self, c: Integer) -> Self {
69        self.div_exact_assign(&c);
70        self
71    }
72}
73
74impl<'a> DivExact<&'a Integer> for IntegerPolynomial {
75    type Output = Self;
76
77    /// Divides an [`IntegerPolynomial`] by an [`Integer`], taking the polynomial by value and the
78    /// [`Integer`] by reference. Every coefficient of the polynomial must be exactly divisible by
79    /// the [`Integer`]. If one isn't, this function may panic or return a meaningless result.
80    ///
81    /// See the documentation for the [`DivExact`] implementation on [`IntegerPolynomial`] that
82    /// takes both arguments by value for details.
83    ///
84    /// # Worst-case complexity
85    /// $T(n) = O(n \log n \log\log n)$
86    ///
87    /// $M(n) = O(n \log n)$
88    ///
89    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits in the
90    /// polynomial's coefficients.
91    ///
92    /// # Panics
93    /// Panics if `c` is zero. May panic if a coefficient of the polynomial is not divisible by `c`.
94    ///
95    /// # Examples
96    /// ```
97    /// use core::str::FromStr;
98    /// use malachite_base::num::arithmetic::traits::DivExact;
99    /// use malachite_base::num::basic::traits::Zero;
100    /// use malachite_nz::integer::Integer;
101    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
102    ///
103    /// let p = IntegerPolynomial::from_str("6*x^2-3*x+9").unwrap();
104    /// assert_eq!(
105    ///     p.clone().div_exact(&Integer::from(3)).to_string(),
106    ///     "2*x^2-x+3"
107    /// );
108    /// assert_eq!(
109    ///     p.clone().div_exact(&Integer::from(-3)).to_string(),
110    ///     "-2*x^2+x-3"
111    /// );
112    /// assert_eq!(
113    ///     IntegerPolynomial::ZERO.div_exact(&Integer::from(5)),
114    ///     IntegerPolynomial::ZERO
115    /// );
116    /// ```
117    ///
118    /// This is equivalent to `fmpz_poly_scalar_divexact_fmpz` from
119    /// `fmpz_poly/scalar_divexact_fmpz.c`, FLINT 3.6.0.
120    #[inline]
121    fn div_exact(mut self, c: &'a Integer) -> Self {
122        self.div_exact_assign(c);
123        self
124    }
125}
126
127impl DivExact<Integer> for &IntegerPolynomial {
128    type Output = IntegerPolynomial;
129
130    /// Divides an [`IntegerPolynomial`] by an [`Integer`], taking the polynomial by reference and
131    /// the [`Integer`] by value. Every coefficient of the polynomial must be exactly divisible by
132    /// the [`Integer`]. If one isn't, this function may panic or return a meaningless result.
133    ///
134    /// See the documentation for the [`DivExact`] implementation on [`IntegerPolynomial`] that
135    /// takes both arguments by value for details.
136    ///
137    /// # Worst-case complexity
138    /// $T(n) = O(n \log n \log\log n)$
139    ///
140    /// $M(n) = O(n \log n)$
141    ///
142    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits in the
143    /// polynomial's coefficients.
144    ///
145    /// # Panics
146    /// Panics if `c` is zero. May panic if a coefficient of the polynomial is not divisible by `c`.
147    ///
148    /// # Examples
149    /// ```
150    /// use core::str::FromStr;
151    /// use malachite_base::num::arithmetic::traits::DivExact;
152    /// use malachite_base::num::basic::traits::Zero;
153    /// use malachite_nz::integer::Integer;
154    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
155    ///
156    /// let p = IntegerPolynomial::from_str("6*x^2-3*x+9").unwrap();
157    /// assert_eq!((&p).div_exact(Integer::from(3)).to_string(), "2*x^2-x+3");
158    /// assert_eq!((&p).div_exact(Integer::from(-3)).to_string(), "-2*x^2+x-3");
159    /// assert_eq!(
160    ///     IntegerPolynomial::ZERO.div_exact(Integer::from(5)),
161    ///     IntegerPolynomial::ZERO
162    /// );
163    /// ```
164    ///
165    /// This is equivalent to `fmpz_poly_scalar_divexact_fmpz` from
166    /// `fmpz_poly/scalar_divexact_fmpz.c`, FLINT 3.6.0.
167    #[inline]
168    fn div_exact(self, c: Integer) -> IntegerPolynomial {
169        self.div_exact(&c)
170    }
171}
172
173impl<'a> DivExact<&'a Integer> for &IntegerPolynomial {
174    type Output = IntegerPolynomial;
175
176    /// Divides an [`IntegerPolynomial`] by an [`Integer`], taking both by reference. Every
177    /// coefficient of the polynomial must be exactly divisible by the [`Integer`]. If one isn't,
178    /// this function may panic or return a meaningless result.
179    ///
180    /// See the documentation for the [`DivExact`] implementation on [`IntegerPolynomial`] that
181    /// takes both arguments by value for details.
182    ///
183    /// # Worst-case complexity
184    /// $T(n) = O(n \log n \log\log n)$
185    ///
186    /// $M(n) = O(n \log n)$
187    ///
188    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits in the
189    /// polynomial's coefficients.
190    ///
191    /// # Panics
192    /// Panics if `c` is zero. May panic if a coefficient of the polynomial is not divisible by `c`.
193    ///
194    /// # Examples
195    /// ```
196    /// use core::str::FromStr;
197    /// use malachite_base::num::arithmetic::traits::DivExact;
198    /// use malachite_base::num::basic::traits::Zero;
199    /// use malachite_nz::integer::Integer;
200    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
201    ///
202    /// let p = IntegerPolynomial::from_str("6*x^2-3*x+9").unwrap();
203    /// assert_eq!((&p).div_exact(&Integer::from(3)).to_string(), "2*x^2-x+3");
204    /// assert_eq!((&p).div_exact(&Integer::from(-3)).to_string(), "-2*x^2+x-3");
205    /// assert_eq!(
206    ///     IntegerPolynomial::ZERO.div_exact(&Integer::from(5)),
207    ///     IntegerPolynomial::ZERO
208    /// );
209    /// ```
210    ///
211    /// This is equivalent to `fmpz_poly_scalar_divexact_fmpz` from
212    /// `fmpz_poly/scalar_divexact_fmpz.c`, FLINT 3.6.0.
213    fn div_exact(self, c: &'a Integer) -> IntegerPolynomial {
214        assert_ne!(*c, 0u32, "division by zero");
215        // Only a coefficient that is not divisible by `c` can come out as zero, so trimming is what
216        // keeps even a meaningless result a valid polynomial.
217        IntegerPolynomial::from_coefficients_asc(match *c {
218            integer_one!() => self.coefficients.clone(),
219            integer_negative_one!() => self.coefficients.iter().map(|x| -x).collect(),
220            _ => self.coefficients.iter().map(|x| x.div_exact(c)).collect(),
221        })
222    }
223}
224
225impl DivExactAssign<Integer> for IntegerPolynomial {
226    /// Divides an [`IntegerPolynomial`] by an [`Integer`] in place, taking the [`Integer`] by
227    /// value. Every coefficient of the polynomial must be exactly divisible by the [`Integer`]. If
228    /// one isn't, this function may panic or leave a meaningless result.
229    ///
230    /// $$
231    /// p \gets \frac{p}{c}.
232    /// $$
233    ///
234    /// See the documentation for the [`DivExact`] implementation on [`IntegerPolynomial`] that
235    /// takes both arguments by value for details.
236    ///
237    /// # Worst-case complexity
238    /// $T(n) = O(n \log n \log\log n)$
239    ///
240    /// $M(n) = O(n \log n)$
241    ///
242    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits in the
243    /// polynomial's coefficients.
244    ///
245    /// # Panics
246    /// Panics if `c` is zero. May panic if a coefficient of the polynomial is not divisible by `c`.
247    ///
248    /// # Examples
249    /// ```
250    /// use core::str::FromStr;
251    /// use malachite_base::num::arithmetic::traits::DivExactAssign;
252    /// use malachite_nz::integer::Integer;
253    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
254    ///
255    /// let mut p = IntegerPolynomial::from_str("6*x^2-3*x+9").unwrap();
256    /// p.div_exact_assign(Integer::from(3));
257    /// assert_eq!(p.to_string(), "2*x^2-x+3");
258    ///
259    /// let mut p = IntegerPolynomial::from_str("6*x^2-3*x+9").unwrap();
260    /// p.div_exact_assign(Integer::from(-3));
261    /// assert_eq!(p.to_string(), "-2*x^2+x-3");
262    /// ```
263    ///
264    /// This is equivalent to `fmpz_poly_scalar_divexact_fmpz` from
265    /// `fmpz_poly/scalar_divexact_fmpz.c`, FLINT 3.6.0.
266    #[inline]
267    fn div_exact_assign(&mut self, c: Integer) {
268        self.div_exact_assign(&c);
269    }
270}
271
272impl<'a> DivExactAssign<&'a Integer> for IntegerPolynomial {
273    /// Divides an [`IntegerPolynomial`] by an [`Integer`] in place, taking the [`Integer`] by
274    /// reference. Every coefficient of the polynomial must be exactly divisible by the [`Integer`].
275    /// If one isn't, this function may panic or leave a meaningless result.
276    ///
277    /// $$
278    /// p \gets \frac{p}{c}.
279    /// $$
280    ///
281    /// See the documentation for the [`DivExact`] implementation on [`IntegerPolynomial`] that
282    /// takes both arguments by value for details.
283    ///
284    /// # Worst-case complexity
285    /// $T(n) = O(n \log n \log\log n)$
286    ///
287    /// $M(n) = O(n \log n)$
288    ///
289    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits in the
290    /// polynomial's coefficients.
291    ///
292    /// # Panics
293    /// Panics if `c` is zero. May panic if a coefficient of the polynomial is not divisible by `c`.
294    ///
295    /// # Examples
296    /// ```
297    /// use core::str::FromStr;
298    /// use malachite_base::num::arithmetic::traits::DivExactAssign;
299    /// use malachite_nz::integer::Integer;
300    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
301    ///
302    /// let mut p = IntegerPolynomial::from_str("6*x^2-3*x+9").unwrap();
303    /// p.div_exact_assign(&Integer::from(3));
304    /// assert_eq!(p.to_string(), "2*x^2-x+3");
305    ///
306    /// let mut p = IntegerPolynomial::from_str("6*x^2-3*x+9").unwrap();
307    /// p.div_exact_assign(&Integer::from(-3));
308    /// assert_eq!(p.to_string(), "-2*x^2+x-3");
309    /// ```
310    ///
311    /// This is equivalent to `fmpz_poly_scalar_divexact_fmpz` from
312    /// `fmpz_poly/scalar_divexact_fmpz.c`, FLINT 3.6.0.
313    fn div_exact_assign(&mut self, c: &'a Integer) {
314        assert_ne!(*c, 0u32, "division by zero");
315        match *c {
316            integer_one!() => {}
317            integer_negative_one!() => self.neg_assign(),
318            _ => {
319                for x in &mut self.coefficients {
320                    x.div_exact_assign(c);
321                }
322                // Only a coefficient that is not divisible by `c` can come out as zero, so trimming
323                // is what keeps even a meaningless result a valid polynomial.
324                self.trim();
325            }
326        }
327    }
328}