Skip to main content

malachite_nz/integer_polynomial/comparison/
cmp.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 core::cmp::Ordering::{self, *};
11use malachite_base::num::arithmetic::traits::Sign;
12use malachite_base::polynomial::Polynomial;
13
14impl PartialOrd for IntegerPolynomial {
15    /// Compares two [`IntegerPolynomial`]s.
16    ///
17    /// See the documentation for the [`Ord`] implementation.
18    #[inline]
19    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
20        Some(self.cmp(other))
21    }
22}
23
24impl Ord for IntegerPolynomial {
25    /// Compares two [`IntegerPolynomial`]s by how they behave for large arguments.
26    ///
27    /// The greater polynomial is the one that is eventually greater: the comparison is the one that
28    /// $p(x)$ and $q(x)$ eventually settle into as $x$ grows.
29    ///
30    /// $$
31    /// f(p, q) = \lim_{x \to \infty} \operatorname{cmp}(p(x), q(x)).
32    /// $$
33    ///
34    /// The limit always exists. $p - q$ is a polynomial, so it has finitely many roots, and past
35    /// the largest of them its sign is the sign of its leading coefficient and never changes again.
36    /// That also makes this a total order agreeing with [`Eq`]: the limit is $0$ exactly when $p -
37    /// q$ is the zero polynomial.
38    ///
39    /// Finding it needs no evaluation, but a higher degree alone does not settle it the way it does
40    /// over the [`Natural`](crate::natural::Natural)s. A polynomial of higher degree does dominate
41    /// one of lower degree, so the difference's leading coefficient is its own; but that
42    /// coefficient may be negative, in which case the dominating polynomial runs off to $-\infty$
43    /// and is the *smaller* of the two. So $-x^3 < x$, and the zero polynomial is above every
44    /// polynomial with a negative leading coefficient and below every polynomial with a positive
45    /// one. Polynomials of equal degree are decided by the highest-degree coefficient at which they
46    /// differ, since that term eventually outgrows the sum of everything below it.
47    ///
48    /// This is the order that makes the polynomials an ordered ring: it is unchanged by adding a
49    /// polynomial to both sides, and by multiplying both sides by a positive one. Restricted to the
50    /// constant polynomials it is the order on the [`Integer`](crate::integer::Integer)s, so the
51    /// embedding of a number as a polynomial preserves comparisons. It is not a well-order, and no
52    /// order compatible with addition can be: $x > x - 1 > x - 2 > \ldots$ descends forever.
53    ///
54    /// # Worst-case complexity
55    /// $T(n) = O(n)$
56    ///
57    /// $M(n) = O(1)$
58    ///
59    /// where $T$ is time, $M$ is additional memory, and $n$ is the smaller of the two polynomials'
60    /// total number of bits, summed over their coefficients. Polynomials of different degrees are
61    /// compared in constant time.
62    ///
63    /// # Examples
64    /// ```
65    /// use core::str::FromStr;
66    /// use malachite_nz::integer_polynomial::IntegerPolynomial;
67    ///
68    /// // A higher degree dominates, and a positive leading coefficient makes it the greater.
69    /// assert!(
70    ///     IntegerPolynomial::from_str("x^2").unwrap()
71    ///         > IntegerPolynomial::from_str("1000000*x").unwrap()
72    /// );
73    ///
74    /// // But a dominating polynomial with a negative leading coefficient runs off downwards, so
75    /// // it is the smaller one.
76    /// assert!(
77    ///     IntegerPolynomial::from_str("-x^3").unwrap()
78    ///         < IntegerPolynomial::from_str("x").unwrap()
79    /// );
80    ///
81    /// // The zero polynomial sits between the two signs.
82    /// assert!(
83    ///     IntegerPolynomial::from_str("-x").unwrap() < IntegerPolynomial::from_str("0").unwrap()
84    /// );
85    /// assert!(
86    ///     IntegerPolynomial::from_str("0").unwrap() < IntegerPolynomial::from_str("x").unwrap()
87    /// );
88    ///
89    /// // At equal degrees the highest coefficient at which they differ decides.
90    /// assert!(
91    ///     IntegerPolynomial::from_str("-x^2+5").unwrap()
92    ///         > IntegerPolynomial::from_str("-2*x^2+1000000").unwrap()
93    /// );
94    ///
95    /// // Constant polynomials compare as the numbers they are.
96    /// assert!(
97    ///     IntegerPolynomial::from_str("-122").unwrap()
98    ///         > IntegerPolynomial::from_str("-123").unwrap()
99    /// );
100    /// ```
101    fn cmp(&self, other: &Self) -> Ordering {
102        if core::ptr::eq(self, other) {
103            return Equal;
104        }
105        // The coefficients are held with no trailing zero, so the length is the degree plus one,
106        // and 0 for the zero polynomial; comparing lengths is comparing degrees.
107        match self.coefficients.len().cmp(&other.coefficients.len()) {
108            // Equal degrees: the iterators have the same length, so comparing them from the leading
109            // coefficient down is the comparison at the highest coefficient where the two differ.
110            // Two zero polynomials compare equal, both iterators being empty.
111            Equal => self
112                .coefficients
113                .iter()
114                .rev()
115                .cmp(other.coefficients.iter().rev()),
116            // Different degrees: the difference's leading coefficient is the dominating
117            // polynomial's own, so its sign decides. Normalization makes it nonzero, so there is no
118            // `Equal` to fall through to.
119            Greater => self.leading_coefficient().sign(),
120            Less => other.leading_coefficient().sign().reverse(),
121        }
122    }
123}