diff --git a/src/lib.rs b/src/lib.rs index 23116b8..d6eff30 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,10 +78,10 @@ pub use num_complex::Complex; pub use num_integer::Integer; pub use num_iter::{range, range_inclusive, range_step, range_step_inclusive}; pub use num_traits::{Num, Zero, One, Signed, Unsigned, Bounded, + one, zero, abs, abs_sub, signum, Saturating, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, - PrimInt, Float, ToPrimitive, FromPrimitive, NumCast, cast}; - -use std::ops::{Mul}; + PrimInt, Float, ToPrimitive, FromPrimitive, NumCast, cast, + pow, checked_pow}; #[cfg(feature = "num-bigint")] pub mod bigint { @@ -109,114 +109,3 @@ pub mod traits { pub mod rational { pub use num_rational::*; } - -/// Returns the additive identity, `0`. -#[inline(always)] pub fn zero() -> T { Zero::zero() } - -/// Returns the multiplicative identity, `1`. -#[inline(always)] pub fn one() -> T { One::one() } - -/// Computes the absolute value. -/// -/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN` -/// -/// For signed integers, `::MIN` will be returned if the number is `::MIN`. -#[inline(always)] -pub fn abs(value: T) -> T { - value.abs() -} - -/// The positive difference of two numbers. -/// -/// Returns zero if `x` is less than or equal to `y`, otherwise the difference -/// between `x` and `y` is returned. -#[inline(always)] -pub fn abs_sub(x: T, y: T) -> T { - x.abs_sub(&y) -} - -/// Returns the sign of the number. -/// -/// For `f32` and `f64`: -/// -/// * `1.0` if the number is positive, `+0.0` or `INFINITY` -/// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` -/// * `NaN` if the number is `NaN` -/// -/// For signed integers: -/// -/// * `0` if the number is zero -/// * `1` if the number is positive -/// * `-1` if the number is negative -#[inline(always)] pub fn signum(value: T) -> T { value.signum() } - -/// Raises a value to the power of exp, using exponentiation by squaring. -/// -/// # Example -/// -/// ```rust -/// use num; -/// -/// assert_eq!(num::pow(2i8, 4), 16); -/// assert_eq!(num::pow(6u8, 3), 216); -/// ``` -#[inline] -pub fn pow>(mut base: T, mut exp: usize) -> T { - if exp == 0 { return T::one() } - - while exp & 1 == 0 { - base = base.clone() * base; - exp >>= 1; - } - if exp == 1 { return base } - - let mut acc = base.clone(); - while exp > 1 { - exp >>= 1; - base = base.clone() * base; - if exp & 1 == 1 { - acc = acc * base.clone(); - } - } - acc -} - -/// Raises a value to the power of exp, returning `None` if an overflow occurred. -/// -/// Otherwise same as the `pow` function. -/// -/// # Example -/// -/// ```rust -/// use num; -/// -/// assert_eq!(num::checked_pow(2i8, 4), Some(16)); -/// assert_eq!(num::checked_pow(7i8, 8), None); -/// assert_eq!(num::checked_pow(7u32, 8), Some(5_764_801)); -/// ``` -#[inline] -pub fn checked_pow(mut base: T, mut exp: usize) -> Option { - if exp == 0 { return Some(T::one()) } - - macro_rules! optry { - ( $ expr : expr ) => { - if let Some(val) = $expr { val } else { return None } - } - } - - while exp & 1 == 0 { - base = optry!(base.checked_mul(&base)); - exp >>= 1; - } - if exp == 1 { return Some(base) } - - let mut acc = base.clone(); - while exp > 1 { - exp >>= 1; - base = optry!(base.checked_mul(&base)); - if exp & 1 == 1 { - acc = optry!(acc.checked_mul(&base)); - } - } - Some(acc) -} diff --git a/traits/src/identities.rs b/traits/src/identities.rs index 0fee84a..15f0c90 100644 --- a/traits/src/identities.rs +++ b/traits/src/identities.rs @@ -93,3 +93,12 @@ one_impl!(i64, 1i64); one_impl!(f32, 1.0f32); one_impl!(f64, 1.0f64); + + +// Some helper functions provided for backwards compatibility. + +/// Returns the additive identity, `0`. +#[inline(always)] pub fn zero() -> T { Zero::zero() } + +/// Returns the multiplicative identity, `1`. +#[inline(always)] pub fn one() -> T { One::one() } diff --git a/traits/src/lib.rs b/traits/src/lib.rs index d89abe6..13f8cf7 100644 --- a/traits/src/lib.rs +++ b/traits/src/lib.rs @@ -14,12 +14,13 @@ use std::ops::{Add, Sub, Mul, Div, Rem}; pub use bounds::Bounded; pub use float::Float; -pub use identities::{Zero, One}; +pub use identities::{Zero, One, zero, one}; pub use ops::checked::*; pub use ops::saturating::Saturating; -pub use sign::{Signed, Unsigned}; +pub use sign::{Signed, Unsigned, abs, abs_sub, signum}; pub use cast::*; pub use int::PrimInt; +pub use pow::{pow, checked_pow}; pub mod identities; pub mod sign; @@ -28,6 +29,7 @@ pub mod bounds; pub mod float; pub mod cast; pub mod int; +pub mod pow; /// The base trait for numeric types pub trait Num: PartialEq + Zero + One diff --git a/traits/src/pow.rs b/traits/src/pow.rs new file mode 100644 index 0000000..b250ad4 --- /dev/null +++ b/traits/src/pow.rs @@ -0,0 +1,73 @@ +use std::ops::Mul; +use {One, CheckedMul}; + +/// Raises a value to the power of exp, using exponentiation by squaring. +/// +/// # Example +/// +/// ```rust +/// use num_traits::pow; +/// +/// assert_eq!(pow(2i8, 4), 16); +/// assert_eq!(pow(6u8, 3), 216); +/// ``` +#[inline] +pub fn pow>(mut base: T, mut exp: usize) -> T { + if exp == 0 { return T::one() } + + while exp & 1 == 0 { + base = base.clone() * base; + exp >>= 1; + } + if exp == 1 { return base } + + let mut acc = base.clone(); + while exp > 1 { + exp >>= 1; + base = base.clone() * base; + if exp & 1 == 1 { + acc = acc * base.clone(); + } + } + acc +} + +/// Raises a value to the power of exp, returning `None` if an overflow occurred. +/// +/// Otherwise same as the `pow` function. +/// +/// # Example +/// +/// ```rust +/// use num_traits::checked_pow; +/// +/// assert_eq!(checked_pow(2i8, 4), Some(16)); +/// assert_eq!(checked_pow(7i8, 8), None); +/// assert_eq!(checked_pow(7u32, 8), Some(5_764_801)); +/// ``` +#[inline] +pub fn checked_pow(mut base: T, mut exp: usize) -> Option { + if exp == 0 { return Some(T::one()) } + + macro_rules! optry { + ( $ expr : expr ) => { + if let Some(val) = $expr { val } else { return None } + } + } + + while exp & 1 == 0 { + base = optry!(base.checked_mul(&base)); + exp >>= 1; + } + if exp == 1 { return Some(base) } + + let mut acc = base.clone(); + while exp > 1 { + exp >>= 1; + base = optry!(base.checked_mul(&base)); + if exp & 1 == 1 { + acc = optry!(acc.checked_mul(&base)); + } + } + Some(acc) +} diff --git a/traits/src/sign.rs b/traits/src/sign.rs index ae1d38c..d3ec866 100644 --- a/traits/src/sign.rs +++ b/traits/src/sign.rs @@ -114,6 +114,40 @@ macro_rules! signed_float_impl { signed_float_impl!(f32, f32::NAN, f32::INFINITY, f32::NEG_INFINITY); signed_float_impl!(f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY); +/// Computes the absolute value. +/// +/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN` +/// +/// For signed integers, `::MIN` will be returned if the number is `::MIN`. +#[inline(always)] +pub fn abs(value: T) -> T { + value.abs() +} + +/// The positive difference of two numbers. +/// +/// Returns zero if `x` is less than or equal to `y`, otherwise the difference +/// between `x` and `y` is returned. +#[inline(always)] +pub fn abs_sub(x: T, y: T) -> T { + x.abs_sub(&y) +} + +/// Returns the sign of the number. +/// +/// For `f32` and `f64`: +/// +/// * `1.0` if the number is positive, `+0.0` or `INFINITY` +/// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY` +/// * `NaN` if the number is `NaN` +/// +/// For signed integers: +/// +/// * `0` if the number is zero +/// * `1` if the number is positive +/// * `-1` if the number is negative +#[inline(always)] pub fn signum(value: T) -> T { value.signum() } + /// A trait for values which cannot be negative pub trait Unsigned: Num {}