@@ -19,3 +19,69 @@ pub fn pad_bytes_u64<const ALIGN: u64>(n: u64) -> u64 {
19
19
debug_assert ! ( is_pwr_two( ALIGN ) ) ;
20
20
( ALIGN - ( n & ( ALIGN - 1 ) ) ) & ( ALIGN - 1 )
21
21
}
22
+
23
+ // This is a lookup table for the log2 of the first 256 numbers
24
+ const LOG_TABLE_256 : [ u8 ; 256 ] = [
25
+ 0 , 1 , 2 , 2 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,
26
+ 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 ,
27
+ 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ,
28
+ 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 , 7 ,
29
+ 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 ,
30
+ 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 ,
31
+ 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 ,
32
+ 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 ,
33
+ ] ;
34
+
35
+ /// Returns the number of bits needed to represent the given number
36
+ ///
37
+ /// Inspired by https://graphics.stanford.edu/~seander/bithacks.html
38
+ pub fn log_2_ceil ( val : u32 ) -> u32 {
39
+ assert ! ( val > 0 ) ;
40
+ let upper_half = val >> 16 ;
41
+ if upper_half == 0 {
42
+ let third_quarter = val >> 8 ;
43
+ if third_quarter == 0 {
44
+ // Use lowest 8 bits (upper 24 are 0)
45
+ LOG_TABLE_256 [ val as usize ] as u32
46
+ } else {
47
+ // Use bits 16..24 (0..16 are 0)
48
+ LOG_TABLE_256 [ third_quarter as usize ] as u32 + 8
49
+ }
50
+ } else {
51
+ let first_quarter = upper_half >> 8 ;
52
+ if first_quarter == 0 {
53
+ // Use bits 8..16 (0..8 are 0)
54
+ 16 + LOG_TABLE_256 [ upper_half as usize ] as u32
55
+ } else {
56
+ // Use most significant bits (it's a big number!)
57
+ 24 + LOG_TABLE_256 [ first_quarter as usize ] as u32
58
+ }
59
+ }
60
+ }
61
+
62
+ #[ cfg( test) ]
63
+
64
+ pub mod tests {
65
+ use crate :: utils:: bit:: log_2_ceil;
66
+
67
+ #[ test]
68
+ fn test_log_2_ceil ( ) {
69
+ fn classic_approach ( mut val : u32 ) -> u32 {
70
+ let mut counter = 0 ;
71
+ while val > 0 {
72
+ val >>= 1 ;
73
+ counter += 1 ;
74
+ }
75
+ counter
76
+ }
77
+
78
+ for i in 1 ..( 16 * 1024 ) {
79
+ assert_eq ! ( log_2_ceil( i) , classic_approach( i) ) ;
80
+ }
81
+ assert_eq ! ( log_2_ceil( 50 * 1024 ) , classic_approach( 50 * 1024 ) ) ;
82
+ assert_eq ! (
83
+ log_2_ceil( 1024 * 1024 * 1024 ) ,
84
+ classic_approach( 1024 * 1024 * 1024 )
85
+ ) ;
86
+ }
87
+ }
0 commit comments