malachite_nz/integer_polynomial/comparison/shortlex_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::{ShortlexIntegerPolynomial, ShortlexIntegerPolynomialRef};
10use core::cmp::Ordering;
11
12impl Ord for ShortlexIntegerPolynomialRef<'_> {
13 /// Compares two [`ShortlexIntegerPolynomialRef`]s.
14 ///
15 /// The order is shortlex: the polynomials are compared first by degree, and then, in case of a
16 /// tie, by their coefficients from highest to lowest. The zero polynomial, having no degree at
17 /// all, comes first. This is a total order, and its equality agrees with
18 /// [`IntegerPolynomial`](crate::integer_polynomial::IntegerPolynomial) equality. It is the
19 /// order FLINT uses for polynomials, the one `fmpq_poly_cmp` implements.
20 ///
21 /// Where the degrees differ this parts company with
22 /// [`IntegerPolynomial`](crate::integer_polynomial::IntegerPolynomial)'s own [`Ord`], which
23 /// compares polynomials by how they behave for large arguments and so lets a negative leading
24 /// coefficient send a high-degree polynomial to the bottom. Here degree decides outright, so
25 /// $-x^3 > x^2$ where the asymptotic order has $-x^3 < x^2$.
26 ///
27 /// # Worst-case complexity
28 /// $T(n) = O(n)$
29 ///
30 /// $M(n) = O(1)$
31 ///
32 /// where $T$ is time, $M$ is additional memory, and $n$ is the smaller of the two polynomials'
33 /// total number of bits, summed over their coefficients. Polynomials of different degrees are
34 /// compared in constant time.
35 ///
36 /// # Examples
37 /// ```
38 /// use core::str::FromStr;
39 /// use malachite_nz::integer_polynomial::{IntegerPolynomial, ShortlexIntegerPolynomialRef};
40 ///
41 /// let zero = IntegerPolynomial::from_str("0").unwrap();
42 /// let x_squared = IntegerPolynomial::from_str("x^2").unwrap();
43 /// let negative_x_cubed = IntegerPolynomial::from_str("-x^3").unwrap();
44 ///
45 /// // The zero polynomial comes first.
46 /// assert!(ShortlexIntegerPolynomialRef(&zero) < ShortlexIntegerPolynomialRef(&x_squared));
47 /// // Degree decides, whatever the sign of the leading coefficient.
48 /// assert!(
49 /// ShortlexIntegerPolynomialRef(&x_squared)
50 /// < ShortlexIntegerPolynomialRef(&negative_x_cubed)
51 /// );
52 /// ```
53 #[inline]
54 fn cmp(&self, other: &Self) -> Ordering {
55 // The coefficients are held with no trailing zero, so the length is the degree plus one,
56 // and 0 for the zero polynomial; comparing lengths is comparing degrees. Once the lengths
57 // agree the iterators have the same length, so comparing them from the leading coefficient
58 // down is the comparison at the highest coefficient where the two differ.
59 self.0
60 .coefficients
61 .len()
62 .cmp(&other.0.coefficients.len())
63 .then_with(|| {
64 self.0
65 .coefficients
66 .iter()
67 .rev()
68 .cmp(other.0.coefficients.iter().rev())
69 })
70 }
71}
72
73impl PartialOrd for ShortlexIntegerPolynomialRef<'_> {
74 /// Compares two [`ShortlexIntegerPolynomialRef`]s.
75 ///
76 /// See the documentation for the [`Ord`] implementation.
77 #[inline]
78 fn partial_cmp(&self, other: &ShortlexIntegerPolynomialRef) -> Option<Ordering> {
79 Some(self.cmp(other))
80 }
81}
82
83impl Ord for ShortlexIntegerPolynomial {
84 /// Compares two [`ShortlexIntegerPolynomial`]s.
85 ///
86 /// The order is shortlex: the polynomials are compared first by degree, and then, in case of a
87 /// tie, by their coefficients from highest to lowest. See the [`Ord`] implementation for
88 /// [`ShortlexIntegerPolynomialRef`] for details.
89 ///
90 /// # Worst-case complexity
91 /// $T(n) = O(n)$
92 ///
93 /// $M(n) = O(1)$
94 ///
95 /// where $T$ is time, $M$ is additional memory, and $n$ is the smaller of the two polynomials'
96 /// total number of bits, summed over their coefficients. Polynomials of different degrees are
97 /// compared in constant time.
98 ///
99 /// # Examples
100 /// ```
101 /// use core::str::FromStr;
102 /// use malachite_nz::integer_polynomial::{IntegerPolynomial, ShortlexIntegerPolynomial};
103 ///
104 /// let x_squared = IntegerPolynomial::from_str("x^2").unwrap();
105 /// let negative_x_cubed = IntegerPolynomial::from_str("-x^3").unwrap();
106 ///
107 /// // Degree decides, whatever the sign of the leading coefficient.
108 /// assert!(ShortlexIntegerPolynomial(x_squared) < ShortlexIntegerPolynomial(negative_x_cubed));
109 /// ```
110 #[inline]
111 fn cmp(&self, other: &Self) -> Ordering {
112 self.as_ref().cmp(&other.as_ref())
113 }
114}
115
116impl PartialOrd for ShortlexIntegerPolynomial {
117 /// Compares two [`ShortlexIntegerPolynomial`]s.
118 ///
119 /// See the documentation for the [`Ord`] implementation.
120 #[inline]
121 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
122 Some(self.cmp(other))
123 }
124}