malachite_q/comparison/
partial_cmp_abs_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;
12use malachite_base::num::comparison::traits::{OrdAbs, PartialOrdAbs};
13use malachite_base::num::conversion::traits::ExactFrom;
14
15macro_rules! impl_float {
16    ($t: ident) => {
17        impl PartialOrdAbs<$t> for Rational {
18            /// Compares the absolute values of a [`Rational`] and a primitive float.
19            ///
20            /// # Worst-case complexity
21            /// $T(n) = O(n \log n \log\log n)$
22            ///
23            /// $M(n) = O(n \log n)$
24            ///
25            /// where $T$ is time, $M$ is additional memory, and $n$ is
26            /// `max(self.significant_bits(), other.sci_exponent().abs())`.
27            ///
28            /// # Examples
29            /// See [here](super::partial_cmp_abs_primitive_float#partial_cmp_abs).
30            fn partial_cmp_abs(&self, other: &$t) -> Option<Ordering> {
31                if other.is_nan() {
32                    None
33                } else if *other == 0.0 {
34                    self.partial_cmp_abs(&0u32)
35                } else if !other.is_finite() || *self == 0u32 {
36                    Some(Less)
37                } else {
38                    let ord_cmp = self
39                        .floor_log_base_2_abs()
40                        .cmp(&other.abs().floor_log_base_2());
41                    Some(if ord_cmp != Equal {
42                        ord_cmp
43                    } else {
44                        self.cmp_abs(&Rational::exact_from(*other))
45                    })
46                }
47            }
48        }
49
50        impl PartialOrdAbs<Rational> for $t {
51            /// Compares the absolute values of a primitive float and a [`Rational`].
52            ///
53            /// # Worst-case complexity
54            /// $T(n) = O(n \log n \log\log n)$
55            ///
56            /// $M(n) = O(n \log n)$
57            ///
58            /// where $T$ is time, $M$ is additional memory, and $n$ is
59            /// `max(self.sci_exponent().abs(), other.significant_bits())`.
60            ///
61            /// See [here](super::partial_cmp_abs_primitive_float#partial_cmp_abs).
62            #[inline]
63            fn partial_cmp_abs(&self, other: &Rational) -> Option<Ordering> {
64                other.partial_cmp_abs(self).map(Ordering::reverse)
65            }
66        }
67    };
68}
69apply_to_primitive_floats!(impl_float);