malachite_float/arithmetic/
is_power_of_2.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::Float;
10use crate::InnerFloat::Finite;
11use malachite_base::num::arithmetic::traits::IsPowerOf2;
12use malachite_base::num::basic::signeds::PrimitiveSigned;
13use malachite_nz::natural::LIMB_HIGH_BIT;
14
15impl IsPowerOf2 for Float {
16    /// Determines whether a [`Float`] is an integer power of 2.
17    ///
18    /// $f(x) = (\exists n \in \Z : 2^n = x)$.
19    ///
20    /// [`Float`]s that are NaN, infinite, or zero are not powers of 2.
21    ///
22    /// # Worst-case complexity
23    /// $T(n) = O(n)$
24    ///
25    /// $M(n) = O(1)$
26    ///
27    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
28    ///
29    /// # Examples
30    /// ```
31    /// use malachite_base::num::arithmetic::traits::IsPowerOf2;
32    /// use malachite_base::num::basic::traits::{NaN, One, OneHalf, Two};
33    /// use malachite_float::Float;
34    ///
35    /// assert_eq!(Float::NAN.is_power_of_2(), false);
36    ///
37    /// assert_eq!(Float::ONE.is_power_of_2(), true);
38    /// assert_eq!(Float::TWO.is_power_of_2(), true);
39    /// assert_eq!(Float::ONE_HALF.is_power_of_2(), true);
40    /// assert_eq!(Float::from(1024).is_power_of_2(), true);
41    ///
42    /// assert_eq!(Float::from(3).is_power_of_2(), false);
43    /// assert_eq!(Float::from(1025).is_power_of_2(), false);
44    /// assert_eq!(Float::from(0.1f64).is_power_of_2(), false);
45    /// ```
46    fn is_power_of_2(&self) -> bool {
47        match self {
48            Self(Finite {
49                sign: true,
50                significand,
51                ..
52            }) => {
53                let mut first = true;
54                for x in significand.limbs().rev() {
55                    if first {
56                        if x != LIMB_HIGH_BIT {
57                            return false;
58                        }
59                        first = false;
60                    } else if x != 0 {
61                        return false;
62                    }
63                }
64                true
65            }
66            _ => false,
67        }
68    }
69}
70
71pub(crate) fn abs_is_power_of_2(x: &Float) -> bool {
72    match x {
73        Float(Finite { significand, .. }) => {
74            let mut first = true;
75            for x in significand.limbs().rev() {
76                if first {
77                    if x != LIMB_HIGH_BIT {
78                        return false;
79                    }
80                    first = false;
81                } else if x != 0 {
82                    return false;
83                }
84            }
85            true
86        }
87        _ => false,
88    }
89}
90
91pub(crate) fn float_is_signed_min<T: PrimitiveSigned>(f: &Float) -> bool {
92    match f {
93        Float(Finite {
94            sign: false,
95            exponent,
96            significand,
97            ..
98        }) => {
99            if *exponent != T::WIDTH as i32 {
100                return false;
101            }
102            let mut first = true;
103            for x in significand.limbs().rev() {
104                if first {
105                    if x != LIMB_HIGH_BIT {
106                        return false;
107                    }
108                    first = false;
109                } else if x != 0 {
110                    return false;
111                }
112            }
113            true
114        }
115        _ => false,
116    }
117}