Implementing pow, overflowing_pow only for uint. Adding missing docs.

This commit is contained in:
Tomusdrw 2016-01-16 15:45:33 +01:00
parent 40947e214b
commit 666cbe7d47

View File

@ -58,6 +58,7 @@ macro_rules! panic_on_overflow {
} }
} }
} }
pub trait Uint: Sized + Default + FromStr + From<u64> + FromJson + fmt::Debug + fmt::Display + PartialOrd + Ord + PartialEq + Eq + Hash { pub trait Uint: Sized + Default + FromStr + From<u64> + FromJson + fmt::Debug + fmt::Display + PartialOrd + Ord + PartialEq + Eq + Hash {
/// Size of this type. /// Size of this type.
@ -83,11 +84,19 @@ pub trait Uint: Sized + Default + FromStr + From<u64> + FromJson + fmt::Debug +
/// Return the least number of bits needed to represent the number /// Return the least number of bits needed to represent the number
fn bits(&self) -> usize; fn bits(&self) -> usize;
/// Return if specific bit is set
fn bit(&self, index: usize) -> bool; fn bit(&self, index: usize) -> bool;
/// Return single byte
fn byte(&self, index: usize) -> u8; fn byte(&self, index: usize) -> u8;
/// Get this Uint as slice of bytes
fn to_bytes(&self, bytes: &mut[u8]); fn to_bytes(&self, bytes: &mut[u8]);
/// Create `Uint(10**n)`
fn exp10(n: usize) -> Self; fn exp10(n: usize) -> Self;
/// Return eponentation `self**other`. Panic on overflow.
fn pow(self, other: Self) -> Self;
/// Return wrapped eponentation `self**other` and flag if there was an overflow
fn overflowing_pow(self, other: Self) -> (Self, bool);
} }
macro_rules! construct_uint { macro_rules! construct_uint {
@ -112,14 +121,12 @@ macro_rules! construct_uint {
)) ))
} }
/// Conversion to u32
#[inline] #[inline]
fn low_u32(&self) -> u32 { fn low_u32(&self) -> u32 {
let &$name(ref arr) = self; let &$name(ref arr) = self;
arr[0] as u32 arr[0] as u32
} }
/// Conversion to u64
#[inline] #[inline]
fn low_u64(&self) -> u64 { fn low_u64(&self) -> u64 {
let &$name(ref arr) = self; let &$name(ref arr) = self;
@ -147,6 +154,7 @@ macro_rules! construct_uint {
} }
arr[0] arr[0]
} }
/// Return the least number of bits needed to represent the number /// Return the least number of bits needed to represent the number
#[inline] #[inline]
fn bits(&self) -> usize { fn bits(&self) -> usize {
@ -180,34 +188,33 @@ macro_rules! construct_uint {
} }
#[inline] #[inline]
fn exp10(n: usize) -> $name { fn exp10(n: usize) -> Self {
match n { match n {
0 => $name::from(1u64), 0 => Self::from(1u64),
_ => $name::exp10(n - 1) * $name::from(10u64) _ => Self::exp10(n - 1) * Self::from(10u64)
} }
} }
#[inline] #[inline]
fn zero() -> $name { fn zero() -> Self {
From::from(0u64) From::from(0u64)
} }
#[inline] #[inline]
fn one() -> $name { fn one() -> Self {
From::from(1u64) From::from(1u64)
} }
}
impl $name { /// Fast exponentation by squaring
/// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
pub fn pow(self, expon: $name) -> $name { fn pow(self, expon: Self) -> Self {
if expon == $name::zero() { if expon == Self::zero() {
return $name::one() return Self::one()
} }
let is_even = |x : &$name| x.low_u64() & 1 == 0; let is_even = |x : &Self| x.low_u64() & 1 == 0;
let u_one = $name::one(); let u_one = Self::one();
let u_two = $name::from(2); let u_two = Self::from(2);
let mut y = u_one; let mut y = u_one;
let mut n = expon; let mut n = expon;
let mut x = self; let mut x = self;
@ -224,14 +231,16 @@ macro_rules! construct_uint {
x * y x * y
} }
pub fn overflowing_pow(self, expon: $name) -> ($name, bool) { /// Fast exponentation by squaring
if expon == $name::zero() { /// https://en.wikipedia.org/wiki/Exponentiation_by_squaring
return ($name::one(), false) fn overflowing_pow(self, expon: Self) -> (Self, bool) {
if expon == Self::zero() {
return (Self::one(), false)
} }
let is_even = |x : &$name| x.low_u64() & 1 == 0; let is_even = |x : &Self| x.low_u64() & 1 == 0;
let u_one = $name::one(); let u_one = Self::one();
let u_two = $name::from(2); let u_two = Self::from(2);
let mut y = u_one; let mut y = u_one;
let mut n = expon; let mut n = expon;
let mut x = self; let mut x = self;
@ -250,9 +259,11 @@ macro_rules! construct_uint {
let res = overflowing!(x.overflowing_mul(y), overflow); let res = overflowing!(x.overflowing_mul(y), overflow);
(res, overflow) (res, overflow)
} }
}
impl $name {
/// Multiplication by u32 /// Multiplication by u32
fn mul_u32(self, other: u32) -> $name { fn mul_u32(self, other: u32) -> Self {
let $name(ref arr) = self; let $name(ref arr) = self;
let mut carry = [0u64; $n_words]; let mut carry = [0u64; $n_words];
let mut ret = [0u64; $n_words]; let mut ret = [0u64; $n_words];
@ -273,7 +284,7 @@ macro_rules! construct_uint {
} }
/// Overflowing multiplication by u32 /// Overflowing multiplication by u32
fn overflowing_mul_u32(self, other: u32) -> ($name, bool) { fn overflowing_mul_u32(self, other: u32) -> (Self, bool) {
let $name(ref arr) = self; let $name(ref arr) = self;
let mut carry = [0u64; $n_words]; let mut carry = [0u64; $n_words];
let mut ret = [0u64; $n_words]; let mut ret = [0u64; $n_words];