malachite_nz/integer_polynomial/arithmetic/canonicalize_unit.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_polynomial::IntegerPolynomial;
10use malachite_base::num::arithmetic::traits::{
11 CanonicalizeUnit, CanonicalizeUnitAssign, NegAssign,
12};
13use malachite_base::polynomial::Polynomial;
14
15impl CanonicalizeUnit for IntegerPolynomial {
16 type Output = Self;
17
18 /// Brings an [`IntegerPolynomial`] into canonical unit form, taking it by value.
19 ///
20 /// The canonical associate is the one whose leading coefficient is non-negative, so a
21 /// polynomial with a negative leading coefficient is negated and any other is left alone. The
22 /// zero polynomial is its own canonical associate.
23 ///
24 /// # Worst-case complexity
25 /// $T(n) = O(n)$
26 ///
27 /// $M(n) = O(1)$
28 ///
29 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.len()`.
30 ///
31 /// # Examples
32 /// ```
33 /// use core::str::FromStr;
34 /// use malachite_base::num::arithmetic::traits::CanonicalizeUnit;
35 /// use malachite_base::num::basic::traits::Zero;
36 /// use malachite_nz::integer_polynomial::IntegerPolynomial;
37 ///
38 /// assert_eq!(
39 /// IntegerPolynomial::from_str("-3*x^2+2")
40 /// .unwrap()
41 /// .canonicalize_unit()
42 /// .to_string(),
43 /// "3*x^2-2"
44 /// );
45 /// assert_eq!(
46 /// IntegerPolynomial::from_str("3*x^2-2")
47 /// .unwrap()
48 /// .canonicalize_unit()
49 /// .to_string(),
50 /// "3*x^2-2"
51 /// );
52 /// assert_eq!(
53 /// IntegerPolynomial::ZERO.canonicalize_unit(),
54 /// IntegerPolynomial::ZERO
55 /// );
56 /// ```
57 #[inline]
58 fn canonicalize_unit(mut self) -> Self {
59 self.canonicalize_unit_assign();
60 self
61 }
62}
63
64impl CanonicalizeUnit for &IntegerPolynomial {
65 type Output = IntegerPolynomial;
66
67 /// Brings an [`IntegerPolynomial`] into canonical unit form, taking it by reference.
68 ///
69 /// The canonical associate is the one whose leading coefficient is non-negative, so a
70 /// polynomial with a negative leading coefficient is negated and any other is left alone. The
71 /// zero polynomial is its own canonical associate.
72 ///
73 /// # Worst-case complexity
74 /// $T(n) = O(n)$
75 ///
76 /// $M(n) = O(n)$
77 ///
78 /// where $T$ is time, $M$ is additional memory, and $n$ is the total size of the coefficients.
79 ///
80 /// # Examples
81 /// ```
82 /// use core::str::FromStr;
83 /// use malachite_base::num::arithmetic::traits::CanonicalizeUnit;
84 /// use malachite_base::num::basic::traits::Zero;
85 /// use malachite_nz::integer_polynomial::IntegerPolynomial;
86 ///
87 /// assert_eq!(
88 /// (&IntegerPolynomial::from_str("-3*x^2+2").unwrap())
89 /// .canonicalize_unit()
90 /// .to_string(),
91 /// "3*x^2-2"
92 /// );
93 /// assert_eq!(
94 /// (&IntegerPolynomial::from_str("3*x^2-2").unwrap())
95 /// .canonicalize_unit()
96 /// .to_string(),
97 /// "3*x^2-2"
98 /// );
99 /// assert_eq!(
100 /// (&IntegerPolynomial::ZERO).canonicalize_unit(),
101 /// IntegerPolynomial::ZERO
102 /// );
103 /// ```
104 #[inline]
105 fn canonicalize_unit(self) -> IntegerPolynomial {
106 if *self.leading_coefficient() < 0u32 {
107 -self
108 } else {
109 self.clone()
110 }
111 }
112}
113
114impl CanonicalizeUnitAssign for IntegerPolynomial {
115 /// Brings an [`IntegerPolynomial`] into canonical unit form, in place.
116 ///
117 /// See [`canonicalize_unit`](CanonicalizeUnit::canonicalize_unit).
118 ///
119 /// # Worst-case complexity
120 /// $T(n) = O(n)$
121 ///
122 /// $M(n) = O(1)$
123 ///
124 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.len()`.
125 ///
126 /// # Examples
127 /// ```
128 /// use core::str::FromStr;
129 /// use malachite_base::num::arithmetic::traits::CanonicalizeUnitAssign;
130 /// use malachite_nz::integer_polynomial::IntegerPolynomial;
131 ///
132 /// let mut p = IntegerPolynomial::from_str("-3*x^2+2").unwrap();
133 /// p.canonicalize_unit_assign();
134 /// assert_eq!(p.to_string(), "3*x^2-2");
135 /// ```
136 #[inline]
137 fn canonicalize_unit_assign(&mut self) {
138 if *self.leading_coefficient() < 0u32 {
139 self.neg_assign();
140 }
141 }
142}