base/
math.rs

1pub fn previous_po2(number: usize) -> usize {
2   return 1 << (usize::BITS as usize - number.leading_zeros() as usize - 1);
3}
4
5/// Basic power-of-2 integer math.
6pub trait PowersOf2 {
7   fn powerOf2(self) -> bool;
8   fn nextPowerOf2(self) -> usize;
9   fn log2(self) -> u8;
10}
11
12impl PowersOf2 for usize {
13   /// This code is based on
14   /// http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
15   fn powerOf2(self) -> bool {
16      self != 0 && (self & (self - 1)) == 0
17   }
18
19   /// Calculate the next power of two.
20   ///
21   /// Based on
22   /// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
23   fn nextPowerOf2(self) -> usize {
24      // Pick off this immediately in hopes that the optimizer can see it
25      // easily.
26      if self == 0 {
27         return 1;
28      }
29
30      let mut v = Wrapping(self);
31
32      v = v - Wrapping(1);
33      v = v | (v >> 1);
34      v = v | (v >> 2);
35      v = v | (v >> 4);
36      v = v | (v >> 8);
37      v = v | (v >> 16);
38      if size_of::<usize>() > 4 {
39         v = v | (v >> 32);
40      }
41      v = v + Wrapping(1);
42
43      let result = match v {
44         Wrapping(v) => v,
45      };
46      assert!(result.powerOf2());
47      assert!(result >= self && self > result >> 1);
48      result
49   }
50
51   /// Calculate the base-2 logarithm of this value.
52   ///
53   /// This will normally round down, except for the case of `0.log2()`,
54   /// which will return 0.
55   ///
56   /// Based on the obvious code at
57   /// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
58   fn log2(self) -> u8 {
59      let mut temp = self;
60      let mut result = 0;
61      temp >>= 1;
62      while temp != 0 {
63         result += 1;
64         temp >>= 1;
65      }
66      result
67   }
68}
69
70// IMPORTS //
71
72use core::{mem::size_of, num::Wrapping};