Skip to main content

malachite_base/unsigned_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::named::Named;
10use crate::num::basic::traits::Zero;
11use crate::num::basic::unsigneds::PrimitiveUnsigned;
12use crate::num::conversion::traits::ExactFrom;
13use crate::polynomial::Polynomial;
14use crate::unsigned_polynomial::conversion::string::from_string::from_string_with;
15use crate::unsigned_polynomial::conversion::string::to_string::Language;
16use crate::vars::{Var, VarScheme};
17use alloc::string::String;
18use alloc::vec;
19use alloc::vec::Vec;
20
21/// Traits for arithmetic on [`UnsignedPolynomial`]s.
22pub mod arithmetic;
23/// Implementations of [`Ord`] and [`PartialOrd`] for [`UnsignedPolynomial`], comparing two
24/// polynomials by their behavior for large arguments.
25pub mod comparison;
26/// Functions for converting a [`UnsignedPolynomial`] to and from other types.
27pub mod conversion;
28/// Iterators that generate [`UnsignedPolynomial`]s without repetition.
29pub mod exhaustive;
30#[cfg(feature = "random")]
31/// Iterators that generate [`UnsignedPolynomial`]s randomly.
32pub mod random;
33
34/// A polynomial in one variable whose coefficients are unsigned primitive integers.
35///
36/// The coefficients are held in ascending order, so that the coefficient of $x^i$ is the one at
37/// index $i$, and the last is the leading one. Trailing zero coefficients are not held at all: the
38/// zero polynomial has no coefficients, and every other polynomial's last coefficient is nonzero.
39/// That is what makes a polynomial's representation unique, and so what lets [`Eq`] be derived.
40///
41/// The field is private, since not every [`Vec`] of `T`s is one:
42/// [`from_coefficients_asc`](UnsignedPolynomial::from_coefficients_asc) is how a [`Vec`] becomes
43/// one.
44#[derive(Clone, Default, Eq, Hash, PartialEq)]
45#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
46#[cfg_attr(
47    feature = "serde",
48    serde(
49        try_from = "SerdeUnsignedPolynomial<T>",
50        into = "SerdeUnsignedPolynomial<T>"
51    )
52)]
53pub struct UnsignedPolynomial<T: PrimitiveUnsigned> {
54    coefficients: Vec<T>,
55}
56
57// A `UnsignedPolynomial` is its coefficients, so this is what is serialized: the list of them, in
58// the order they are held in. The wrapper is transparent, so the encoding is the list itself and
59// nothing around it.
60//
61// Deserializing goes through `TryFrom`, which rejects a list whose last coefficient is zero: such a
62// list is not a `UnsignedPolynomial`'s coefficients, and accepting it would build one that two
63// equal polynomials could disagree with.
64#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
65#[cfg_attr(feature = "serde", serde(transparent))]
66pub(crate) struct SerdeUnsignedPolynomial<T: PrimitiveUnsigned>(pub(crate) Vec<T>);
67
68/// The constant 0.
69impl<T: PrimitiveUnsigned> Zero for UnsignedPolynomial<T> {
70    const ZERO: Self = Self {
71        coefficients: Vec::new(),
72    };
73}
74
75impl<T: PrimitiveUnsigned> UnsignedPolynomial<T> {
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    // `UnsignedPolynomial`s must be valid.
80    #[cfg(feature = "test_build")]
81    pub fn is_valid(&self) -> bool {
82        self.coefficients.last() != Some(&T::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(&T::ZERO) {
89            self.coefficients.pop();
90        }
91    }
92
93    /// Returns a reference to a [`UnsignedPolynomial`]'s coefficients, in ascending order.
94    ///
95    /// The first is the constant term and the last is the leading coefficient, so the slice is what
96    /// [`from_coefficients_asc`](Self::from_coefficients_asc) would take back. It holds no trailing
97    /// zeros, and for the zero polynomial it is empty.
98    ///
99    /// # Worst-case complexity
100    /// Constant time and additional memory.
101    ///
102    /// # Examples
103    /// ```
104    /// use core::str::FromStr;
105    /// use malachite_base::num::basic::traits::Zero;
106    /// use malachite_base::strings::ToDebugString;
107    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
108    ///
109    /// let p = UnsignedPolynomial::<u64>::from_str("x^2+3*x+2").unwrap();
110    /// assert_eq!(p.coefficients_asc().to_debug_string(), "[2, 3, 1]");
111    /// assert_eq!(
112    ///     UnsignedPolynomial::<u64>::ZERO
113    ///         .coefficients_asc()
114    ///         .to_debug_string(),
115    ///     "[]"
116    /// );
117    /// ```
118    #[inline]
119    pub fn coefficients_asc(&self) -> &[T] {
120        &self.coefficients
121    }
122}
123
124macro_rules! impl_named_unsigned_polynomial {
125    ($t:ident, $name:expr) => {
126        impl Named for UnsignedPolynomial<$t> {
127            /// The name of this type, with its coefficient type spelled out.
128            const NAME: &'static str = $name;
129        }
130    };
131}
132
133impl<T: PrimitiveUnsigned> Polynomial for UnsignedPolynomial<T> {
134    type Coefficient = T;
135    type CoefficientOutput<'a>
136        = T
137    where
138        Self: 'a;
139
140    /// The constant polynomial 1.
141    ///
142    /// This is a function rather than an associated constant, and
143    /// [`One`](crate::num::basic::traits::One) is not implemented, because a polynomial holds its
144    /// coefficients in a [`Vec`] and a [`Vec`] with anything in it cannot be built at compile time.
145    /// The zero polynomial has no coefficients, so [`ZERO`](crate::num::basic::traits::Zero::ZERO)
146    /// is a constant after all.
147    ///
148    /// # Worst-case complexity
149    /// Constant time and additional memory.
150    ///
151    /// # Examples
152    /// ```
153    /// use malachite_base::polynomial::Polynomial;
154    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
155    ///
156    /// assert_eq!(UnsignedPolynomial::<u64>::one().to_string(), "1");
157    /// assert_eq!(UnsignedPolynomial::<u64>::one().degree(), Some(0));
158    /// ```
159    fn one() -> Self {
160        Self {
161            coefficients: vec![T::ONE],
162        }
163    }
164
165    /// The constant polynomial 2.
166    ///
167    /// This is a function rather than an associated constant, for the reason given by
168    /// [`one`](Self::one).
169    ///
170    /// # Worst-case complexity
171    /// Constant time and additional memory.
172    ///
173    /// # Examples
174    /// ```
175    /// use malachite_base::polynomial::Polynomial;
176    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
177    ///
178    /// assert_eq!(UnsignedPolynomial::<u64>::two().to_string(), "2");
179    /// assert_eq!(UnsignedPolynomial::<u64>::two().degree(), Some(0));
180    /// ```
181    fn two() -> Self {
182        Self {
183            coefficients: vec![T::TWO],
184        }
185    }
186
187    /// The polynomial $x$, of degree 1 with leading coefficient 1 and constant term 0.
188    ///
189    /// This is a function rather than an associated constant, for the reason given by
190    /// [`one`](Self::one).
191    ///
192    /// # Worst-case complexity
193    /// Constant time and additional memory.
194    ///
195    /// # Examples
196    /// ```
197    /// use malachite_base::polynomial::Polynomial;
198    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
199    ///
200    /// assert_eq!(UnsignedPolynomial::<u64>::x().to_string(), "x");
201    /// assert_eq!(UnsignedPolynomial::<u64>::x().degree(), Some(1));
202    /// ```
203    fn x() -> Self {
204        Self {
205            coefficients: vec![T::ZERO, T::ONE],
206        }
207    }
208
209    /// Converts a [`Vec`] of [`u64`]s to a [`UnsignedPolynomial`].
210    ///
211    /// The coefficients are in ascending order, so that the first is the constant term. Trailing
212    /// zeros are dropped, since a polynomial does not hold them; the [`Vec`] may therefore end with
213    /// as many as it likes, and the empty [`Vec`] is the zero polynomial.
214    ///
215    /// # Worst-case complexity
216    /// $T(n) = O(n)$
217    ///
218    /// $M(n) = O(1)$
219    ///
220    /// where $T$ is time, $M$ is additional memory, and $n$ is `coefficients.len()`.
221    ///
222    /// # Examples
223    /// ```
224    /// use malachite_base::polynomial::Polynomial;
225    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
226    /// use u64;
227    ///
228    /// let p = UnsignedPolynomial::<u64>::from_coefficients_asc(vec![2, u64::from(3u32), 1]);
229    /// assert_eq!(p.to_string(), "x^2+3*x+2");
230    ///
231    /// // The trailing zeros are not part of the polynomial.
232    /// let q = UnsignedPolynomial::<u64>::from_coefficients_asc(vec![2, u64::from(3u32), 1, 0, 0]);
233    /// assert_eq!(q.to_string(), "x^2+3*x+2");
234    ///
235    /// assert_eq!(
236    ///     UnsignedPolynomial::<u64>::from_coefficients_asc(vec![]).to_string(),
237    ///     "0"
238    /// );
239    /// ```
240    fn from_coefficients_asc(coefficients: Vec<T>) -> Self {
241        let mut p = Self { coefficients };
242        p.trim();
243        p
244    }
245
246    /// Converts a [`UnsignedPolynomial`] to a [`Vec`] of [`u64`]s, in ascending order.
247    ///
248    /// The first is the constant term and the last is the leading coefficient, so the [`Vec`] is
249    /// what [`from_coefficients_asc`](Self::from_coefficients_asc) would take back. It holds no
250    /// trailing zeros, and for the zero polynomial it is empty.
251    ///
252    /// # Worst-case complexity
253    /// Constant time and additional memory.
254    ///
255    /// # Examples
256    /// ```
257    /// use core::str::FromStr;
258    /// use malachite_base::num::basic::traits::Zero;
259    /// use malachite_base::polynomial::Polynomial;
260    /// use malachite_base::strings::ToDebugString;
261    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
262    ///
263    /// let p = UnsignedPolynomial::<u64>::from_str("x^2+3*x+2").unwrap();
264    /// assert_eq!(p.into_coefficients_asc().to_debug_string(), "[2, 3, 1]");
265    /// assert_eq!(
266    ///     UnsignedPolynomial::<u64>::ZERO
267    ///         .into_coefficients_asc()
268    ///         .to_debug_string(),
269    ///     "[]"
270    /// );
271    /// ```
272    #[inline]
273    fn into_coefficients_asc(self) -> Vec<T> {
274        self.coefficients
275    }
276
277    /// Returns the degree of a [`UnsignedPolynomial`].
278    ///
279    /// The zero polynomial has no degree, and gives `None`. Every other polynomial's degree is the
280    /// index of its leading coefficient, so that a nonzero constant has degree 0.
281    ///
282    /// # Worst-case complexity
283    /// Constant time and additional memory.
284    ///
285    /// # Examples
286    /// ```
287    /// use core::str::FromStr;
288    /// use malachite_base::num::basic::traits::Zero;
289    /// use malachite_base::polynomial::Polynomial;
290    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
291    ///
292    /// assert_eq!(UnsignedPolynomial::<u64>::ZERO.degree(), None);
293    /// assert_eq!(
294    ///     UnsignedPolynomial::<u64>::from_str("5").unwrap().degree(),
295    ///     Some(0)
296    /// );
297    /// assert_eq!(
298    ///     UnsignedPolynomial::<u64>::from_str("x").unwrap().degree(),
299    ///     Some(1)
300    /// );
301    /// assert_eq!(
302    ///     UnsignedPolynomial::<u64>::from_str("x^2+3*x+2")
303    ///         .unwrap()
304    ///         .degree(),
305    ///     Some(2)
306    /// );
307    /// ```
308    #[inline]
309    fn degree(&self) -> Option<u64> {
310        self.coefficients.len().checked_sub(1).map(u64::exact_from)
311    }
312
313    /// Returns the length of a [`UnsignedPolynomial`]: the number of coefficients it holds.
314    ///
315    /// A polynomial holds no trailing zeros, so its length is one more than its
316    /// [`degree`](Self::degree), and the zero polynomial, which has no degree, has length 0.
317    ///
318    /// # Worst-case complexity
319    /// Constant time and additional memory.
320    ///
321    /// # Examples
322    /// ```
323    /// use core::str::FromStr;
324    /// use malachite_base::num::basic::traits::Zero;
325    /// use malachite_base::polynomial::Polynomial;
326    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
327    ///
328    /// assert_eq!(UnsignedPolynomial::<u64>::ZERO.len(), 0);
329    /// assert_eq!(UnsignedPolynomial::<u64>::from_str("5").unwrap().len(), 1);
330    /// assert_eq!(UnsignedPolynomial::<u64>::from_str("x").unwrap().len(), 2);
331    /// assert_eq!(
332    ///     UnsignedPolynomial::<u64>::from_str("x^2+3*x+2")
333    ///         .unwrap()
334    ///         .len(),
335    ///     3
336    /// );
337    /// ```
338    ///
339    /// This is equivalent to `nmod_poly_length` from `nmod_poly.h`, FLINT 3.6.0.
340    #[inline]
341    fn len(&self) -> u64 {
342        u64::exact_from(self.coefficients.len())
343    }
344
345    /// Returns one of a [`UnsignedPolynomial`]'s coefficients.
346    ///
347    /// The index is the power of the variable the coefficient belongs to, so that index 0 gives the
348    /// constant term. An index past the degree gives zero, which is the coefficient a polynomial
349    /// has there. A [`u64`] is [`Copy`], so this hands back a value rather than a reference.
350    ///
351    /// # Worst-case complexity
352    /// Constant time and additional memory.
353    ///
354    /// # Examples
355    /// ```
356    /// use core::str::FromStr;
357    /// use malachite_base::polynomial::Polynomial;
358    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
359    ///
360    /// let p = UnsignedPolynomial::<u64>::from_str("x^2+3*x+2").unwrap();
361    /// assert_eq!(p.coefficient(0), 2);
362    /// assert_eq!(p.coefficient(1), 3);
363    /// assert_eq!(p.coefficient(2), 1);
364    /// assert_eq!(p.coefficient(100), 0);
365    /// ```
366    #[inline]
367    fn coefficient(&self, index: u64) -> T {
368        usize::try_from(index)
369            .ok()
370            .and_then(|i| self.coefficients.get(i))
371            .copied()
372            .unwrap_or(T::ZERO)
373    }
374
375    /// Returns a [`UnsignedPolynomial`]'s leading coefficient.
376    ///
377    /// This is the coefficient of the highest power of the variable that the polynomial has one
378    /// for. The zero polynomial has no such power, and gives zero, which is what every one of its
379    /// coefficients is.
380    ///
381    /// # Worst-case complexity
382    /// Constant time and additional memory.
383    ///
384    /// # Examples
385    /// ```
386    /// use core::str::FromStr;
387    /// use malachite_base::num::basic::traits::Zero;
388    /// use malachite_base::polynomial::Polynomial;
389    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
390    ///
391    /// let p = UnsignedPolynomial::<u64>::from_str("7*x^2+3*x+2").unwrap();
392    /// assert_eq!(p.leading_coefficient(), 7);
393    /// assert_eq!(UnsignedPolynomial::<u64>::ZERO.leading_coefficient(), 0);
394    /// ```
395    #[inline]
396    fn leading_coefficient(&self) -> T {
397        self.coefficients.last().copied().unwrap_or(T::ZERO)
398    }
399
400    /// Determines whether an [`UnsignedPolynomial`] is monic: nonzero, with leading coefficient 1.
401    ///
402    /// The zero polynomial is not monic.
403    ///
404    /// # Worst-case complexity
405    /// Constant time and additional memory.
406    ///
407    /// # Examples
408    /// ```
409    /// use core::str::FromStr;
410    /// use malachite_base::num::basic::traits::Zero;
411    /// use malachite_base::polynomial::Polynomial;
412    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
413    ///
414    /// assert!(
415    ///     UnsignedPolynomial::<u8>::from_str("x^2+3*x+2")
416    ///         .unwrap()
417    ///         .is_monic()
418    /// );
419    /// assert!(
420    ///     !UnsignedPolynomial::<u8>::from_str("2*x^2+3")
421    ///         .unwrap()
422    ///         .is_monic()
423    /// );
424    /// assert!(!UnsignedPolynomial::<u8>::ZERO.is_monic());
425    /// ```
426    #[inline]
427    fn is_monic(&self) -> bool {
428        self.coefficients.last() == Some(&T::ONE)
429    }
430
431    /// Mutates one of a [`UnsignedPolynomial`]'s coefficients using a provided closure, and then
432    /// returns whatever the closure returns.
433    ///
434    /// The index is the power of the variable the coefficient belongs to. An index past the degree
435    /// is not an error: the polynomial grows to reach it, and the closure is handed the zero that
436    /// was there all along.
437    ///
438    /// After the closure executes, this function drops whatever trailing zero coefficients the
439    /// polynomial has acquired, so that a coefficient set to zero, or a growth that came to
440    /// nothing, leaves no trace.
441    ///
442    /// # Worst-case complexity
443    /// $T(n, m) = O(n + m)$
444    ///
445    /// $M(n, m) = O(n + m)$
446    ///
447    /// where $T$ is time, $M$ is additional memory, $n$ is `index`, and $m$ is the cost of the
448    /// closure.
449    ///
450    /// # Panics
451    /// Panics if `index` does not fit in a [`usize`], which cannot happen on a target with 64-bit
452    /// pointers, or if growing to reach `index` would exceed the maximum length of a [`Vec`].
453    ///
454    /// # Examples
455    /// ```
456    /// use core::str::FromStr;
457    /// use malachite_base::polynomial::Polynomial;
458    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
459    /// use u64;
460    ///
461    /// let mut p = UnsignedPolynomial::<u64>::from_str("x^2+3*x+2").unwrap();
462    ///
463    /// let ret = p.mutate_coefficient(1, |c| {
464    ///     *c += 1;
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 += 1);
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 = 0);
476    /// assert_eq!(p.to_string(), "x^2+4*x+2");
477    /// ```
478    fn mutate_coefficient<F: FnOnce(&mut T) -> U, U>(&mut self, index: u64, f: F) -> U {
479        let index = usize::exact_from(index);
480        if index >= self.coefficients.len() {
481            self.coefficients.resize(index + 1, T::ZERO);
482        }
483        let out = f(&mut self.coefficients[index]);
484        self.trim();
485        out
486    }
487
488    /// Sets the coefficients of a [`UnsignedPolynomial`] 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_base::unsigned_polynomial::UnsignedPolynomial;
509    ///
510    /// let mut p;
511    /// p = UnsignedPolynomial::<u64>::from_str("x^4+x^3+x^2+x+1").unwrap();
512    /// p.zero_coefficients(1, 3);
513    /// assert_eq!(p.to_string(), "x^4+x^3+1");
514    /// p = UnsignedPolynomial::<u64>::from_str("x^4+x^3+x^2+x+1").unwrap();
515    /// p.zero_coefficients(2, 10);
516    /// assert_eq!(p.to_string(), "x+1");
517    /// p = UnsignedPolynomial::<u64>::from_str("x^4+x^3+x^2+x+1").unwrap();
518    /// p.zero_coefficients(5, 10);
519    /// assert_eq!(p.to_string(), "x^4+x^3+x^2+x+1");
520    /// ```
521    ///
522    /// FLINT has no counterpart for `nmod_poly`; this is the counterpart of `fmpz_poly_zero_coeffs`
523    /// from `fmpz_poly/zero_coeffs.c`, FLINT 3.6.0.
524    fn zero_coefficients(&mut self, start: u64, end: u64) {
525        assert!(start <= end);
526        let len = self.coefficients.len();
527        let Ok(start) = usize::try_from(start) else {
528            return;
529        };
530        if start >= len {
531            return;
532        }
533        let end = usize::try_from(end).map_or(len, |end| end.min(len));
534        if end == len {
535            // The range reaches the leading coefficient, so the zeros it leaves are trailing.
536            self.coefficients.truncate(start);
537            self.trim();
538        } else {
539            self.coefficients[start..end].fill(T::ZERO);
540        }
541    }
542
543    /// Truncates a [`UnsignedPolynomial`] to its first `len` coefficients, taking the polynomial by
544    /// reference and returning the result.
545    ///
546    /// The result is the polynomial reduced modulo $x^{\mathrm{len}}$: every term of degree `len`
547    /// or more is dropped, and then any zeros left at the top go too, so the result may have fewer
548    /// than `len` coefficients. A polynomial with at most `len` coefficients is returned unchanged.
549    ///
550    /// $$
551    /// f(p, n) = p \bmod x^n.
552    /// $$
553    ///
554    /// # Worst-case complexity
555    /// $T(n) = O(n)$
556    ///
557    /// $M(n) = O(n)$
558    ///
559    /// where $T$ is time, $M$ is additional memory, and $n$ is `min(len, self.len())`.
560    ///
561    /// # Examples
562    /// ```
563    /// use core::str::FromStr;
564    /// use malachite_base::polynomial::Polynomial;
565    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
566    ///
567    /// assert_eq!(
568    ///     UnsignedPolynomial::<u64>::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    ///     UnsignedPolynomial::<u64>::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    ///     UnsignedPolynomial::<u64>::from_str("x^3+3*x+4")
585    ///         .unwrap()
586    ///         .truncate(3)
587    ///         .to_string(),
588    ///     "3*x+4"
589    /// );
590    /// assert_eq!(
591    ///     UnsignedPolynomial::<u64>::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 `nmod_poly_set_trunc` from `nmod_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 != T::ZERO)
608            .map_or(0, |i| i + 1);
609        Self {
610            coefficients: self.coefficients[..kept].to_vec(),
611        }
612    }
613
614    /// Truncates a [`UnsignedPolynomial`] 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_base::unsigned_polynomial::UnsignedPolynomial;
630    ///
631    /// let mut p;
632    /// p = UnsignedPolynomial::<u64>::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 = UnsignedPolynomial::<u64>::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 = UnsignedPolynomial::<u64>::from_str("x^3+3*x+4").unwrap();
641    /// p.truncate_assign(3);
642    /// assert_eq!(p.to_string(), "3*x+4");
643    /// p = UnsignedPolynomial::<u64>::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 `nmod_poly_truncate` from `nmod_poly.h`, 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 [`UnsignedPolynomial`], 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) = O(n)$
674    ///
675    /// $M(n) = O(n)$
676    ///
677    /// where $T$ is time, $M$ is additional memory, and $n$ is `len`.
678    ///
679    /// # Panics
680    /// Panics if `len` exceeds `self.len()` and does not fit in a [`usize`], which cannot happen on
681    /// a target with 64-bit pointers.
682    ///
683    /// # Examples
684    /// ```
685    /// use core::str::FromStr;
686    /// use malachite_base::polynomial::Polynomial;
687    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
688    ///
689    /// assert_eq!(
690    ///     UnsignedPolynomial::<u64>::from_str("x^2+2*x+3")
691    ///         .unwrap()
692    ///         .reverse(3)
693    ///         .to_string(),
694    ///     "3*x^2+2*x+1"
695    /// );
696    /// // Padding to length 5 adds low zeros.
697    /// assert_eq!(
698    ///     UnsignedPolynomial::<u64>::from_str("x^2+2*x+3")
699    ///         .unwrap()
700    ///         .reverse(5)
701    ///         .to_string(),
702    ///     "3*x^4+2*x^3+x^2"
703    /// );
704    /// // Truncating to length 2 drops x^2 first.
705    /// assert_eq!(
706    ///     UnsignedPolynomial::<u64>::from_str("x^2+2*x+3")
707    ///         .unwrap()
708    ///         .reverse(2)
709    ///         .to_string(),
710    ///     "3*x+2"
711    /// );
712    /// // A zero constant term becomes a trailing zero, and is dropped.
713    /// assert_eq!(
714    ///     UnsignedPolynomial::<u64>::from_str("x^2+2*x")
715    ///         .unwrap()
716    ///         .reverse(3)
717    ///         .to_string(),
718    ///     "2*x+1"
719    /// );
720    /// ```
721    ///
722    /// This is equivalent to `nmod_poly_reverse` from `nmod_poly/reverse.c`, FLINT 3.6.0.
723    fn reverse(&self, len: u64) -> Self {
724        let kept = usize::try_from(len).map_or(self.coefficients.len(), |len| {
725            len.min(self.coefficients.len())
726        });
727        if kept == 0 {
728            return Self::ZERO;
729        }
730        // The coefficients past the kept ones become the result's low zeros.
731        let mut coefficients = vec![T::ZERO; usize::exact_from(len) - kept];
732        coefficients.extend(self.coefficients[..kept].iter().rev().copied());
733        Self::from_coefficients_asc(coefficients)
734    }
735
736    /// Reverses the coefficients of a [`UnsignedPolynomial`], considered as having length `len`, in
737    /// place.
738    ///
739    /// See [`reverse`](Self::reverse) for what the result is.
740    ///
741    /// # Worst-case complexity
742    /// $T(n) = O(n)$
743    ///
744    /// $M(n) = O(n)$
745    ///
746    /// where $T$ is time, $M$ is additional memory, and $n$ is the larger of `len` and
747    /// `self.len()`.
748    ///
749    /// # Panics
750    /// Panics if `len` exceeds `self.len()` and does not fit in a [`usize`], which cannot happen on
751    /// a target with 64-bit pointers.
752    ///
753    /// # Examples
754    /// ```
755    /// use core::str::FromStr;
756    /// use malachite_base::polynomial::Polynomial;
757    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
758    ///
759    /// let mut p;
760    /// p = UnsignedPolynomial::<u64>::from_str("x^2+2*x+3").unwrap();
761    /// p.reverse_assign(3);
762    /// assert_eq!(p.to_string(), "3*x^2+2*x+1");
763    /// // Padding to length 5 adds low zeros.
764    /// p = UnsignedPolynomial::<u64>::from_str("x^2+2*x+3").unwrap();
765    /// p.reverse_assign(5);
766    /// assert_eq!(p.to_string(), "3*x^4+2*x^3+x^2");
767    /// // Truncating to length 2 drops x^2 first.
768    /// p = UnsignedPolynomial::<u64>::from_str("x^2+2*x+3").unwrap();
769    /// p.reverse_assign(2);
770    /// assert_eq!(p.to_string(), "3*x+2");
771    /// // A zero constant term becomes a trailing zero, and is dropped.
772    /// p = UnsignedPolynomial::<u64>::from_str("x^2+2*x").unwrap();
773    /// p.reverse_assign(3);
774    /// assert_eq!(p.to_string(), "2*x+1");
775    /// ```
776    ///
777    /// This is equivalent to `nmod_poly_reverse` from `nmod_poly/reverse.c`, FLINT 3.6.0.
778    fn reverse_assign(&mut self, len: u64) {
779        let kept = usize::try_from(len).map_or(self.coefficients.len(), |len| {
780            len.min(self.coefficients.len())
781        });
782        if kept == 0 {
783            *self = Self::ZERO;
784            return;
785        }
786        self.coefficients.truncate(kept);
787        self.coefficients.reverse();
788        // Pad at the high end and rotate the padding down, so that it becomes the low zeros.
789        let len = usize::exact_from(len);
790        self.coefficients.resize(len, T::ZERO);
791        self.coefficients.rotate_right(len - kept);
792        // The polynomial's low zeros, if any, are now at the top.
793        self.trim();
794    }
795
796    /// Converts a [`UnsignedPolynomial`] to a [`String`], naming its variable with any
797    /// [`VarScheme`].
798    ///
799    /// The syntax is the one [`Display`](core::fmt::Display) writes, which that implementation
800    /// describes; the only difference is that the variable is whichever one is handed in rather
801    /// than `x`.
802    ///
803    /// # Worst-case complexity
804    /// $T(n) = O(n \log n \log\log n)$
805    ///
806    /// $M(n) = O(n \log n)$
807    ///
808    /// where $T$ is time, $M$ is additional memory, and $n$ is the sum of the bits of the
809    /// coefficients.
810    ///
811    /// # Panics
812    /// Panics if `var`'s index is not less than its scheme's [`capacity`](VarScheme::capacity).
813    ///
814    /// # Examples
815    /// ```
816    /// use core::str::FromStr;
817    /// use malachite_base::polynomial::Polynomial;
818    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
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    ///
824    /// let p = UnsignedPolynomial::<u64>::from_str("x^2+3*x+2").unwrap();
825    /// assert_eq!(p.to_string_with(GreekVars.var(0)), "α^2+3*α+2");
826    /// assert_eq!(p.to_string_with(IndexedVars.var(7)), "x₇^2+3*x₇+2");
827    ///
828    /// let vars = ListVars::new(["t"]);
829    /// assert_eq!(p.to_string_with(vars.var(0)), "t^2+3*t+2");
830    /// ```
831    fn to_string_with<S: VarScheme + ?Sized>(&self, var: Var<'_, S>) -> String {
832        let mut s = String::new();
833        // Writing to a `String` cannot fail, so the result is the string itself.
834        self.write_with_var(var, Language::Plain, &mut s).unwrap();
835        s
836    }
837
838    /// Converts a [`UnsignedPolynomial`] to a LaTeX math-mode fragment, naming its variable with
839    /// any [`VarScheme`].
840    ///
841    /// The fragment is the one [`ToLatex`](crate::strings::latex::ToLatex) writes, which that
842    /// implementation describes; the only difference is that the variable is whichever one is
843    /// handed in rather than `x`.
844    ///
845    /// # Worst-case complexity
846    /// $T(n) = O(n \log n \log\log n)$
847    ///
848    /// $M(n) = O(n \log n)$
849    ///
850    /// where $T$ is time, $M$ is additional memory, and $n$ is the sum of the bits of the
851    /// coefficients.
852    ///
853    /// # Panics
854    /// Panics if `var`'s index is not less than its scheme's [`capacity`](VarScheme::capacity).
855    ///
856    /// # Examples
857    /// ```
858    /// use core::str::FromStr;
859    /// use malachite_base::polynomial::Polynomial;
860    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
861    /// use malachite_base::vars::VarScheme;
862    /// use malachite_base::vars::greek::GreekVars;
863    /// use malachite_base::vars::indexed::IndexedVars;
864    ///
865    /// let p = UnsignedPolynomial::<u64>::from_str("x^2+3*x+2").unwrap();
866    /// assert_eq!(
867    ///     p.to_latex_string_with(GreekVars.var(0)),
868    ///     r"\alpha^2+3\alpha+2"
869    /// );
870    /// assert_eq!(p.to_latex_string_with(IndexedVars.var(7)), "x_7^2+3x_7+2");
871    /// ```
872    ///
873    /// The polynomial is `x^2+3*x+2` in each row; only its variable differs.
874    ///
875    /// | variable | fragment             | renders as           |
876    /// |----------|----------------------|----------------------|
877    /// | `α`      | `\alpha^2+3\alpha+2` | $\alpha^2+3\alpha+2$ |
878    /// | `x₇`     | `x_7^2+3x_7+2`       | $x_7^2+3x_7+2$       |
879    fn to_latex_string_with<S: VarScheme + ?Sized>(&self, var: Var<'_, S>) -> String {
880        let mut s = String::new();
881        // Writing to a `String` cannot fail, so the result is the string itself.
882        self.write_with_var(var, Language::Latex, &mut s).unwrap();
883        s
884    }
885
886    /// Converts a [`UnsignedPolynomial`] to a Typst math-mode fragment, naming its variable with
887    /// any [`VarScheme`].
888    ///
889    /// The fragment is the one [`ToTypst`](crate::strings::typst::ToTypst) writes, which that
890    /// implementation describes; the only difference is that the variable is whichever one is
891    /// handed in rather than `x`.
892    ///
893    /// # Worst-case complexity
894    /// $T(n) = O(n \log n \log\log n)$
895    ///
896    /// $M(n) = O(n \log n)$
897    ///
898    /// where $T$ is time, $M$ is additional memory, and $n$ is the sum of the bits of the
899    /// coefficients.
900    ///
901    /// # Panics
902    /// Panics if `var`'s index is not less than its scheme's [`capacity`](VarScheme::capacity).
903    ///
904    /// # Examples
905    /// ```
906    /// use core::str::FromStr;
907    /// use malachite_base::polynomial::Polynomial;
908    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
909    /// use malachite_base::vars::VarScheme;
910    /// use malachite_base::vars::greek::GreekVars;
911    /// use malachite_base::vars::indexed::IndexedVars;
912    ///
913    /// let p = UnsignedPolynomial::<u64>::from_str("x^2+3*x+2").unwrap();
914    /// assert_eq!(p.to_typst_string_with(GreekVars.var(0)), "α^2+3α+2");
915    /// assert_eq!(p.to_typst_string_with(IndexedVars.var(7)), "x_7^2+3x_7+2");
916    /// ```
917    ///
918    /// The polynomial is `x^2+3*x+2` in each row; only its variable differs.
919    ///
920    /// | variable | fragment       |
921    /// |----------|----------------|
922    /// | `α`      | `α^2+3α+2`     |
923    /// | `x₇`     | `x_7^2+3x_7+2` |
924    fn to_typst_string_with<S: VarScheme + ?Sized>(&self, var: Var<'_, S>) -> String {
925        let mut s = String::new();
926        // Writing to a `String` cannot fail, so the result is the string itself.
927        self.write_with_var(var, Language::Typst, &mut s).unwrap();
928        s
929    }
930
931    /// Converts a string to a [`UnsignedPolynomial`], with its variable named by any [`VarScheme`].
932    ///
933    /// The syntax is the one [`FromStr`](core::str::FromStr) reads, which that implementation
934    /// describes; the only difference is that the variable is whichever one is handed in rather
935    /// than `x`.
936    ///
937    /// # Worst-case complexity
938    /// $T(n) = O(n (\log n)^2 \log\log n)$
939    ///
940    /// $M(n) = O(n \log n)$
941    ///
942    /// where $T$ is time, $M$ is additional memory, and $n$ is `s.len()`.
943    ///
944    /// # Examples
945    /// ```
946    /// use malachite_base::polynomial::Polynomial;
947    /// use malachite_base::unsigned_polynomial::UnsignedPolynomial;
948    /// use malachite_base::vars::VarScheme;
949    /// use malachite_base::vars::greek::GreekVars;
950    /// use malachite_base::vars::list::ListVars;
951    ///
952    /// let p = UnsignedPolynomial::<u64>::from_string_with(GreekVars.var(0), "α^2+3*α+2").unwrap();
953    /// assert_eq!(p.to_string(), "x^2+3*x+2");
954    ///
955    /// let vars = ListVars::new(["t"]);
956    /// assert_eq!(
957    ///     UnsignedPolynomial::<u64>::from_string_with(vars.var(0), "t^2+1")
958    ///         .unwrap()
959    ///         .to_string(),
960    ///     "x^2+1"
961    /// );
962    ///
963    /// // The variable must be the one that was asked for.
964    /// assert!(UnsignedPolynomial::<u64>::from_string_with(GreekVars.var(0), "β^2").is_none());
965    /// ```
966    #[inline]
967    fn from_string_with<S: VarScheme + ?Sized>(var: Var<'_, S>, s: &str) -> Option<Self> {
968        from_string_with(var, s)
969    }
970}
971
972impl_named_unsigned_polynomial!(u8, "UnsignedPolynomial<u8>");
973impl_named_unsigned_polynomial!(u16, "UnsignedPolynomial<u16>");
974impl_named_unsigned_polynomial!(u32, "UnsignedPolynomial<u32>");
975impl_named_unsigned_polynomial!(u64, "UnsignedPolynomial<u64>");
976impl_named_unsigned_polynomial!(u128, "UnsignedPolynomial<u128>");
977impl_named_unsigned_polynomial!(usize, "UnsignedPolynomial<usize>");