Skip to content

Commit 2200568

Browse files
committed
Define trait Power, naïvely for now
1 parent fb097cb commit 2200568

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ mod roots;
3030
pub use roots::Roots;
3131
pub use roots::{sqrt, cbrt, nth_root};
3232

33+
mod power;
34+
pub use power::Power;
35+
3336
pub trait Integer: Sized + Num + PartialOrd + Ord + Eq {
3437
/// Floored integer division.
3538
///

src/power.rs

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
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

Comments
 (0)