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
use num_traits::PrimInt;

pub trait IntLog2: PrimInt {
    fn log2(self) -> Self {
        Self::from(8 * std::mem::size_of::<Self>() - (self.leading_zeros() as usize) - 1).unwrap()
    }
}

impl<I: PrimInt> IntLog2 for I {}

pub trait VecLog2 {
    fn log2(n: usize) -> Self;
}

impl<I: PrimInt> VecLog2 for Vec<I> {
    fn log2(n: usize) -> Vec<I> {
        let mut log2 = vec![I::zero(); n];
        for i in 2..n {
            log2[i] = log2[i / 2] + I::one();
        }
        log2
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_log2() {
        assert_eq!(0x10u8.log2(), 4);
        assert_eq!(0x0111u16.log2(), 8);
        assert_eq!(0x0101i32.log2(), 8);
    }

    #[test]
    fn test_log2_vec() {
        let log2 = Vec::<i128>::log2(17);
        let expected = &[0i128, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4];
        assert_eq!(&log2, expected);
    }
}