|
| 1 | +use traits::Zero; |
| 2 | + |
| 3 | +use Integer; |
| 4 | + |
| 5 | +pub trait Power: Integer { |
| 6 | + /// Returns whether `self` is a power of `other`. |
| 7 | + /// |
| 8 | + /// # Examples |
| 9 | + /// |
| 10 | + /// ~~~ |
| 11 | + /// use num_integer::Power; |
| 12 | + /// assert_eq!(100u32.is_power_of(&10), true); |
| 13 | + /// assert_eq!(4u32.is_power_of(&10), false); |
| 14 | + /// ~~~ |
| 15 | + #[inline] |
| 16 | + fn is_power_of(&self, other: &Self) -> bool { |
| 17 | + self.checked_next_power_of(other).map_or(false, |new| self == &new) |
| 18 | + } |
| 19 | + |
| 20 | + /// Returns the truncated base-`other` logarithm of `self`. |
| 21 | + /// Panics if `self.is_zero()`. |
| 22 | + /// |
| 23 | + /// # Examples |
| 24 | + /// |
| 25 | + /// ~~~ |
| 26 | + /// use num_integer::Power; |
| 27 | + /// assert_eq!(100u32.log(&10), 2); |
| 28 | + /// assert_eq!(4u32.log(&10), 0); |
| 29 | + /// ~~~ |
| 30 | + #[inline] |
| 31 | + fn log(&self, other: &Self) -> u32 { |
| 32 | + self.checked_log(other).expect("log: `self` is zero") |
| 33 | + } |
| 34 | + |
| 35 | + /// Returns the truncated base-`other` logarithm of `self`, or `None` if `self.is_zero()`. |
| 36 | + /// |
| 37 | + /// # Examples |
| 38 | + /// |
| 39 | + /// ~~~ |
| 40 | + /// use num_integer::Power; |
| 41 | + /// assert_eq!(100u32.checked_log(&10), Some(2)); |
| 42 | + /// assert_eq!(4u32.checked_log(&10), Some(0)); |
| 43 | + /// assert_eq!(0u32.checked_log(&10), None); |
| 44 | + /// ~~~ |
| 45 | + fn checked_log(&self, other: &Self) -> Option<u32>; |
| 46 | + |
| 47 | + /// Returns the least power of `other` not less than `self`, or `0` if the value is out of |
| 48 | + /// bounds of the type. |
| 49 | + /// |
| 50 | + /// # Examples |
| 51 | + /// |
| 52 | + /// ~~~ |
| 53 | + /// use num_integer::Power; |
| 54 | + /// assert_eq!(100u32.wrapping_next_power_of(&10), 100); |
| 55 | + /// assert_eq!(4u32.wrapping_next_power_of(&10), 10); |
| 56 | + /// assert_eq!(200u8.wrapping_next_power_of(&10), 0); |
| 57 | + /// ~~~ |
| 58 | + #[inline] |
| 59 | + fn wrapping_next_power_of(&self, other: &Self) -> Self { |
| 60 | + self.checked_next_power_of(other).unwrap_or(Self::zero()) |
| 61 | + } |
| 62 | + |
| 63 | + /// Returns the least power of `other` not less than `self`, or `None` if the value is out |
| 64 | + /// of bounds of the type. |
| 65 | + /// |
| 66 | + /// # Examples |
| 67 | + /// |
| 68 | + /// ~~~ |
| 69 | + /// use num_integer::Power; |
| 70 | + /// assert_eq!(100u32.checked_next_power_of(&10), Some(100)); |
| 71 | + /// assert_eq!(4u32.checked_next_power_of(&10), Some(10)); |
| 72 | + /// assert_eq!(200u8.checked_next_power_of(&10), None); |
| 73 | + /// ~~~ |
| 74 | + fn checked_next_power_of(&self, other: &Self) -> Option<Self>; |
| 75 | + |
| 76 | + /// Returns the least power of `other` not less than `self`. |
| 77 | + /// Panics if the value is out of bounds of the type. |
| 78 | + /// |
| 79 | + /// # Examples |
| 80 | + /// |
| 81 | + /// ~~~ |
| 82 | + /// use num_integer::Power; |
| 83 | + /// assert_eq!(100u32.next_power_of(&10), 100); |
| 84 | + /// assert_eq!(4u32.next_power_of(&10), 10); |
| 85 | + /// ~~~ |
| 86 | + #[inline] |
| 87 | + fn next_power_of(&self, other: &Self) -> Self { |
| 88 | + self.checked_next_power_of(other).expect("checked_next_power_of: out of range") |
| 89 | + } |
| 90 | +} |
| 91 | + |
| 92 | +macro_rules! impl_Power { |
| 93 | + ($t:ty) => (impl Power for $t { |
| 94 | + #[inline] |
| 95 | + fn checked_log(&self, other: &Self) -> Option<u32> { |
| 96 | + let mut n = self.clone(); |
| 97 | + let mut a = None; |
| 98 | + while !n.is_zero() { |
| 99 | + a = Some(a.map_or(0, |a| a+1)); |
| 100 | + n /= other; |
| 101 | + } |
| 102 | + a |
| 103 | + } |
| 104 | + |
| 105 | + #[inline] |
| 106 | + fn checked_next_power_of(&self, other: &Self) -> Option<Self> { |
| 107 | + self.checked_sub(1) |
| 108 | + .map_or(Some(1), |new| |
| 109 | + traits::checked_pow(*other, |
| 110 | + new.checked_log(other) |
| 111 | + .map_or(0, |a| a as Self + 1) as usize)) |
| 112 | + } |
| 113 | + }); |
| 114 | + |
| 115 | + ($($t:ty),*) => { $(impl_Power!($t);)* }; |
| 116 | +} |
| 117 | + |
| 118 | +impl_Power!(usize, u8, u16, u32, u64, u128); |
0 commit comments