malachite_nz/natural/comparison/partial_cmp_primitive_int.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::natural::InnerNatural::{Large, Small};
10use crate::natural::{Natural, bit_to_limb_count_ceiling, limb_to_bit_count};
11use crate::platform::Limb;
12use core::cmp::Ordering::{self, *};
13use malachite_base::num::basic::integers::{PrimitiveInt, USIZE_IS_U32};
14use malachite_base::num::conversion::traits::WrappingFrom;
15use malachite_base::num::logic::traits::SignificantBits;
16
17macro_rules! impl_partial_ord_limb {
18 ($u: ident) => {
19 impl PartialOrd<$u> for Natural {
20 /// Compares a [`Natural`] to a [`Limb`](crate#limbs).
21 ///
22 /// # Worst-case complexity
23 /// Constant time and additional memory.
24 ///
25 /// # Examples
26 /// See [here](super::partial_cmp_primitive_int#partial_cmp).
27 fn partial_cmp(&self, other: &$u) -> Option<Ordering> {
28 match self {
29 Natural(Small(small)) => small.partial_cmp(other),
30 Natural(Large(_)) => Some(Greater),
31 }
32 }
33 }
34
35 impl PartialOrd<Natural> for $u {
36 /// Compares a [`Limb`](crate#limbs) to a [`Natural`].
37 ///
38 /// # Worst-case complexity
39 /// Constant time and additional memory.
40 ///
41 /// # Examples
42 /// See [here](super::partial_cmp_primitive_int#partial_cmp).
43 #[inline]
44 fn partial_cmp(&self, other: &Natural) -> Option<Ordering> {
45 other.partial_cmp(self).map(Ordering::reverse)
46 }
47 }
48 };
49}
50
51macro_rules! impl_partial_ord_smaller_than_limb {
52 ($u: ident) => {
53 impl PartialOrd<$u> for Natural {
54 /// Compares a [`Natural`] to a value of an unsigned primitive integer type that's
55 /// smaller than a [`Limb`](crate#limbs).
56 ///
57 /// # Worst-case complexity
58 /// Constant time and additional memory.
59 ///
60 /// # Examples
61 /// See [here](super::partial_cmp_primitive_int#partial_cmp).
62 #[inline]
63 fn partial_cmp(&self, other: &$u) -> Option<Ordering> {
64 self.partial_cmp(&Limb::from(*other))
65 }
66 }
67
68 impl PartialOrd<Natural> for $u {
69 /// Compares a value of an unsigned primitive integer type that's smaller than a
70 /// [`Limb`](crate#limbs) to a [`Natural`].
71 ///
72 /// # Worst-case complexity
73 /// Constant time and additional memory.
74 ///
75 /// # Examples
76 /// See [here](super::partial_cmp_primitive_int#partial_cmp).
77 #[inline]
78 fn partial_cmp(&self, other: &Natural) -> Option<Ordering> {
79 other.partial_cmp(self).map(Ordering::reverse)
80 }
81 }
82 };
83}
84
85macro_rules! impl_partial_ord_larger_than_limb_or_usize {
86 ($u: ident) => {
87 impl PartialOrd<Natural> for $u {
88 /// Compares a value of an unsigned primitive integer type that's larger than a
89 /// [`Limb`](crate#limbs) to a [`Natural`]. This implementation is general enough to
90 /// also work for [`usize`], regardless of whether it is equal in width to
91 /// [`Limb`](crate#limbs).
92 ///
93 /// # Worst-case complexity
94 /// Constant time and additional memory.
95 ///
96 /// # Examples
97 /// See [here](super::partial_cmp_primitive_int#partial_cmp).
98 #[inline]
99 fn partial_cmp(&self, other: &Natural) -> Option<Ordering> {
100 other.partial_cmp(self).map(Ordering::reverse)
101 }
102 }
103 };
104}
105
106macro_rules! impl_partial_ord_larger_than_limb {
107 ($u: ident) => {
108 impl_partial_ord_larger_than_limb_or_usize!($u);
109
110 impl PartialOrd<$u> for Natural {
111 /// Compares a [`Natural`] to a value of an unsigned primitive integer type that's
112 /// larger than a [`Limb`](crate#limbs).
113 ///
114 /// # Worst-case complexity
115 /// Constant time and additional memory.
116 ///
117 /// # Examples
118 /// See [here](super::partial_cmp_primitive_int#partial_cmp).
119 #[inline]
120 fn partial_cmp(&self, other: &$u) -> Option<Ordering> {
121 let limb_count = bit_to_limb_count_ceiling(other.significant_bits());
122 let limb_count_cmp = usize::wrapping_from(self.limb_count()).cmp(&limb_count);
123 if limb_count_cmp != Equal || limb_count == 0 {
124 return Some(limb_count_cmp);
125 }
126 let width = Limb::WIDTH;
127 let mut i = limb_to_bit_count(limb_count);
128 let mut mask = $u::from(Limb::MAX) << (i - width);
129 for limb in self.limbs().rev() {
130 i -= width;
131 let limb_cmp = limb.cmp(&Limb::wrapping_from((other & mask) >> i));
132 if limb_cmp != Equal {
133 return Some(limb_cmp);
134 }
135 mask >>= width;
136 }
137 Some(Equal)
138 }
139 }
140 };
141}
142
143macro_rules! impl_signed {
144 ($t: ident) => {
145 impl PartialOrd<$t> for Natural {
146 /// Compares a [`Natural`] to a signed primitive integer.
147 ///
148 /// # Worst-case complexity
149 /// Constant time and additional memory.
150 ///
151 /// # Examples
152 /// See [here](super::partial_cmp_primitive_int#partial_cmp).
153 fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
154 if *other < 0 {
155 Some(Greater)
156 } else {
157 self.partial_cmp(&other.unsigned_abs())
158 }
159 }
160 }
161
162 impl PartialOrd<Natural> for $t {
163 /// Compares a signed primitive integer to a [`Natural`].
164 ///
165 /// # Worst-case complexity
166 /// Constant time and additional memory.
167 ///
168 /// # Examples
169 /// See [here](super::partial_cmp_primitive_int#partial_cmp).
170 #[inline]
171 fn partial_cmp(&self, other: &Natural) -> Option<Ordering> {
172 other.partial_cmp(self).map(Ordering::reverse)
173 }
174 }
175 };
176}
177
178impl_partial_ord_smaller_than_limb!(u8);
179impl_partial_ord_smaller_than_limb!(u16);
180#[cfg(feature = "32_bit_limbs")]
181impl_partial_ord_limb!(u32);
182#[cfg(not(feature = "32_bit_limbs"))]
183impl_partial_ord_smaller_than_limb!(u32);
184#[cfg(feature = "32_bit_limbs")]
185impl_partial_ord_larger_than_limb!(u64);
186#[cfg(not(feature = "32_bit_limbs"))]
187impl_partial_ord_limb!(u64);
188impl_partial_ord_larger_than_limb!(u128);
189impl_partial_ord_larger_than_limb_or_usize!(usize);
190
191apply_to_signeds!(impl_signed);
192
193impl PartialOrd<usize> for Natural {
194 /// Compares a [`Natural`] to a [`usize`].
195 ///
196 /// # Worst-case complexity
197 /// Constant time and additional memory.
198 ///
199 /// # Examples
200 /// See [here](super::partial_cmp_primitive_int#partial_cmp).
201 #[inline]
202 fn partial_cmp(&self, other: &usize) -> Option<Ordering> {
203 if USIZE_IS_U32 {
204 self.partial_cmp(&u32::wrapping_from(*other))
205 } else {
206 assert_eq!(usize::WIDTH, u64::WIDTH);
207 self.partial_cmp(&u64::wrapping_from(*other))
208 }
209 }
210}