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}