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);