1
//! Utilities for working with numbers, particularly powers of two.
2

            
3
/// Returns true when the given value is a power of two.
4
///
5
/// A number is a power of two when exactly a single bit is one.
6
38
pub fn is_power_of_two<T>(value: T) -> bool
7
38
where
8
38
    T: num::PrimInt,
9
{
10
38
    !value.is_zero() && (value & (value - T::one())).is_zero()
11
38
}
12

            
13
/// Returns the smallest power of two that is larger than or equal to the given value.
14
///
15
/// # Examples
16
/// ```
17
/// use merc_number::round_up_to_power_of_two;
18
///
19
/// assert_eq!(round_up_to_power_of_two(3u32), 4);
20
/// assert_eq!(round_up_to_power_of_two(4u32), 4);
21
/// assert_eq!(round_up_to_power_of_two(5u32), 8);
22
/// ```
23
14
pub fn round_up_to_power_of_two<T>(mut value: T) -> T
24
14
where
25
14
    T: num::PrimInt,
26
{
27
14
    if is_power_of_two(value) {
28
4
        return value;
29
10
    }
30

            
31
10
    if value.is_zero() {
32
1
        return T::one();
33
9
    }
34

            
35
    // Set all bits to the right of the highest 1-bit
36
9
    let bits = std::mem::size_of::<T>() * 8;
37
312
    for i in 0..bits {
38
312
        value = value | (value >> i);
39
312
    }
40

            
41
    // Add one to get the next power of two
42
9
    debug_assert!(is_power_of_two(value + T::one()));
43
9
    value + T::one()
44
14
}
45

            
46
#[cfg(test)]
47
mod tests {
48
    use super::*;
49

            
50
    #[test]
51
1
    fn test_is_power_of_two() {
52
        // Test powers of 2
53
1
        assert!(is_power_of_two(1u32));
54
1
        assert!(is_power_of_two(2u32));
55
1
        assert!(is_power_of_two(4u32));
56
1
        assert!(is_power_of_two(8u32));
57
1
        assert!(is_power_of_two(16u32));
58

            
59
        // Test non-powers of 2
60
1
        assert!(!is_power_of_two(0u32));
61
1
        assert!(!is_power_of_two(3u32));
62
1
        assert!(!is_power_of_two(5u32));
63
1
        assert!(!is_power_of_two(6u32));
64
1
        assert!(!is_power_of_two(7u32));
65
1
    }
66

            
67
    #[test]
68
1
    fn test_round_up_to_power_of_two() {
69
        // Test exact powers of 2
70
1
        assert_eq!(round_up_to_power_of_two(1u32), 1);
71
1
        assert_eq!(round_up_to_power_of_two(2u32), 2);
72
1
        assert_eq!(round_up_to_power_of_two(4u32), 4);
73
1
        assert_eq!(round_up_to_power_of_two(8u32), 8);
74

            
75
        // Test values in between
76
1
        assert_eq!(round_up_to_power_of_two(0u32), 1);
77
1
        assert_eq!(round_up_to_power_of_two(3u32), 4);
78
1
        assert_eq!(round_up_to_power_of_two(5u32), 8);
79
1
        assert_eq!(round_up_to_power_of_two(7u32), 8);
80
1
        assert_eq!(round_up_to_power_of_two(9u32), 16);
81
1
    }
82

            
83
    #[test]
84
1
    fn test_different_types() {
85
1
        assert!(is_power_of_two(4u8));
86
1
        assert!(is_power_of_two(8u16));
87
1
        assert!(is_power_of_two(16u32));
88
1
        assert!(is_power_of_two(32u64));
89
1
        assert!(is_power_of_two(64usize));
90

            
91
1
        assert_eq!(round_up_to_power_of_two(3u8), 4);
92
1
        assert_eq!(round_up_to_power_of_two(5u16), 8);
93
1
        assert_eq!(round_up_to_power_of_two(9u32), 16);
94
1
        assert_eq!(round_up_to_power_of_two(17u64), 32);
95
1
        assert_eq!(round_up_to_power_of_two(33usize), 64);
96
1
    }
97
}