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>");