Skip to main content

malachite_nz/integer_polynomial/
mod.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::conversion::string::from_string::from_string_with;
11use crate::integer_polynomial::conversion::string::to_string::Language;
12use alloc::string::String;
13use alloc::vec;
14use alloc::vec::Vec;
15use core::ops::Deref;
16use malachite_base::named::Named;
17use malachite_base::num::basic::traits::{NegativeOne, One, Two, Zero};
18use malachite_base::num::conversion::traits::ExactFrom;
19use malachite_base::polynomial::Polynomial;
20use malachite_base::vars::{Var, VarScheme};
21
22/// Traits for arithmetic on [`IntegerPolynomial`]s.
23pub mod arithmetic;
24/// Implementations of [`Ord`] and [`PartialOrd`] for [`IntegerPolynomial`], comparing two
25/// polynomials by their behavior for large arguments.
26pub mod comparison;
27/// Functions for converting an [`IntegerPolynomial`] to and from other types.
28pub mod conversion;
29/// Iterators that generate [`IntegerPolynomial`]s without repetition.
30pub mod exhaustive;
31#[cfg(feature = "random")]
32/// Iterators that generate [`IntegerPolynomial`]s randomly.
33pub mod random;
34
35// The zero `Integer`, as something a reference can be handed out to.
36//
37// A `Integer` owns a `Vec` when it is large, so it has a destructor, and a `&Integer::ZERO` written
38// where a reference is returned would point at a temporary that does not outlive the call. A
39// `static` is the same zero with a lifetime long enough to hand out.
40pub(crate) static ZERO: Integer = Integer::ZERO;
41
42/// A polynomial in one variable whose coefficients are [`Integer`]s.
43///
44/// The coefficients are held in ascending order, so that the coefficient of $x^i$ is the one at
45/// index $i$, and the last is the leading one. Trailing zero coefficients are not held at all: the
46/// zero polynomial has no coefficients, and every other polynomial's last coefficient is nonzero.
47/// That is what makes a polynomial's representation unique, and so what lets [`Eq`] be derived.
48///
49/// The field is private, since not every [`Vec`] of [`Integer`]s is one:
50/// [`from_coefficients_asc`](IntegerPolynomial::from_coefficients_asc) is how a [`Vec`] becomes
51/// one.
52#[derive(Clone, Default, Eq, Hash, PartialEq)]
53#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
54#[cfg_attr(
55    feature = "serde",
56    serde(try_from = "SerdeIntegerPolynomial", into = "SerdeIntegerPolynomial")
57)]
58pub struct IntegerPolynomial {
59    coefficients: Vec<Integer>,
60}
61
62// As for a `NaturalPolynomial`: the coefficients are the polynomial, so the encoding is the list of
63// them and nothing around it, and a list whose last coefficient is zero is rejected.
64#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
65#[cfg_attr(feature = "serde", serde(transparent))]
66pub(crate) struct SerdeIntegerPolynomial(pub(crate) Vec<Integer>);
67
68/// The constant 0.
69impl Zero for IntegerPolynomial {
70    const ZERO: Self = Self {
71        coefficients: Vec::new(),
72    };
73}
74
75impl IntegerPolynomial {
76    // Returns true iff `self` is valid.
77    //
78    // To be valid, its last coefficient, if it has one at all, must be nonzero. All
79    // `IntegerPolynomial`s must be valid.
80    #[cfg(feature = "test_build")]
81    pub fn is_valid(&self) -> bool {
82        self.coefficients.last() != Some(&Integer::ZERO)
83    }
84
85    // Drops the trailing zero coefficients, which is what makes a `Vec` of coefficients the one
86    // representation of its polynomial.
87    fn trim(&mut self) {
88        while self.coefficients.last() == Some(&Integer::ZERO) {
89            self.coefficients.pop();
90        }
91    }
92
93    /// The constant polynomial -1.
94    ///
95    /// This is a function rather than an associated constant, for the reason given by
96    /// [`one`](Self::one).
97    ///
98    /// # Worst-case complexity
99    /// Constant time and additional memory.
100    ///
101    /// # Examples
102    /// ```
103    /// use malachite_base::polynomial::Polynomial;
104    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
105    ///
106    /// assert_eq!(IntegerPolynomial::negative_one().to_string(), "-1");
107    /// assert_eq!(IntegerPolynomial::negative_one().degree(), Some(0));
108    /// ```
109    pub fn negative_one() -> Self {
110        Self {
111            coefficients: vec![Integer::NEGATIVE_ONE],
112        }
113    }
114
115    /// Returns a reference to an [`IntegerPolynomial`]'s coefficients, in ascending order.
116    ///
117    /// The first is the constant term and the last is the leading coefficient, so the slice is what
118    /// [`from_coefficients_asc`](Self::from_coefficients_asc) would take back. It holds no trailing
119    /// zeros, and for the zero polynomial it is empty.
120    ///
121    /// # Worst-case complexity
122    /// Constant time and additional memory.
123    ///
124    /// # Examples
125    /// ```
126    /// use core::str::FromStr;
127    /// use malachite_base::num::basic::traits::Zero;
128    /// use malachite_base::strings::ToDebugString;
129    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
130    ///
131    /// let p = IntegerPolynomial::from_str("x^2+3*x+2").unwrap();
132    /// assert_eq!(p.coefficients_asc().to_debug_string(), "[2, 3, 1]");
133    /// assert_eq!(
134    ///     IntegerPolynomial::ZERO.coefficients_asc().to_debug_string(),
135    ///     "[]"
136    /// );
137    /// ```
138    #[inline]
139    pub fn coefficients_asc(&self) -> &[Integer] {
140        &self.coefficients
141    }
142}
143
144impl Polynomial for IntegerPolynomial {
145    type Coefficient = Integer;
146    type CoefficientOutput<'a>
147        = &'a Integer
148    where
149        Self: 'a;
150
151    /// The constant polynomial 1.
152    ///
153    /// This is a function rather than an associated constant, and [`One`] is not implemented,
154    /// because a polynomial holds its coefficients in a [`Vec`] and a [`Vec`] with anything in it
155    /// cannot be built at compile time. The zero polynomial has no coefficients, so
156    /// [`ZERO`](malachite_base::num::basic::traits::Zero::ZERO) is a constant after all.
157    ///
158    /// # Worst-case complexity
159    /// Constant time and additional memory.
160    ///
161    /// # Examples
162    /// ```
163    /// use malachite_base::polynomial::Polynomial;
164    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
165    ///
166    /// assert_eq!(IntegerPolynomial::one().to_string(), "1");
167    /// assert_eq!(IntegerPolynomial::one().degree(), Some(0));
168    /// ```
169    fn one() -> Self {
170        Self {
171            coefficients: vec![Integer::ONE],
172        }
173    }
174
175    /// The constant polynomial 2.
176    ///
177    /// This is a function rather than an associated constant, for the reason given by
178    /// [`one`](Self::one).
179    ///
180    /// # Worst-case complexity
181    /// Constant time and additional memory.
182    ///
183    /// # Examples
184    /// ```
185    /// use malachite_base::polynomial::Polynomial;
186    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
187    ///
188    /// assert_eq!(IntegerPolynomial::two().to_string(), "2");
189    /// assert_eq!(IntegerPolynomial::two().degree(), Some(0));
190    /// ```
191    fn two() -> Self {
192        Self {
193            coefficients: vec![Integer::TWO],
194        }
195    }
196
197    /// The polynomial $x$, of degree 1 with leading coefficient 1 and constant term 0.
198    ///
199    /// This is a function rather than an associated constant, for the reason given by
200    /// [`one`](Self::one).
201    ///
202    /// # Worst-case complexity
203    /// Constant time and additional memory.
204    ///
205    /// # Examples
206    /// ```
207    /// use malachite_base::polynomial::Polynomial;
208    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
209    ///
210    /// assert_eq!(IntegerPolynomial::x().to_string(), "x");
211    /// assert_eq!(IntegerPolynomial::x().degree(), Some(1));
212    /// ```
213    fn x() -> Self {
214        Self {
215            coefficients: vec![Integer::ZERO, Integer::ONE],
216        }
217    }
218
219    /// Converts a [`Vec`] of [`Integer`]s to an [`IntegerPolynomial`].
220    ///
221    /// The coefficients are in ascending order, so that the first is the constant term. Trailing
222    /// zeros are dropped, since a polynomial does not hold them; the [`Vec`] may therefore end with
223    /// as many as it likes, and the empty [`Vec`] is the zero polynomial.
224    ///
225    /// # Worst-case complexity
226    /// $T(n) = O(n)$
227    ///
228    /// $M(n) = O(1)$
229    ///
230    /// where $T$ is time, $M$ is additional memory, and $n$ is `coefficients.len()`.
231    ///
232    /// # Examples
233    /// ```
234    /// use malachite_base::num::basic::traits::{One, Two, Zero};
235    /// use malachite_base::polynomial::Polynomial;
236    /// use malachite_nz::integer::Integer;
237    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
238    ///
239    /// let p = IntegerPolynomial::from_coefficients_asc(vec![
240    ///     Integer::TWO,
241    ///     Integer::from(3u32),
242    ///     Integer::ONE,
243    /// ]);
244    /// assert_eq!(p.to_string(), "x^2+3*x+2");
245    ///
246    /// // The trailing zeros are not part of the polynomial.
247    /// let q = IntegerPolynomial::from_coefficients_asc(vec![
248    ///     Integer::TWO,
249    ///     Integer::from(3u32),
250    ///     Integer::ONE,
251    ///     Integer::ZERO,
252    ///     Integer::ZERO,
253    /// ]);
254    /// assert_eq!(q.to_string(), "x^2+3*x+2");
255    ///
256    /// assert_eq!(
257    ///     IntegerPolynomial::from_coefficients_asc(vec![]).to_string(),
258    ///     "0"
259    /// );
260    /// ```
261    fn from_coefficients_asc(coefficients: Vec<Integer>) -> Self {
262        let mut p = Self { coefficients };
263        p.trim();
264        p
265    }
266
267    /// Converts an [`IntegerPolynomial`] to a [`Vec`] of [`Integer`]s, in ascending order.
268    ///
269    /// The first is the constant term and the last is the leading coefficient, so the [`Vec`] is
270    /// what [`from_coefficients_asc`](Self::from_coefficients_asc) would take back. It holds no
271    /// trailing zeros, and for the zero polynomial it is empty.
272    ///
273    /// # Worst-case complexity
274    /// Constant time and additional memory.
275    ///
276    /// # Examples
277    /// ```
278    /// use core::str::FromStr;
279    /// use malachite_base::num::basic::traits::Zero;
280    /// use malachite_base::polynomial::Polynomial;
281    /// use malachite_base::strings::ToDebugString;
282    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
283    ///
284    /// let p = IntegerPolynomial::from_str("x^2+3*x+2").unwrap();
285    /// assert_eq!(p.into_coefficients_asc().to_debug_string(), "[2, 3, 1]");
286    /// assert_eq!(
287    ///     IntegerPolynomial::ZERO
288    ///         .into_coefficients_asc()
289    ///         .to_debug_string(),
290    ///     "[]"
291    /// );
292    /// ```
293    #[inline]
294    fn into_coefficients_asc(self) -> Vec<Integer> {
295        self.coefficients
296    }
297
298    /// Returns the degree of an [`IntegerPolynomial`].
299    ///
300    /// The zero polynomial has no degree, and gives `None`. Every other polynomial's degree is the
301    /// index of its leading coefficient, so that a nonzero constant has degree 0.
302    ///
303    /// # Worst-case complexity
304    /// Constant time and additional memory.
305    ///
306    /// # Examples
307    /// ```
308    /// use core::str::FromStr;
309    /// use malachite_base::num::basic::traits::Zero;
310    /// use malachite_base::polynomial::Polynomial;
311    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
312    ///
313    /// assert_eq!(IntegerPolynomial::ZERO.degree(), None);
314    /// assert_eq!(IntegerPolynomial::from_str("5").unwrap().degree(), Some(0));
315    /// assert_eq!(IntegerPolynomial::from_str("x").unwrap().degree(), Some(1));
316    /// assert_eq!(
317    ///     IntegerPolynomial::from_str("x^2+3*x+2").unwrap().degree(),
318    ///     Some(2)
319    /// );
320    /// ```
321    #[inline]
322    fn degree(&self) -> Option<u64> {
323        self.coefficients.len().checked_sub(1).map(u64::exact_from)
324    }
325
326    /// Returns the length of a [`IntegerPolynomial`]: the number of coefficients it holds.
327    ///
328    /// A polynomial holds no trailing zeros, so its length is one more than its
329    /// [`degree`](Self::degree), and the zero polynomial, which has no degree, has length 0.
330    ///
331    /// # Worst-case complexity
332    /// Constant time and additional memory.
333    ///
334    /// # Examples
335    /// ```
336    /// use core::str::FromStr;
337    /// use malachite_base::num::basic::traits::Zero;
338    /// use malachite_base::polynomial::Polynomial;
339    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
340    ///
341    /// assert_eq!(IntegerPolynomial::ZERO.len(), 0);
342    /// assert_eq!(IntegerPolynomial::from_str("-5").unwrap().len(), 1);
343    /// assert_eq!(IntegerPolynomial::from_str("x").unwrap().len(), 2);
344    /// assert_eq!(IntegerPolynomial::from_str("x^2-3*x+2").unwrap().len(), 3);
345    /// ```
346    ///
347    /// This is equivalent to `fmpz_poly_length` from `fmpz_poly.h`, FLINT 3.6.0.
348    #[inline]
349    fn len(&self) -> u64 {
350        u64::exact_from(self.coefficients.len())
351    }
352
353    /// Returns a reference to one of an [`IntegerPolynomial`]'s coefficients.
354    ///
355    /// The index is the power of the variable the coefficient belongs to, so that index 0 gives the
356    /// constant term. An index past the degree gives zero, which is the coefficient a polynomial
357    /// has there.
358    ///
359    /// # Worst-case complexity
360    /// Constant time and additional memory.
361    ///
362    /// # Examples
363    /// ```
364    /// use core::str::FromStr;
365    /// use malachite_base::polynomial::Polynomial;
366    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
367    ///
368    /// let p = IntegerPolynomial::from_str("x^2+3*x+2").unwrap();
369    /// assert_eq!(*p.coefficient(0), 2);
370    /// assert_eq!(*p.coefficient(1), 3);
371    /// assert_eq!(*p.coefficient(2), 1);
372    /// assert_eq!(*p.coefficient(100), 0);
373    /// ```
374    #[inline]
375    fn coefficient(&self, index: u64) -> &Integer {
376        usize::try_from(index)
377            .ok()
378            .and_then(|i| self.coefficients.get(i))
379            .unwrap_or(&ZERO)
380    }
381
382    /// Returns a reference to an [`IntegerPolynomial`]'s leading coefficient.
383    ///
384    /// This is the coefficient of the highest power of the variable that the polynomial has one
385    /// for. The zero polynomial has no such power, and gives zero, which is what every one of its
386    /// coefficients is.
387    ///
388    /// # Worst-case complexity
389    /// Constant time and additional memory.
390    ///
391    /// # Examples
392    /// ```
393    /// use core::str::FromStr;
394    /// use malachite_base::num::basic::traits::Zero;
395    /// use malachite_base::polynomial::Polynomial;
396    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
397    ///
398    /// let p = IntegerPolynomial::from_str("7*x^2+3*x+2").unwrap();
399    /// assert_eq!(*p.leading_coefficient(), 7);
400    /// assert_eq!(*IntegerPolynomial::ZERO.leading_coefficient(), 0);
401    /// ```
402    #[inline]
403    fn leading_coefficient(&self) -> &Integer {
404        self.coefficients.last().unwrap_or(&ZERO)
405    }
406
407    /// Determines whether an [`IntegerPolynomial`] is monic: nonzero, with leading coefficient 1.
408    ///
409    /// The zero polynomial is not monic.
410    ///
411    /// # Worst-case complexity
412    /// Constant time and additional memory.
413    ///
414    /// # Examples
415    /// ```
416    /// use core::str::FromStr;
417    /// use malachite_base::num::basic::traits::Zero;
418    /// use malachite_base::polynomial::Polynomial;
419    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
420    ///
421    /// assert!(IntegerPolynomial::from_str("x^2-3*x+2").unwrap().is_monic());
422    /// assert!(!IntegerPolynomial::from_str("-x^2+3").unwrap().is_monic());
423    /// assert!(!IntegerPolynomial::ZERO.is_monic());
424    /// ```
425    #[inline]
426    fn is_monic(&self) -> bool {
427        self.coefficients.last().is_some_and(|c| *c == 1u32)
428    }
429
430    /// Mutates one of an [`IntegerPolynomial`]'s coefficients using a provided closure, and then
431    /// returns whatever the closure returns.
432    ///
433    /// The index is the power of the variable the coefficient belongs to. An index past the degree
434    /// is not an error: the polynomial grows to reach it, and the closure is handed the zero that
435    /// was there all along.
436    ///
437    /// After the closure executes, this function drops whatever trailing zero coefficients the
438    /// polynomial has acquired, so that a coefficient set to zero, or a growth that came to
439    /// nothing, leaves no trace.
440    ///
441    /// # Worst-case complexity
442    /// $T(n, m) = O(n + m)$
443    ///
444    /// $M(n, m) = O(n + m)$
445    ///
446    /// where $T$ is time, $M$ is additional memory, $n$ is `index`, and $m$ is the cost of the
447    /// closure.
448    ///
449    /// # Panics
450    /// Panics if `index` does not fit in a [`usize`], which cannot happen on a target with 64-bit
451    /// pointers, or if growing to reach `index` would exceed the maximum length of a [`Vec`].
452    ///
453    /// # Examples
454    /// ```
455    /// use core::str::FromStr;
456    /// use malachite_base::num::basic::traits::{One, Zero};
457    /// use malachite_base::polynomial::Polynomial;
458    /// use malachite_nz::integer::Integer;
459    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
460    ///
461    /// let mut p = IntegerPolynomial::from_str("x^2+3*x+2").unwrap();
462    ///
463    /// let ret = p.mutate_coefficient(1, |c| {
464    ///     *c += Integer::ONE;
465    ///     true
466    /// });
467    /// assert_eq!(p.to_string(), "x^2+4*x+2");
468    /// assert_eq!(ret, true);
469    ///
470    /// // The polynomial grows to reach a coefficient it did not have.
471    /// p.mutate_coefficient(5, |c| *c += Integer::ONE);
472    /// assert_eq!(p.to_string(), "x^5+x^2+4*x+2");
473    ///
474    /// // Clearing the leading coefficient lowers the degree.
475    /// p.mutate_coefficient(5, |c| *c = Integer::ZERO);
476    /// assert_eq!(p.to_string(), "x^2+4*x+2");
477    /// ```
478    fn mutate_coefficient<F: FnOnce(&mut Integer) -> T, T>(&mut self, index: u64, f: F) -> T {
479        let index = usize::exact_from(index);
480        if index >= self.coefficients.len() {
481            self.coefficients.resize(index + 1, Integer::ZERO);
482        }
483        let out = f(&mut self.coefficients[index]);
484        self.trim();
485        out
486    }
487
488    /// Sets the coefficients of a [`IntegerPolynomial`] of $x^i$ for $i$ in `start..end` to zero.
489    ///
490    /// Indices past the degree are allowed; the coefficients there are zero already. Zeroing the
491    /// leading coefficient lowers the degree, to that of the highest nonzero coefficient that
492    /// remains.
493    ///
494    /// # Worst-case complexity
495    /// $T(n) = O(n)$
496    ///
497    /// $M(n) = O(1)$
498    ///
499    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.len()`.
500    ///
501    /// # Panics
502    /// Panics if `start > end`.
503    ///
504    /// # Examples
505    /// ```
506    /// use core::str::FromStr;
507    /// use malachite_base::polynomial::Polynomial;
508    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
509    ///
510    /// let mut p;
511    /// p = IntegerPolynomial::from_str("5*x^4-4*x^3+3*x^2-2*x+1").unwrap();
512    /// p.zero_coefficients(1, 3);
513    /// assert_eq!(p.to_string(), "5*x^4-4*x^3+1");
514    /// p = IntegerPolynomial::from_str("5*x^4-4*x^3+3*x^2-2*x+1").unwrap();
515    /// p.zero_coefficients(2, 10);
516    /// assert_eq!(p.to_string(), "-2*x+1");
517    /// p = IntegerPolynomial::from_str("5*x^4-4*x^3+3*x^2-2*x+1").unwrap();
518    /// p.zero_coefficients(5, 10);
519    /// assert_eq!(p.to_string(), "5*x^4-4*x^3+3*x^2-2*x+1");
520    /// ```
521    ///
522    /// This is equivalent to `fmpz_poly_zero_coeffs` from `fmpz_poly/zero_coeffs.c`, FLINT 3.6.0.
523    fn zero_coefficients(&mut self, start: u64, end: u64) {
524        assert!(start <= end);
525        let len = self.coefficients.len();
526        let Ok(start) = usize::try_from(start) else {
527            return;
528        };
529        if start >= len {
530            return;
531        }
532        let end = usize::try_from(end).map_or(len, |end| end.min(len));
533        if end == len {
534            // The range reaches the leading coefficient, so the zeros it leaves are trailing.
535            self.coefficients.truncate(start);
536            self.trim();
537        } else {
538            self.coefficients[start..end].fill(Integer::ZERO);
539        }
540    }
541
542    /// Truncates a [`IntegerPolynomial`] to its first `len` coefficients, taking the polynomial by
543    /// reference and returning the result.
544    ///
545    /// The result is the polynomial reduced modulo $x^{\mathrm{len}}$: every term of degree `len`
546    /// or more is dropped, and then any zeros left at the top go too, so the result may have fewer
547    /// than `len` coefficients. A polynomial with at most `len` coefficients is returned unchanged.
548    ///
549    /// $$
550    /// f(p, n) = p \bmod x^n.
551    /// $$
552    ///
553    /// # Worst-case complexity
554    /// $T(n) = O(n)$
555    ///
556    /// $M(n) = O(n)$
557    ///
558    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
559    /// coefficients that are kept.
560    ///
561    /// # Examples
562    /// ```
563    /// use core::str::FromStr;
564    /// use malachite_base::polynomial::Polynomial;
565    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
566    ///
567    /// assert_eq!(
568    ///     IntegerPolynomial::from_str("x^3-2*x^2+3*x-4")
569    ///         .unwrap()
570    ///         .truncate(2)
571    ///         .to_string(),
572    ///     "3*x-4"
573    /// );
574    /// // A polynomial with no more than len coefficients is unchanged.
575    /// assert_eq!(
576    ///     IntegerPolynomial::from_str("x^3-2*x^2+3*x-4")
577    ///         .unwrap()
578    ///         .truncate(10)
579    ///         .to_string(),
580    ///     "x^3-2*x^2+3*x-4"
581    /// );
582    /// // Truncating can uncover zeros, which are dropped too.
583    /// assert_eq!(
584    ///     IntegerPolynomial::from_str("x^3+3*x-4")
585    ///         .unwrap()
586    ///         .truncate(3)
587    ///         .to_string(),
588    ///     "3*x-4"
589    /// );
590    /// assert_eq!(
591    ///     IntegerPolynomial::from_str("x^3-2*x^2+3*x-4")
592    ///         .unwrap()
593    ///         .truncate(0)
594    ///         .to_string(),
595    ///     "0"
596    /// );
597    /// ```
598    ///
599    /// This is equivalent to `fmpz_poly_set_trunc` from `fmpz_poly/set_trunc.c`, FLINT 3.6.0.
600    fn truncate(&self, len: u64) -> Self {
601        let kept = usize::try_from(len).map_or(self.coefficients.len(), |len| {
602            len.min(self.coefficients.len())
603        });
604        // Skip the zeros that truncating leaves at the top rather than copying them and trimming.
605        let kept = self.coefficients[..kept]
606            .iter()
607            .rposition(|c| *c != 0u32)
608            .map_or(0, |i| i + 1);
609        Self {
610            coefficients: self.coefficients[..kept].to_vec(),
611        }
612    }
613
614    /// Truncates a [`IntegerPolynomial`] to its first `len` coefficients, in place.
615    ///
616    /// See [`truncate`](Self::truncate) for what the result is.
617    ///
618    /// # Worst-case complexity
619    /// $T(n) = O(n)$
620    ///
621    /// $M(n) = O(1)$
622    ///
623    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.len()`.
624    ///
625    /// # Examples
626    /// ```
627    /// use core::str::FromStr;
628    /// use malachite_base::polynomial::Polynomial;
629    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
630    ///
631    /// let mut p;
632    /// p = IntegerPolynomial::from_str("x^3-2*x^2+3*x-4").unwrap();
633    /// p.truncate_assign(2);
634    /// assert_eq!(p.to_string(), "3*x-4");
635    /// // A polynomial with no more than len coefficients is unchanged.
636    /// p = IntegerPolynomial::from_str("x^3-2*x^2+3*x-4").unwrap();
637    /// p.truncate_assign(10);
638    /// assert_eq!(p.to_string(), "x^3-2*x^2+3*x-4");
639    /// // Truncating can uncover zeros, which are dropped too.
640    /// p = IntegerPolynomial::from_str("x^3+3*x-4").unwrap();
641    /// p.truncate_assign(3);
642    /// assert_eq!(p.to_string(), "3*x-4");
643    /// p = IntegerPolynomial::from_str("x^3-2*x^2+3*x-4").unwrap();
644    /// p.truncate_assign(0);
645    /// assert_eq!(p.to_string(), "0");
646    /// ```
647    ///
648    /// This is equivalent to `fmpz_poly_truncate` from `fmpz_poly/truncate.c`, FLINT 3.6.0.
649    fn truncate_assign(&mut self, len: u64) {
650        if let Ok(len) = usize::try_from(len)
651            && len < self.coefficients.len()
652        {
653            self.coefficients.truncate(len);
654            self.trim();
655        }
656    }
657
658    /// Reverses the coefficients of a [`IntegerPolynomial`], considered as having length `len`,
659    /// taking the polynomial by reference.
660    ///
661    /// The polynomial is first truncated, or padded with zeros, to exactly `len` coefficients, and
662    /// those are then reversed, so that the result's coefficient of $x^i$ is the polynomial's
663    /// coefficient of $x^{\mathrm{len} - 1 - i}$:
664    ///
665    /// $$
666    /// f(p, n) = x^{n-1} \left( p \bmod x^n \right)\!\left(\frac{1}{x}\right).
667    /// $$
668    ///
669    /// A polynomial holds no trailing zeros, so the result may have fewer than `len` coefficients:
670    /// it does whenever the polynomial's constant term is zero.
671    ///
672    /// # Worst-case complexity
673    /// $T(n, m) = O(n + m)$
674    ///
675    /// $M(n, m) = O(n + m)$
676    ///
677    /// where $T$ is time, $M$ is additional memory, $n$ is `len`, and $m$ is the total number of
678    /// bits of the coefficients.
679    ///
680    /// # Panics
681    /// Panics if `len` exceeds `self.len()` and does not fit in a [`usize`], which cannot happen on
682    /// a target with 64-bit pointers.
683    ///
684    /// # Examples
685    /// ```
686    /// use core::str::FromStr;
687    /// use malachite_base::polynomial::Polynomial;
688    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
689    ///
690    /// assert_eq!(
691    ///     IntegerPolynomial::from_str("x^2-2*x+3")
692    ///         .unwrap()
693    ///         .reverse(3)
694    ///         .to_string(),
695    ///     "3*x^2-2*x+1"
696    /// );
697    /// // Padding to length 5 adds low zeros.
698    /// assert_eq!(
699    ///     IntegerPolynomial::from_str("x^2-2*x+3")
700    ///         .unwrap()
701    ///         .reverse(5)
702    ///         .to_string(),
703    ///     "3*x^4-2*x^3+x^2"
704    /// );
705    /// // Truncating to length 2 drops x^2 first.
706    /// assert_eq!(
707    ///     IntegerPolynomial::from_str("x^2-2*x+3")
708    ///         .unwrap()
709    ///         .reverse(2)
710    ///         .to_string(),
711    ///     "3*x-2"
712    /// );
713    /// // A zero constant term becomes a trailing zero, and is dropped.
714    /// assert_eq!(
715    ///     IntegerPolynomial::from_str("x^2-2*x")
716    ///         .unwrap()
717    ///         .reverse(3)
718    ///         .to_string(),
719    ///     "-2*x+1"
720    /// );
721    /// ```
722    ///
723    /// This is equivalent to `fmpz_poly_reverse` from `fmpz_poly/reverse.c`, FLINT 3.6.0.
724    fn reverse(&self, len: u64) -> Self {
725        let kept = usize::try_from(len).map_or(self.coefficients.len(), |len| {
726            len.min(self.coefficients.len())
727        });
728        if kept == 0 {
729            return Self::ZERO;
730        }
731        // The coefficients past the kept ones become the result's low zeros.
732        let mut coefficients = vec![Integer::ZERO; usize::exact_from(len) - kept];
733        coefficients.extend(self.coefficients[..kept].iter().rev().cloned());
734        Self::from_coefficients_asc(coefficients)
735    }
736
737    /// Reverses the coefficients of a [`IntegerPolynomial`], considered as having length `len`, in
738    /// place.
739    ///
740    /// See [`reverse`](Self::reverse) for what the result is.
741    ///
742    /// # Worst-case complexity
743    /// $T(n) = O(n)$
744    ///
745    /// $M(n) = O(n)$
746    ///
747    /// where $T$ is time, $M$ is additional memory, and $n$ is the larger of `len` and
748    /// `self.len()`.
749    ///
750    /// # Panics
751    /// Panics if `len` exceeds `self.len()` and does not fit in a [`usize`], which cannot happen on
752    /// a target with 64-bit pointers.
753    ///
754    /// # Examples
755    /// ```
756    /// use core::str::FromStr;
757    /// use malachite_base::polynomial::Polynomial;
758    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
759    ///
760    /// let mut p;
761    /// p = IntegerPolynomial::from_str("x^2-2*x+3").unwrap();
762    /// p.reverse_assign(3);
763    /// assert_eq!(p.to_string(), "3*x^2-2*x+1");
764    /// // Padding to length 5 adds low zeros.
765    /// p = IntegerPolynomial::from_str("x^2-2*x+3").unwrap();
766    /// p.reverse_assign(5);
767    /// assert_eq!(p.to_string(), "3*x^4-2*x^3+x^2");
768    /// // Truncating to length 2 drops x^2 first.
769    /// p = IntegerPolynomial::from_str("x^2-2*x+3").unwrap();
770    /// p.reverse_assign(2);
771    /// assert_eq!(p.to_string(), "3*x-2");
772    /// // A zero constant term becomes a trailing zero, and is dropped.
773    /// p = IntegerPolynomial::from_str("x^2-2*x").unwrap();
774    /// p.reverse_assign(3);
775    /// assert_eq!(p.to_string(), "-2*x+1");
776    /// ```
777    ///
778    /// This is equivalent to `fmpz_poly_reverse` from `fmpz_poly/reverse.c`, FLINT 3.6.0.
779    fn reverse_assign(&mut self, len: u64) {
780        let kept = usize::try_from(len).map_or(self.coefficients.len(), |len| {
781            len.min(self.coefficients.len())
782        });
783        if kept == 0 {
784            *self = Self::ZERO;
785            return;
786        }
787        self.coefficients.truncate(kept);
788        self.coefficients.reverse();
789        // Pad at the high end and rotate the padding down, so that it becomes the low zeros.
790        let len = usize::exact_from(len);
791        self.coefficients.resize(len, Integer::ZERO);
792        self.coefficients.rotate_right(len - kept);
793        // The polynomial's low zeros, if any, are now at the top.
794        self.trim();
795    }
796
797    /// Converts an [`IntegerPolynomial`] to a [`String`], naming its variable with any
798    /// [`VarScheme`].
799    ///
800    /// The syntax is the one [`Display`](core::fmt::Display) writes, which that implementation
801    /// describes; the only difference is that the variable is whichever one is handed in rather
802    /// than `x`.
803    ///
804    /// # Worst-case complexity
805    /// $T(n) = O(n \log n \log\log n)$
806    ///
807    /// $M(n) = O(n \log n)$
808    ///
809    /// where $T$ is time, $M$ is additional memory, and $n$ is the sum of the bits of the
810    /// coefficients.
811    ///
812    /// # Panics
813    /// Panics if `var`'s index is not less than its scheme's [`capacity`](VarScheme::capacity).
814    ///
815    /// # Examples
816    /// ```
817    /// use core::str::FromStr;
818    /// use malachite_base::polynomial::Polynomial;
819    /// use malachite_base::vars::VarScheme;
820    /// use malachite_base::vars::greek::GreekVars;
821    /// use malachite_base::vars::indexed::IndexedVars;
822    /// use malachite_base::vars::list::ListVars;
823    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
824    ///
825    /// let p = IntegerPolynomial::from_str("x^2+3*x+2").unwrap();
826    /// assert_eq!(p.to_string_with(GreekVars.var(0)), "α^2+3*α+2");
827    /// assert_eq!(p.to_string_with(IndexedVars.var(7)), "x₇^2+3*x₇+2");
828    ///
829    /// let vars = ListVars::new(["t"]);
830    /// assert_eq!(p.to_string_with(vars.var(0)), "t^2+3*t+2");
831    /// ```
832    fn to_string_with<S: VarScheme + ?Sized>(&self, var: Var<'_, S>) -> String {
833        let mut s = String::new();
834        // Writing to a `String` cannot fail, so the result is the string itself.
835        self.write_with_var(var, Language::Plain, &mut s).unwrap();
836        s
837    }
838
839    /// Converts an [`IntegerPolynomial`] to a LaTeX math-mode fragment, naming its variable with
840    /// any [`VarScheme`].
841    ///
842    /// The fragment is the one [`ToLatex`](malachite_base::strings::latex::ToLatex) writes, which
843    /// that implementation describes; the only difference is that the variable is whichever one is
844    /// handed in rather than `x`.
845    ///
846    /// # Worst-case complexity
847    /// $T(n) = O(n \log n \log\log n)$
848    ///
849    /// $M(n) = O(n \log n)$
850    ///
851    /// where $T$ is time, $M$ is additional memory, and $n$ is the sum of the bits of the
852    /// coefficients.
853    ///
854    /// # Panics
855    /// Panics if `var`'s index is not less than its scheme's [`capacity`](VarScheme::capacity).
856    ///
857    /// # Examples
858    /// ```
859    /// use core::str::FromStr;
860    /// use malachite_base::polynomial::Polynomial;
861    /// use malachite_base::vars::VarScheme;
862    /// use malachite_base::vars::greek::GreekVars;
863    /// use malachite_base::vars::indexed::IndexedVars;
864    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
865    ///
866    /// let p = IntegerPolynomial::from_str("x^2+3*x+2").unwrap();
867    /// assert_eq!(
868    ///     p.to_latex_string_with(GreekVars.var(0)),
869    ///     r"\alpha^2+3\alpha+2"
870    /// );
871    /// assert_eq!(p.to_latex_string_with(IndexedVars.var(7)), "x_7^2+3x_7+2");
872    /// ```
873    ///
874    /// The polynomial is `x^2+3*x+2` in each row; only its variable differs.
875    ///
876    /// | variable | fragment             | renders as           |
877    /// |----------|----------------------|----------------------|
878    /// | `α`      | `\alpha^2+3\alpha+2` | $\alpha^2+3\alpha+2$ |
879    /// | `x₇`     | `x_7^2+3x_7+2`       | $x_7^2+3x_7+2$       |
880    fn to_latex_string_with<S: VarScheme + ?Sized>(&self, var: Var<'_, S>) -> String {
881        let mut s = String::new();
882        // Writing to a `String` cannot fail, so the result is the string itself.
883        self.write_with_var(var, Language::Latex, &mut s).unwrap();
884        s
885    }
886
887    /// Converts an [`IntegerPolynomial`] to a Typst math-mode fragment, naming its variable with
888    /// any [`VarScheme`].
889    ///
890    /// The fragment is the one [`ToTypst`](malachite_base::strings::typst::ToTypst) writes, which
891    /// that implementation describes; the only difference is that the variable is whichever one is
892    /// handed in rather than `x`.
893    ///
894    /// # Worst-case complexity
895    /// $T(n) = O(n \log n \log\log n)$
896    ///
897    /// $M(n) = O(n \log n)$
898    ///
899    /// where $T$ is time, $M$ is additional memory, and $n$ is the sum of the bits of the
900    /// coefficients.
901    ///
902    /// # Panics
903    /// Panics if `var`'s index is not less than its scheme's [`capacity`](VarScheme::capacity).
904    ///
905    /// # Examples
906    /// ```
907    /// use core::str::FromStr;
908    /// use malachite_base::polynomial::Polynomial;
909    /// use malachite_base::vars::VarScheme;
910    /// use malachite_base::vars::greek::GreekVars;
911    /// use malachite_base::vars::indexed::IndexedVars;
912    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
913    ///
914    /// let p = IntegerPolynomial::from_str("x^2+3*x+2").unwrap();
915    /// assert_eq!(p.to_typst_string_with(GreekVars.var(0)), "α^2+3α+2");
916    /// assert_eq!(p.to_typst_string_with(IndexedVars.var(7)), "x_7^2+3x_7+2");
917    /// ```
918    ///
919    /// The polynomial is `x^2+3*x+2` in each row; only its variable differs.
920    ///
921    /// | variable | fragment       |
922    /// |----------|----------------|
923    /// | `α`      | `α^2+3α+2`     |
924    /// | `x₇`     | `x_7^2+3x_7+2` |
925    fn to_typst_string_with<S: VarScheme + ?Sized>(&self, var: Var<'_, S>) -> String {
926        let mut s = String::new();
927        // Writing to a `String` cannot fail, so the result is the string itself.
928        self.write_with_var(var, Language::Typst, &mut s).unwrap();
929        s
930    }
931
932    /// Converts a string to an [`IntegerPolynomial`], with its variable named by any [`VarScheme`].
933    ///
934    /// The syntax is the one [`FromStr`](core::str::FromStr) reads, which that implementation
935    /// describes; the only difference is that the variable is whichever one is handed in rather
936    /// than `x`.
937    ///
938    /// # Worst-case complexity
939    /// $T(n) = O(n (\log n)^2 \log\log n)$
940    ///
941    /// $M(n) = O(n \log n)$
942    ///
943    /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`.
944    ///
945    /// # Examples
946    /// ```
947    /// use malachite_base::polynomial::Polynomial;
948    /// use malachite_base::vars::VarScheme;
949    /// use malachite_base::vars::greek::GreekVars;
950    /// use malachite_base::vars::list::ListVars;
951    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
952    ///
953    /// let p = IntegerPolynomial::from_string_with(GreekVars.var(0), "α^2+3*α+2").unwrap();
954    /// assert_eq!(p.to_string(), "x^2+3*x+2");
955    ///
956    /// let vars = ListVars::new(["t"]);
957    /// assert_eq!(
958    ///     IntegerPolynomial::from_string_with(vars.var(0), "t^2+1")
959    ///         .unwrap()
960    ///         .to_string(),
961    ///     "x^2+1"
962    /// );
963    ///
964    /// // The variable must be the one that was asked for.
965    /// assert!(IntegerPolynomial::from_string_with(GreekVars.var(0), "β^2").is_none());
966    /// ```
967    #[inline]
968    fn from_string_with<S: VarScheme + ?Sized>(var: Var<'_, S>, s: &str) -> Option<Self> {
969        from_string_with(var, s)
970    }
971}
972
973impl_named!(IntegerPolynomial);
974
975/// `ShortlexIntegerPolynomial` is a wrapper around an [`IntegerPolynomial`], taking the
976/// [`IntegerPolynomial`] by value.
977///
978/// [`IntegerPolynomial`] is ordered by how its polynomials behave for large arguments, which is the
979/// order that respects their arithmetic. Sometimes a different order is wanted: one that puts the
980/// smaller polynomials first, whatever their signs, so that a list of them is enumerated from the
981/// simplest upward. Wrapping an [`IntegerPolynomial`] in a `ShortlexIntegerPolynomial` provides
982/// one: polynomials are compared first by degree and then, in case of a tie, by their coefficients
983/// from highest to lowest. This is a total order whose equality agrees with [`IntegerPolynomial`]
984/// equality; it is FLINT's order for polynomials, the one `fmpq_poly_cmp` implements.
985///
986/// The difference from the [`Ord`] implementation on [`IntegerPolynomial`] is what happens when the
987/// degrees differ. There, a polynomial of higher degree dominates, so it is the greater one only if
988/// its leading coefficient is positive, and $-x^3 < x^2$. Here, degree decides outright, so $-x^3 >
989/// x^2$.
990///
991/// Neither order is a well-order. Ordering by degree first does not make one: $x > x - 1 > x - 2 >
992/// \ldots$ all have degree 1, so the chain descends forever under either order. No order that
993/// restricts to the usual order on the constant polynomials can be a well-order, since the
994/// [`Integer`]s are not well-ordered.
995///
996/// `ShortlexIntegerPolynomial` owns its value. This is useful in many cases, for example if you
997/// want to use [`IntegerPolynomial`]s as keys in a map. In other situations, it is better to use
998/// [`ShortlexIntegerPolynomialRef`], which only has a reference to its value.
999// Serialized as its inner `IntegerPolynomial`, since the wrapper adds no data of its own.
1000#[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
1001#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1002#[cfg_attr(feature = "serde", serde(transparent))]
1003pub struct ShortlexIntegerPolynomial(pub IntegerPolynomial);
1004
1005/// `ShortlexIntegerPolynomialRef` is a wrapper around an [`IntegerPolynomial`], taking the
1006/// [`IntegerPolynomial`] by reference.
1007///
1008/// See the [`ShortlexIntegerPolynomial`] documentation for details.
1009#[derive(Clone, Debug, Eq, Hash, PartialEq)]
1010pub struct ShortlexIntegerPolynomialRef<'a>(pub &'a IntegerPolynomial);
1011
1012impl ShortlexIntegerPolynomial {
1013    /// Borrows a [`ShortlexIntegerPolynomial`] as a [`ShortlexIntegerPolynomialRef`].
1014    ///
1015    /// # Worst-case complexity
1016    /// Constant time and additional memory.
1017    ///
1018    /// # Examples
1019    /// ```
1020    /// use core::str::FromStr;
1021    /// use malachite_nz::integer_polynomial::{
1022    ///     IntegerPolynomial, ShortlexIntegerPolynomial, ShortlexIntegerPolynomialRef,
1023    /// };
1024    ///
1025    /// let p = IntegerPolynomial::from_str("x^2-3*x+2").unwrap();
1026    /// let x = ShortlexIntegerPolynomial(p.clone());
1027    /// assert_eq!(x.as_ref(), ShortlexIntegerPolynomialRef(&p));
1028    /// ```
1029    pub const fn as_ref(&self) -> ShortlexIntegerPolynomialRef<'_> {
1030        ShortlexIntegerPolynomialRef(&self.0)
1031    }
1032}
1033
1034impl Deref for ShortlexIntegerPolynomial {
1035    type Target = IntegerPolynomial;
1036
1037    /// Allows a [`ShortlexIntegerPolynomial`] to dereference to an [`IntegerPolynomial`].
1038    ///
1039    /// ```
1040    /// use core::str::FromStr;
1041    /// use malachite_nz::integer_polynomial::{IntegerPolynomial, ShortlexIntegerPolynomial};
1042    ///
1043    /// let p = IntegerPolynomial::from_str("x^2-3*x+2").unwrap();
1044    /// let x = ShortlexIntegerPolynomial(p.clone());
1045    /// assert_eq!(*x, p);
1046    /// ```
1047    fn deref(&self) -> &IntegerPolynomial {
1048        &self.0
1049    }
1050}
1051
1052impl Deref for ShortlexIntegerPolynomialRef<'_> {
1053    type Target = IntegerPolynomial;
1054
1055    /// Allows a [`ShortlexIntegerPolynomialRef`] to dereference to an [`IntegerPolynomial`].
1056    ///
1057    /// ```
1058    /// use core::str::FromStr;
1059    /// use malachite_nz::integer_polynomial::{IntegerPolynomial, ShortlexIntegerPolynomialRef};
1060    ///
1061    /// let p = IntegerPolynomial::from_str("x^2-3*x+2").unwrap();
1062    /// let x = ShortlexIntegerPolynomialRef(&p);
1063    /// assert_eq!(*x, p);
1064    /// ```
1065    fn deref(&self) -> &IntegerPolynomial {
1066        self.0
1067    }
1068}