1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Copyright © 2024 Mikhail Hogrefe
//
// This file is part of Malachite.
//
// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.

use crate::Float;
use crate::InnerFloat::Finite;
use malachite_base::num::arithmetic::traits::IsPowerOf2;
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::basic::signeds::PrimitiveSigned;
use malachite_nz::platform::Limb;

const HIGH_BIT: Limb = 1 << (Limb::WIDTH - 1);

impl IsPowerOf2 for Float {
    /// Determines whether a [`Float`] is an integer power of 2.
    ///
    /// $f(x) = (\exists n \in \Z : 2^n = x)$.
    ///
    /// [`Float`]s that are NaN, infinite, or zero are not powers of 2.
    ///
    /// # Worst-case complexity
    /// $T(n) = O(n)$
    ///
    /// $M(n) = O(1)$
    ///
    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
    ///
    /// # Examples
    /// ```
    /// use malachite_base::num::arithmetic::traits::IsPowerOf2;
    /// use malachite_base::num::basic::traits::{NaN, One, OneHalf, Two};
    /// use malachite_float::Float;
    ///
    /// assert_eq!(Float::NAN.is_power_of_2(), false);
    ///
    /// assert_eq!(Float::ONE.is_power_of_2(), true);
    /// assert_eq!(Float::TWO.is_power_of_2(), true);
    /// assert_eq!(Float::ONE_HALF.is_power_of_2(), true);
    /// assert_eq!(Float::from(1024).is_power_of_2(), true);
    ///
    /// assert_eq!(Float::from(3).is_power_of_2(), false);
    /// assert_eq!(Float::from(1025).is_power_of_2(), false);
    /// assert_eq!(Float::from(0.1f64).is_power_of_2(), false);
    /// ```
    fn is_power_of_2(&self) -> bool {
        match self {
            Float(Finite {
                sign: true,
                significand,
                ..
            }) => {
                let mut first = true;
                for x in significand.limbs().rev() {
                    if first {
                        if x != HIGH_BIT {
                            return false;
                        }
                        first = false;
                    } else if x != 0 {
                        return false;
                    }
                }
                true
            }
            _ => false,
        }
    }
}

pub(crate) fn float_is_signed_min<T: PrimitiveSigned>(f: &Float) -> bool {
    match f {
        Float(Finite {
            sign: false,
            exponent,
            significand,
            ..
        }) => {
            if *exponent != T::WIDTH as i64 {
                return false;
            }
            let mut first = true;
            for x in significand.limbs().rev() {
                if first {
                    if x != HIGH_BIT {
                        return false;
                    }
                    first = false;
                } else if x != 0 {
                    return false;
                }
            }
            true
        }
        _ => false,
    }
}