From 2200568418090278b56d529a95549195fb38b4e2 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Mon, 17 Dec 2018 16:38:04 -0800 Subject: [PATCH 1/2] =?UTF-8?q?Define=20`trait=20Power`,=20na=C3=AFvely=20?= =?UTF-8?q?for=20now?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib.rs | 3 ++ src/power.rs | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 src/power.rs diff --git a/src/lib.rs b/src/lib.rs index 41e0139..f084d06 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,9 @@ mod roots; pub use roots::Roots; pub use roots::{sqrt, cbrt, nth_root}; +mod power; +pub use power::Power; + pub trait Integer: Sized + Num + PartialOrd + Ord + Eq { /// Floored integer division. /// diff --git a/src/power.rs b/src/power.rs new file mode 100644 index 0000000..8f734a4 --- /dev/null +++ b/src/power.rs @@ -0,0 +1,118 @@ +use traits::Zero; + +use Integer; + +pub trait Power: Integer { + /// Returns whether `self` is a power of `other`. + /// + /// # Examples + /// + /// ~~~ + /// use num_integer::Power; + /// assert_eq!(100u32.is_power_of(&10), true); + /// assert_eq!(4u32.is_power_of(&10), false); + /// ~~~ + #[inline] + fn is_power_of(&self, other: &Self) -> bool { + self.checked_next_power_of(other).map_or(false, |new| self == &new) + } + + /// Returns the truncated base-`other` logarithm of `self`. + /// Panics if `self.is_zero()`. + /// + /// # Examples + /// + /// ~~~ + /// use num_integer::Power; + /// assert_eq!(100u32.log(&10), 2); + /// assert_eq!(4u32.log(&10), 0); + /// ~~~ + #[inline] + fn log(&self, other: &Self) -> u32 { + self.checked_log(other).expect("log: `self` is zero") + } + + /// Returns the truncated base-`other` logarithm of `self`, or `None` if `self.is_zero()`. + /// + /// # Examples + /// + /// ~~~ + /// use num_integer::Power; + /// assert_eq!(100u32.checked_log(&10), Some(2)); + /// assert_eq!(4u32.checked_log(&10), Some(0)); + /// assert_eq!(0u32.checked_log(&10), None); + /// ~~~ + fn checked_log(&self, other: &Self) -> Option; + + /// Returns the least power of `other` not less than `self`, or `0` if the value is out of + /// bounds of the type. + /// + /// # Examples + /// + /// ~~~ + /// use num_integer::Power; + /// assert_eq!(100u32.wrapping_next_power_of(&10), 100); + /// assert_eq!(4u32.wrapping_next_power_of(&10), 10); + /// assert_eq!(200u8.wrapping_next_power_of(&10), 0); + /// ~~~ + #[inline] + fn wrapping_next_power_of(&self, other: &Self) -> Self { + self.checked_next_power_of(other).unwrap_or(Self::zero()) + } + + /// Returns the least power of `other` not less than `self`, or `None` if the value is out + /// of bounds of the type. + /// + /// # Examples + /// + /// ~~~ + /// use num_integer::Power; + /// assert_eq!(100u32.checked_next_power_of(&10), Some(100)); + /// assert_eq!(4u32.checked_next_power_of(&10), Some(10)); + /// assert_eq!(200u8.checked_next_power_of(&10), None); + /// ~~~ + fn checked_next_power_of(&self, other: &Self) -> Option; + + /// Returns the least power of `other` not less than `self`. + /// Panics if the value is out of bounds of the type. + /// + /// # Examples + /// + /// ~~~ + /// use num_integer::Power; + /// assert_eq!(100u32.next_power_of(&10), 100); + /// assert_eq!(4u32.next_power_of(&10), 10); + /// ~~~ + #[inline] + fn next_power_of(&self, other: &Self) -> Self { + self.checked_next_power_of(other).expect("checked_next_power_of: out of range") + } +} + +macro_rules! impl_Power { + ($t:ty) => (impl Power for $t { + #[inline] + fn checked_log(&self, other: &Self) -> Option { + let mut n = self.clone(); + let mut a = None; + while !n.is_zero() { + a = Some(a.map_or(0, |a| a+1)); + n /= other; + } + a + } + + #[inline] + fn checked_next_power_of(&self, other: &Self) -> Option { + self.checked_sub(1) + .map_or(Some(1), |new| + traits::checked_pow(*other, + new.checked_log(other) + .map_or(0, |a| a as Self + 1) as usize)) + } + }); + + ($($t:ty),*) => { $(impl_Power!($t);)* }; +} + +impl_Power!(usize, u8, u16, u32, u64, u128); From a9bc5f51e55b0f533ce14a0ad5ba90d06bca59c7 Mon Sep 17 00:00:00 2001 From: M Farkas-Dyck Date: Mon, 17 Dec 2018 20:41:11 -0800 Subject: [PATCH 2/2] unbreak on older Rust --- src/power.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/power.rs b/src/power.rs index 8f734a4..22ec0d9 100644 --- a/src/power.rs +++ b/src/power.rs @@ -1,4 +1,4 @@ -use traits::Zero; +use traits::{Zero, checked_pow}; use Integer; @@ -97,7 +97,7 @@ macro_rules! impl_Power { let mut a = None; while !n.is_zero() { a = Some(a.map_or(0, |a| a+1)); - n /= other; + n /= *other; } a } @@ -106,13 +106,14 @@ macro_rules! impl_Power { fn checked_next_power_of(&self, other: &Self) -> Option { self.checked_sub(1) .map_or(Some(1), |new| - traits::checked_pow(*other, - new.checked_log(other) - .map_or(0, |a| a as Self + 1) as usize)) + checked_pow(*other, new.checked_log(other) + .map_or(0, |a| a as Self + 1) as usize)) } }); ($($t:ty),*) => { $(impl_Power!($t);)* }; } -impl_Power!(usize, u8, u16, u32, u64, u128); +impl_Power!(usize, u8, u16, u32, u64); +#[cfg(has_i128)] +impl_Power!(u128);