malachite_q/comparison/
partial_cmp_primitive_float.rs

1// Copyright © 2025 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::Rational;
10use core::cmp::Ordering::{self, *};
11use malachite_base::num::arithmetic::traits::FloorLogBase2;
12
13macro_rules! impl_float {
14    ($t: ident) => {
15        impl PartialOrd<$t> for Rational {
16            /// Compares a [`Rational`] to a primitive float.
17            ///
18            /// # Worst-case complexity
19            /// $T(n) = O(n \log n \log\log n)$
20            ///
21            /// $M(n) = O(n \log n)$
22            ///
23            /// where $T$ is time, $M$ is additional memory, and $n$ is
24            /// `max(self.significant_bits(), other.sci_exponent().abs())`.
25            ///
26            /// # Examples
27            /// See [here](super::partial_cmp_primitive_float#partial_cmp).
28            fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
29                if other.is_nan() {
30                    None
31                } else if self.sign != (*other >= 0.0) {
32                    Some(if self.sign { Greater } else { Less })
33                } else if !other.is_finite() {
34                    Some(if self.sign { Less } else { Greater })
35                } else if *other == 0.0 {
36                    self.partial_cmp(&0u32)
37                } else if *self == 0u32 {
38                    0.0.partial_cmp(other)
39                } else {
40                    let ord_cmp = self
41                        .floor_log_base_2_abs()
42                        .cmp(&other.abs().floor_log_base_2());
43                    Some(if ord_cmp != Equal {
44                        if self.sign {
45                            ord_cmp
46                        } else {
47                            ord_cmp.reverse()
48                        }
49                    } else {
50                        self.cmp(&Rational::try_from(*other).unwrap())
51                    })
52                }
53            }
54        }
55
56        impl PartialOrd<Rational> for $t {
57            /// Compares a primitive float to a [`Rational`].
58            ///
59            /// # Worst-case complexity
60            /// $T(n) = O(n \log n \log\log n)$
61            ///
62            /// $M(n) = O(n \log n)$
63            ///
64            /// where $T$ is time, $M$ is additional memory, and $n$ is
65            /// `max(other.sci_exponent().abs(), self.significant_bits())`.
66            ///
67            /// # Examples
68            /// See [here](super::partial_cmp_primitive_float#partial_cmp).
69            #[inline]
70            fn partial_cmp(&self, other: &Rational) -> Option<Ordering> {
71                other.partial_cmp(self).map(Ordering::reverse)
72            }
73        }
74    };
75}
76apply_to_primitive_floats!(impl_float);