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}