Skip to main content

malachite_nz/integer_vector/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_vector::{ShortlexIntegerVector, ShortlexIntegerVectorRef};
10use core::cmp::Ordering;
11
12impl Ord for ShortlexIntegerVectorRef<'_> {
13    /// Compares two [`ShortlexIntegerVectorRef`]s.
14    ///
15    /// The order is shortlex: the vectors are compared first by dimension, and then, in case of a
16    /// tie, lexicographically, by their elements from first to last. The 0-dimensional vector comes
17    /// first. This is a total order, and its equality agrees with
18    /// [`IntegerVector`](crate::integer_vector::IntegerVector) equality.
19    ///
20    /// Where the dimensions differ this parts company with the lexicographic order of [`Vec`]s:
21    /// here dimension decides outright, so $(5) < (0, 0)$, where lexicographic order has $(5) > (0,
22    /// 0)$.
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 the smaller of the two vectors'
30    /// total number of bits, summed over their elements. Vectors of different dimensions are
31    /// compared in constant time.
32    ///
33    /// # Examples
34    /// ```
35    /// use core::str::FromStr;
36    /// use malachite_nz::integer_vector::{IntegerVector, ShortlexIntegerVectorRef};
37    ///
38    /// let empty = IntegerVector::from_str("()").unwrap();
39    /// let five = IntegerVector::from_str("(5)").unwrap();
40    /// let zero_zero = IntegerVector::from_str("(0, 0)").unwrap();
41    /// let zero_one = IntegerVector::from_str("(0, 1)").unwrap();
42    ///
43    /// // The 0-dimensional vector comes first.
44    /// assert!(ShortlexIntegerVectorRef(&empty) < ShortlexIntegerVectorRef(&five));
45    /// // Dimension decides, whatever the elements.
46    /// assert!(ShortlexIntegerVectorRef(&five) < ShortlexIntegerVectorRef(&zero_zero));
47    /// // At equal dimensions, the first differing element decides.
48    /// assert!(ShortlexIntegerVectorRef(&zero_zero) < ShortlexIntegerVectorRef(&zero_one));
49    /// ```
50    #[inline]
51    fn cmp(&self, other: &Self) -> Ordering {
52        // Once the lengths agree, comparing the `Vec`s is the comparison at the first element where
53        // the two differ.
54        self.0
55            .elements
56            .len()
57            .cmp(&other.0.elements.len())
58            .then_with(|| self.0.elements.cmp(&other.0.elements))
59    }
60}
61
62impl PartialOrd for ShortlexIntegerVectorRef<'_> {
63    /// Compares two [`ShortlexIntegerVectorRef`]s.
64    ///
65    /// See the documentation for the [`Ord`] implementation.
66    #[inline]
67    fn partial_cmp(&self, other: &ShortlexIntegerVectorRef) -> Option<Ordering> {
68        Some(self.cmp(other))
69    }
70}
71
72impl Ord for ShortlexIntegerVector {
73    /// Compares two [`ShortlexIntegerVector`]s.
74    ///
75    /// The order is shortlex: the vectors are compared first by dimension, and then, in case of a
76    /// tie, lexicographically. See the [`Ord`] implementation for [`ShortlexIntegerVectorRef`] for
77    /// details.
78    ///
79    /// # Worst-case complexity
80    /// $T(n) = O(n)$
81    ///
82    /// $M(n) = O(1)$
83    ///
84    /// where $T$ is time, $M$ is additional memory, and $n$ is the smaller of the two vectors'
85    /// total number of bits, summed over their elements. Vectors of different dimensions are
86    /// compared in constant time.
87    ///
88    /// # Examples
89    /// ```
90    /// use core::str::FromStr;
91    /// use malachite_nz::integer_vector::{IntegerVector, ShortlexIntegerVector};
92    /// use std::collections::BTreeSet;
93    ///
94    /// let five = IntegerVector::from_str("(5)").unwrap();
95    /// let zero_zero = IntegerVector::from_str("(0, 0)").unwrap();
96    ///
97    /// // Dimension decides, whatever the elements.
98    /// assert!(ShortlexIntegerVector(five.clone()) < ShortlexIntegerVector(zero_zero.clone()));
99    ///
100    /// // The wrapper makes vectors usable in ordered collections.
101    /// let set: BTreeSet<_> = [zero_zero, five]
102    ///     .into_iter()
103    ///     .map(ShortlexIntegerVector)
104    ///     .collect();
105    /// assert_eq!(
106    ///     set.iter().map(|v| v.to_string()).collect::<Vec<_>>(),
107    ///     ["(5)", "(0, 0)"]
108    /// );
109    /// ```
110    #[inline]
111    fn cmp(&self, other: &Self) -> Ordering {
112        self.as_ref().cmp(&other.as_ref())
113    }
114}
115
116impl PartialOrd for ShortlexIntegerVector {
117    /// Compares two [`ShortlexIntegerVector`]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}