diff --git a/src/lib.rs b/src/lib.rs index 639ec9e..6436421 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,7 @@ pub use bounds::Bounded; #[cfg(any(feature = "std", feature = "libm"))] pub use float::Float; pub use float::FloatConst; +pub use float::FloatCore; // pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`. pub use cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive}; pub use identities::{one, zero, One, Zero}; @@ -40,7 +41,7 @@ pub use int::PrimInt; pub use ops::checked::{ CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub, }; -pub use ops::euclid::{CheckedDivEuclid, CheckedRemEuclid, DivEuclid, RemEuclid}; +pub use ops::euclid::{CheckedEuclid, Euclid}; pub use ops::inv::Inv; pub use ops::mul_add::{MulAdd, MulAddAssign}; pub use ops::saturating::{Saturating, SaturatingAdd, SaturatingMul, SaturatingSub}; @@ -49,6 +50,7 @@ pub use ops::wrapping::{ }; pub use pow::{checked_pow, pow, Pow}; pub use sign::{abs, abs_sub, signum, Signed, Unsigned}; + #[macro_use] mod macros; diff --git a/src/ops/euclid.rs b/src/ops/euclid.rs index fe35e1d..b4ab6fa 100644 --- a/src/ops/euclid.rs +++ b/src/ops/euclid.rs @@ -1,5 +1,6 @@ use core::ops::{Div, Rem}; -pub trait DivEuclid: Sized + Div { + +pub trait Euclid: Sized + Div + Rem { /// Calculates Euclidean division, the matching method for `rem_euclid`. /// /// This computes the integer `n` such that @@ -10,18 +11,17 @@ pub trait DivEuclid: Sized + Div { /// # Examples /// /// ``` - /// use num_traits::DivEuclid; + /// use num_traits::Euclid; /// /// let a: i32 = 7; /// let b: i32 = 4; - /// assert_eq!(DivEuclid::div_euclid(a,b), 1); // 7 > 4 * 1 - /// assert_eq!(DivEuclid::div_euclid(-a,b), -2); // -7 >= 4 * -2 - /// assert_eq!(DivEuclid::div_euclid(a,-b), -1); // 7 >= -4 * -1 - /// assert_eq!(DivEuclid::div_euclid(-a,-b), 2); // -7 >= -4 * 2 + /// assert_eq!(Euclid::div_euclid(a, b), 1); // 7 > 4 * 1 + /// assert_eq!(Euclid::div_euclid(-a, b), -2); // -7 >= 4 * -2 + /// assert_eq!(Euclid::div_euclid(a, -b), -1); // 7 >= -4 * -1 + /// assert_eq!(Euclid::div_euclid(-a, -b), 2); // -7 >= -4 * 2 /// ``` fn div_euclid(self, v: Self) -> Self; -} -pub trait RemEuclid: Sized + Rem { + /// Calculates the least nonnegative remainder of `self (mod v)`. /// /// In particular, the return value `r` satisfies `0.0 <= r < v.abs()` in @@ -36,20 +36,20 @@ pub trait RemEuclid: Sized + Rem { /// # Examples /// /// ``` - /// use num_traits::RemEuclid; + /// use num_traits::Euclid; /// /// let a: i32 = 7; /// let b: i32 = 4; - /// assert_eq!(RemEuclid::rem_euclid(a,b), 3); - /// assert_eq!(RemEuclid::rem_euclid(-a,b), 1); - /// assert_eq!(RemEuclid::rem_euclid(a,-b), 3); - /// assert_eq!(RemEuclid::rem_euclid(-a,-b), 1); + /// assert_eq!(Euclid::rem_euclid(a, b), 3); + /// assert_eq!(Euclid::rem_euclid(-a, b), 1); + /// assert_eq!(Euclid::rem_euclid(a, -b), 3); + /// assert_eq!(Euclid::rem_euclid(-a, -b), 1); /// ``` fn rem_euclid(self, v: Self) -> Self; } -macro_rules! div_euclid_int_impl { - ($trait_name:ident for $($t:ty)*) => {$( - impl $trait_name for $t { +macro_rules! euclid_int_impl { + ($($t:ty)*) => {$( + impl Euclid for $t { #[inline] fn div_euclid(self, v: $t) -> Self { let q = self / v; @@ -58,22 +58,7 @@ macro_rules! div_euclid_int_impl { } q } - } - )*} -} -macro_rules! div_euclid_uint_impl { - ($trait_name:ident for $($t:ty)*) => {$( - impl $trait_name for $t { - #[inline] - fn div_euclid(self, v: $t) -> Self { - self / v - } - } - )*} -} -macro_rules! rem_euclid_int_impl { - ($trait_name:ident for $($t:ty)*) => {$( - impl $trait_name for $t { + #[inline] fn rem_euclid(self, v: $t) -> Self { let r = self % v; @@ -90,9 +75,14 @@ macro_rules! rem_euclid_int_impl { } )*} } -macro_rules! rem_euclid_uint_impl { - ($trait_name:ident for $($t:ty)*) => {$( - impl $trait_name for $t { +macro_rules! euclid_uint_impl { + ($($t:ty)*) => {$( + impl Euclid for $t { + #[inline] + fn div_euclid(self, v: $t) -> Self { + self / v + } + #[inline] fn rem_euclid(self, v: $t) -> Self { self % v @@ -100,142 +90,116 @@ macro_rules! rem_euclid_uint_impl { } )*} } -div_euclid_int_impl!(DivEuclid for i8 i16 i32 i64); -div_euclid_uint_impl!(DivEuclid for isize usize u8 u16 u32 u64); -rem_euclid_int_impl!(RemEuclid for i8 i16 i32 i64); -rem_euclid_uint_impl!(RemEuclid for isize usize u8 u16 u32 u64); +euclid_int_impl!(isize i8 i16 i32 i64); +euclid_uint_impl!(usize u8 u16 u32 u64); #[cfg(has_i128)] -div_euclid_int_impl!(DivEuclid for i128); +euclid_int_impl!(i128); #[cfg(has_i128)] -div_euclid_uint_impl!(DivEuclid for u128); -#[cfg(has_i128)] -rem_euclid_int_impl!(RemEuclid for i128); -#[cfg(has_i128)] -rem_euclid_uint_impl!(RemEuclid for u128); +euclid_uint_impl!(u128); -#[cfg(any(feature = "std", feature = "libm"))] -impl DivEuclid for f32 { +impl Euclid for f32 { + #[inline] fn div_euclid(self, v: f32) -> f32 { - let q = ::trunc(self / v); + let q = ::trunc(self / v); if self % v < 0.0 { return if v > 0.0 { q - 1.0 } else { q + 1.0 }; } q } -} -#[cfg(any(feature = "std", feature = "libm"))] -impl RemEuclid for f32 { + #[inline] fn rem_euclid(self, v: f32) -> f32 { let r = self % v; if r < 0.0 { - r + ::abs(v) + r + ::abs(v) } else { r } } } -#[cfg(any(feature = "std", feature = "libm"))] -impl DivEuclid for f64 { +impl Euclid for f64 { + #[inline] fn div_euclid(self, v: f64) -> f64 { - let q = ::trunc(self / v); + let q = ::trunc(self / v); if self % v < 0.0 { return if v > 0.0 { q - 1.0 } else { q + 1.0 }; } q } -} -#[cfg(any(feature = "std", feature = "libm"))] -impl RemEuclid for f64 { + + #[inline] fn rem_euclid(self, v: f64) -> f64 { let r = self % v; if r < 0.0 { - r + ::abs(v) + r + ::abs(v) } else { r } } } -pub trait CheckedDivEuclid: DivEuclid { +pub trait CheckedEuclid: Euclid { /// Performs euclid division that returns `None` instead of panicking on division by zero /// and instead of wrapping around on underflow and overflow. fn checked_div_euclid(self, v: Self) -> Option; -} -pub trait CheckedRemEuclid: RemEuclid { + /// Finds the euclid remainder of dividing two numbers, checking for underflow, overflow and /// division by zero. If any of that happens, `None` is returned. fn checked_rem_euclid(self, v: Self) -> Option; } -macro_rules! checked_div_euclid_int_impl { - ($trait_name:ident for $($t:ty)*) => {$( - impl $trait_name for $t { +macro_rules! checked_euclid_int_impl { + ($($t:ty)*) => {$( + impl CheckedEuclid for $t { #[inline] fn checked_div_euclid(self, v: $t) -> Option<$t> { if v == 0 || (self == Self::min_value() && v == -1) { None } else { - Some(DivEuclid::div_euclid(self,v)) + Some(Euclid::div_euclid(self, v)) } } - } - )*} -} -macro_rules! checked_div_euclid_uint_impl { - ($trait_name:ident for $($t:ty)*) => {$( - impl $trait_name for $t { - #[inline] - fn checked_div_euclid(self, v: $t) -> Option<$t> { - if v == 0{ - None - } else { - Some(DivEuclid::div_euclid(self,v)) - } - } - } - )*} -} -macro_rules! checked_rem_euclid_int_impl { - ($trait_name:ident for $($t:ty)*) => {$( - impl $trait_name for $t { + #[inline] fn checked_rem_euclid(self, v: $t) -> Option<$t> { if v == 0 || (self == Self::min_value() && v == -1) { None } else { - Some(RemEuclid::rem_euclid(self,v)) + Some(Euclid::rem_euclid(self, v)) } } } )*} } -macro_rules! checked_rem_euclid_uint_impl { - ($trait_name:ident for $($t:ty)*) => {$( - impl $trait_name for $t { +macro_rules! checked_euclid_uint_impl { + ($($t:ty)*) => {$( + impl CheckedEuclid for $t { + #[inline] + fn checked_div_euclid(self, v: $t) -> Option<$t> { + if v == 0{ + None + } else { + Some(Euclid::div_euclid(self, v)) + } + } + #[inline] fn checked_rem_euclid(self, v: $t) -> Option<$t> { if v == 0{ None } else { - Some(RemEuclid::rem_euclid(self,v)) + Some(Euclid::rem_euclid(self, v)) } } } )*} } -checked_div_euclid_int_impl!(CheckedDivEuclid for i8 i16 i32 i64); -checked_div_euclid_uint_impl!(CheckedDivEuclid for isize usize u8 u16 u32 u64); -checked_rem_euclid_int_impl!(CheckedRemEuclid for i8 i16 i32 i64); -checked_rem_euclid_uint_impl!(CheckedRemEuclid for isize usize u8 u16 u32 u64); +checked_euclid_int_impl!(isize i8 i16 i32 i64); +checked_euclid_uint_impl!(usize u8 u16 u32 u64); #[cfg(has_i128)] -checked_div_euclid_int_impl!(CheckedDivEuclid for i128); +checked_euclid_int_impl!(i128); #[cfg(has_i128)] -checked_div_euclid_uint_impl!(CheckedDivEuclid for u128); -#[cfg(has_i128)] -checked_rem_euclid_int_impl!(CheckedRemEuclid for i128); -#[cfg(has_i128)] -checked_rem_euclid_uint_impl!(CheckedRemEuclid for u128); +checked_euclid_uint_impl!(u128); #[cfg(test)] mod tests { @@ -249,8 +213,8 @@ mod tests { { let x: $t = 10; let y: $t = 3; - assert_eq!(DivEuclid::div_euclid(x,y),3); - assert_eq!(RemEuclid::rem_euclid(x,y),1); + assert_eq!(Euclid::div_euclid(x, y),3); + assert_eq!(Euclid::rem_euclid(x, y),1); } )+ }; @@ -267,13 +231,13 @@ mod tests { { let x: $t = 10; let y: $t = -3; - assert_eq!(DivEuclid::div_euclid(x,y),-3); - assert_eq!(DivEuclid::div_euclid(-x,y),4); - assert_eq!(RemEuclid::rem_euclid(x,y),1); - assert_eq!(RemEuclid::rem_euclid(-x,y),2); + assert_eq!(Euclid::div_euclid(x, y),-3); + assert_eq!(Euclid::div_euclid(-x, y),4); + assert_eq!(Euclid::rem_euclid(x, y),1); + assert_eq!(Euclid::rem_euclid(-x, y),2); let x: $t = $t::min_value()+1; let y: $t = -1; - assert_eq!(DivEuclid::div_euclid(x,y),$t::max_value()); + assert_eq!(Euclid::div_euclid(x, y),$t::max_value()); } )+ }; @@ -283,7 +247,6 @@ mod tests { } #[test] - #[cfg(any(feature = "std", feature = "libm"))] fn euclid_float() { macro_rules! test_euclid { ($($t:ident)+) => { @@ -291,14 +254,14 @@ mod tests { { let x: $t = 12.1; let y: $t = 3.2; - assert!(DivEuclid::div_euclid(x,y)*y+RemEuclid::rem_euclid(x,y)-x - <=46.4 * <$t as ::Float>::epsilon()); - assert!(DivEuclid::div_euclid(x,-y)*-y+RemEuclid::rem_euclid(x,-y)-x - <= 46.4 * <$t as ::Float>::epsilon()); - assert!(DivEuclid::div_euclid(-x,y)*y+RemEuclid::rem_euclid(-x,y)-(-x) - <= 46.4 * <$t as ::Float>::epsilon()); - assert!(DivEuclid::div_euclid(-x,-y)*-y+RemEuclid::rem_euclid(-x,-y)-(-x) - <= 46.4 * <$t as ::Float>::epsilon()); + assert!(Euclid::div_euclid(x, y)*y+Euclid::rem_euclid(x, y)-x + <=46.4 * <$t as ::FloatCore>::epsilon()); + assert!(Euclid::div_euclid(x, -y)*-y+Euclid::rem_euclid(x, -y)-x + <= 46.4 * <$t as ::FloatCore>::epsilon()); + assert!(Euclid::div_euclid(-x, y)*y+Euclid::rem_euclid(-x, y)-(-x) + <= 46.4 * <$t as ::FloatCore>::epsilon()); + assert!(Euclid::div_euclid(-x, -y)*-y+Euclid::rem_euclid(-x, -y)-(-x) + <= 46.4 * <$t as ::FloatCore>::epsilon()); } )+ }; @@ -313,10 +276,10 @@ mod tests { ($($t:ident)+) => { $( { - assert_eq!(CheckedDivEuclid::checked_div_euclid($t::min_value(),-1),None); - assert_eq!(CheckedRemEuclid::checked_rem_euclid($t::min_value(),-1),None); - assert_eq!(CheckedDivEuclid::checked_div_euclid(1,0),None); - assert_eq!(CheckedRemEuclid::checked_rem_euclid(1,0),None); + assert_eq!(CheckedEuclid::checked_div_euclid($t::min_value(), -1),None); + assert_eq!(CheckedEuclid::checked_rem_euclid($t::min_value(), -1),None); + assert_eq!(CheckedEuclid::checked_div_euclid(1, 0),None); + assert_eq!(CheckedEuclid::checked_rem_euclid(1, 0),None); } )+ };