From 5b126673aabaf791607ef413dd224314790c2c27 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sat, 29 Apr 2017 07:21:14 +0200 Subject: [PATCH 01/17] impl Signed and Unsigned for Wrapping --- traits/src/sign.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/traits/src/sign.rs b/traits/src/sign.rs index c56ad25..bcb20e2 100644 --- a/traits/src/sign.rs +++ b/traits/src/sign.rs @@ -1,5 +1,6 @@ use std::ops::Neg; use std::{f32, f64}; +use std::num::Wrapping; use Num; @@ -73,6 +74,30 @@ macro_rules! signed_impl { signed_impl!(isize i8 i16 i32 i64); +impl Signed for Wrapping where Wrapping: Num + Neg +{ + #[inline] + fn abs(&self) -> Self { + Wrapping(self.0.abs()) + } + + #[inline] + fn abs_sub(&self, other: &Self) -> Self { + Wrapping(self.0.abs_sub(&other.0)) + } + + #[inline] + fn signum(&self) -> Self { + Wrapping(self.0.signum()) + } + + #[inline] + fn is_positive(&self) -> bool { self.0.is_positive() } + + #[inline] + fn is_negative(&self) -> bool { self.0.is_negative() } +} + macro_rules! signed_float_impl { ($t:ty, $nan:expr, $inf:expr, $neg_inf:expr) => { impl Signed for $t { @@ -159,3 +184,5 @@ macro_rules! empty_trait_impl { } empty_trait_impl!(Unsigned for usize u8 u16 u32 u64); + +impl Unsigned for Wrapping where Wrapping: Num {} From 579466d95cde00b5e7cb313141330775bba2e070 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sat, 29 Apr 2017 07:46:51 +0200 Subject: [PATCH 02/17] impl PrimInt for Wrapping --- traits/src/int.rs | 104 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/traits/src/int.rs b/traits/src/int.rs index 4f9221f..ec88b6d 100644 --- a/traits/src/int.rs +++ b/traits/src/int.rs @@ -1,4 +1,5 @@ use std::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; +use std::num::Wrapping; use {Num, NumCast}; use bounds::Bounded; @@ -374,3 +375,106 @@ prim_int_impl!(i16, i16, u16); prim_int_impl!(i32, i32, u32); prim_int_impl!(i64, i64, u64); prim_int_impl!(isize, isize, usize); + +// While this might violate the possible assumption that +// PrimInt represents genuine primitive integer types, +// Wrapping is _practically_ one too, so this +// shouldn't be a concern. +impl PrimInt for Wrapping + where Wrapping: + Num + NumCast + + Bounded + + Not> + + BitAnd> + + BitOr> + + BitXor> + + Shl> + + Shr> + + CheckedAdd> + + CheckedSub> + + CheckedMul> + + CheckedDiv> + + Saturating +{ + #[inline] + fn count_ones(self) -> u32 { + self.0.count_ones() + } + + #[inline] + fn count_zeros(self) -> u32 { + self.0.count_zeros() + } + + #[inline] + fn leading_zeros(self) -> u32 { + self.0.leading_zeros() + } + + #[inline] + fn trailing_zeros(self) -> u32 { + self.0.trailing_zeros() + } + + #[inline] + fn rotate_left(self, n: u32) -> Self { + Wrapping(self.0.rotate_left(n)) + } + + #[inline] + fn rotate_right(self, n: u32) -> Self { + Wrapping(self.0.rotate_right(n)) + } + + #[inline] + fn signed_shl(self, n: u32) -> Self { + Wrapping(self.0.signed_shl(n)) + } + + #[inline] + fn signed_shr(self, n: u32) -> Self { + Wrapping(self.0.signed_shr(n)) + } + + #[inline] + fn unsigned_shl(self, n: u32) -> Self { + Wrapping(self.0.unsigned_shl(n)) + } + + #[inline] + fn unsigned_shr(self, n: u32) -> Self { + Wrapping(self.0.unsigned_shr(n)) + } + + #[inline] + fn swap_bytes(self) -> Self { + Wrapping(self.0.swap_bytes()) + } + + #[inline] + fn from_be(x: Self) -> Self { + Wrapping(T::from_be(x.0)) + } + + #[inline] + fn from_le(x: Self) -> Self { + Wrapping(T::from_le(x.0)) + } + + #[inline] + fn to_be(self) -> Self { + Wrapping(self.0.to_be()) + } + + #[inline] + fn to_le(self) -> Self { + Wrapping(self.0.to_le()) + } + + // This is (or should be ?) fine because Wrapping only guarantees that + // _standard_ operations (Add, Mul, etc) have wrapping semantics. + #[inline] + fn pow(self, exp: u32) -> Self { + Wrapping(self.0.pow(exp)) + } +} From b2d957fe4bb3ac836f7737ed6a7fc0c243e8c7f8 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sat, 29 Apr 2017 07:47:39 +0200 Subject: [PATCH 03/17] Small fix for older Rust versions --- traits/src/sign.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/traits/src/sign.rs b/traits/src/sign.rs index bcb20e2..e91e9fa 100644 --- a/traits/src/sign.rs +++ b/traits/src/sign.rs @@ -74,7 +74,7 @@ macro_rules! signed_impl { signed_impl!(isize i8 i16 i32 i64); -impl Signed for Wrapping where Wrapping: Num + Neg +impl Signed for Wrapping where Wrapping: Num + Neg> { #[inline] fn abs(&self) -> Self { From 35a9bcba199f28a0d46cc6074387dd7590afa9a8 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sat, 29 Apr 2017 07:51:04 +0200 Subject: [PATCH 04/17] impl Bounded for Wrapping --- traits/src/bounds.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/traits/src/bounds.rs b/traits/src/bounds.rs index 966296c..0b8fbf4 100644 --- a/traits/src/bounds.rs +++ b/traits/src/bounds.rs @@ -1,6 +1,7 @@ use std::{usize, u8, u16, u32, u64}; use std::{isize, i8, i16, i32, i64}; use std::{f32, f64}; +use std::num::Wrapping; /// Numbers which have upper and lower bounds pub trait Bounded { @@ -35,6 +36,11 @@ bounded_impl!(i16, i16::MIN, i16::MAX); bounded_impl!(i32, i32::MIN, i32::MAX); bounded_impl!(i64, i64::MIN, i64::MAX); +impl Bounded for Wrapping { + #[inline] fn min_value() -> Self { Wrapping(T::min_value()) } + #[inline] fn max_value() -> Self { Wrapping(T::max_value()) } +} + bounded_impl!(f32, f32::MIN, f32::MAX); macro_rules! for_each_tuple_ { From f249edf546ad38514897bdee3db665c3c8b75139 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sat, 29 Apr 2017 08:04:59 +0200 Subject: [PATCH 05/17] impl ToPrimitive, FromPrimitive and NumCast for Wrapping --- traits/src/cast.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/traits/src/cast.rs b/traits/src/cast.rs index 8ff03fd..eda58f5 100644 --- a/traits/src/cast.rs +++ b/traits/src/cast.rs @@ -1,4 +1,5 @@ use std::mem::size_of; +use std::num::Wrapping; use identities::Zero; use bounds::Bounded; @@ -385,6 +386,17 @@ impl_from_primitive!(u64, to_u64); impl_from_primitive!(f32, to_f32); impl_from_primitive!(f64, to_f64); + +impl ToPrimitive for Wrapping { + fn to_i64(&self) -> Option { self.0.to_i64() } + fn to_u64(&self) -> Option { self.0.to_u64() } +} +impl FromPrimitive for Wrapping { + fn from_u64(n: u64) -> Option { T::from_u64(n).map(Wrapping) } + fn from_i64(n: i64) -> Option { T::from_i64(n).map(Wrapping) } +} + + /// Cast from one machine scalar to another. /// /// # Examples @@ -434,6 +446,11 @@ impl_num_cast!(isize, to_isize); impl_num_cast!(f32, to_f32); impl_num_cast!(f64, to_f64); +impl NumCast for Wrapping { + fn from(n: U) -> Option { + T::from(n).map(Wrapping) + } +} #[test] fn to_primitive_float() { From 9c3e9791d2b563a8f4ddc955b96e6ad35dfc96c7 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sat, 29 Apr 2017 08:22:44 +0200 Subject: [PATCH 06/17] impl Checked* and Saturating for Wrapping --- traits/src/ops/checked.rs | 28 ++++++++++++++++++++++++++++ traits/src/ops/saturating.rs | 7 +++++++ 2 files changed, 35 insertions(+) diff --git a/traits/src/ops/checked.rs b/traits/src/ops/checked.rs index b6bf0d6..4437acb 100644 --- a/traits/src/ops/checked.rs +++ b/traits/src/ops/checked.rs @@ -1,4 +1,5 @@ use std::ops::{Add, Sub, Mul, Div}; +use std::num::Wrapping; /// Performs addition that returns `None` instead of wrapping around on /// overflow. @@ -89,3 +90,30 @@ checked_impl!(CheckedDiv, checked_div, i16); checked_impl!(CheckedDiv, checked_div, i32); checked_impl!(CheckedDiv, checked_div, i64); checked_impl!(CheckedDiv, checked_div, isize); + +// Was skeptical at first, since checked ops somewhat defeat the point of +// Wrapping, but there are more pros than cons IMO : +// - These are methods, so users still have to be explicit about their intent; +// - Wrapping could be used for to enforce wrapping semantics _most of the time_, +// and only have a handful of places where they want to perform checked ops; +// - This allows Wrapping to implement PrimInt. +impl CheckedAdd for Wrapping where Wrapping: Add>{ + fn checked_add(&self, v: &Self) -> Option { + self.0.checked_add(&v.0).map(Wrapping) + } +} +impl CheckedSub for Wrapping where Wrapping: Sub> { + fn checked_sub(&self, v: &Self) -> Option { + self.0.checked_sub(&v.0).map(Wrapping) + } +} +impl CheckedMul for Wrapping where Wrapping: Mul>{ + fn checked_mul(&self, v: &Self) -> Option { + self.0.checked_mul(&v.0).map(Wrapping) + } +} +impl CheckedDiv for Wrapping where Wrapping: Div> { + fn checked_div(&self, v: &Self) -> Option { + self.0.checked_div(&v.0).map(Wrapping) + } +} diff --git a/traits/src/ops/saturating.rs b/traits/src/ops/saturating.rs index e9db749..ebbbe51 100644 --- a/traits/src/ops/saturating.rs +++ b/traits/src/ops/saturating.rs @@ -1,3 +1,5 @@ +use std::num::Wrapping; + /// Saturating math operations pub trait Saturating { /// Saturating addition operator. @@ -26,3 +28,8 @@ macro_rules! saturating_impl { } saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64); + +impl Saturating for Wrapping { + fn saturating_add(self, v: Self) -> Self { Wrapping(self.0.saturating_add(v.0)) } + fn saturating_sub(self, v: Self) -> Self { Wrapping(self.0.saturating_sub(v.0)) } +} From 47b8c7b5ae1fc10eab28430f9c2878524dadb302 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sat, 29 Apr 2017 08:29:02 +0200 Subject: [PATCH 07/17] impl Wrapping ops for Wrapping --- traits/src/ops/wrapping.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/traits/src/ops/wrapping.rs b/traits/src/ops/wrapping.rs index 40b266d..cd68ac4 100644 --- a/traits/src/ops/wrapping.rs +++ b/traits/src/ops/wrapping.rs @@ -1,4 +1,5 @@ use std::ops::{Add, Sub, Mul}; +use std::num::Wrapping; macro_rules! wrapping_impl { ($trait_name:ident, $method:ident, $t:ty) => { @@ -76,6 +77,23 @@ wrapping_impl!(WrappingMul, wrapping_mul, i32); wrapping_impl!(WrappingMul, wrapping_mul, i64); wrapping_impl!(WrappingMul, wrapping_mul, isize); +// Well this is a bit funny, but all the more appropriate. +impl WrappingAdd for Wrapping where Wrapping: Add> { + fn wrapping_add(&self, v: &Self) -> Self { + Wrapping(self.0.wrapping_add(&v.0)) + } +} +impl WrappingSub for Wrapping where Wrapping: Sub> { + fn wrapping_sub(&self, v: &Self) -> Self { + Wrapping(self.0.wrapping_sub(&v.0)) + } +} +impl WrappingMul for Wrapping where Wrapping: Mul> { + fn wrapping_mul(&self, v: &Self) -> Self { + Wrapping(self.0.wrapping_mul(&v.0)) + } +} + #[test] fn test_wrapping_traits() { From 760604361d0f4d1dd014da0047a27f5775d1b26e Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sat, 29 Apr 2017 08:35:37 +0200 Subject: [PATCH 08/17] Add missing #[inline] hints --- traits/src/cast.rs | 9 +++++---- traits/src/identities.rs | 3 +++ traits/src/lib.rs | 1 + traits/src/ops/checked.rs | 4 ++++ traits/src/ops/saturating.rs | 2 ++ traits/src/ops/wrapping.rs | 3 +++ 6 files changed, 18 insertions(+), 4 deletions(-) diff --git a/traits/src/cast.rs b/traits/src/cast.rs index eda58f5..7d1807d 100644 --- a/traits/src/cast.rs +++ b/traits/src/cast.rs @@ -388,12 +388,12 @@ impl_from_primitive!(f64, to_f64); impl ToPrimitive for Wrapping { - fn to_i64(&self) -> Option { self.0.to_i64() } - fn to_u64(&self) -> Option { self.0.to_u64() } + #[inline] fn to_i64(&self) -> Option { self.0.to_i64() } + #[inline] fn to_u64(&self) -> Option { self.0.to_u64() } } impl FromPrimitive for Wrapping { - fn from_u64(n: u64) -> Option { T::from_u64(n).map(Wrapping) } - fn from_i64(n: i64) -> Option { T::from_i64(n).map(Wrapping) } + #[inline] fn from_u64(n: u64) -> Option { T::from_u64(n).map(Wrapping) } + #[inline] fn from_i64(n: i64) -> Option { T::from_i64(n).map(Wrapping) } } @@ -447,6 +447,7 @@ impl_num_cast!(f32, to_f32); impl_num_cast!(f64, to_f64); impl NumCast for Wrapping { + #[inline] fn from(n: U) -> Option { T::from(n).map(Wrapping) } diff --git a/traits/src/identities.rs b/traits/src/identities.rs index 889b11d..dea7b9c 100644 --- a/traits/src/identities.rs +++ b/traits/src/identities.rs @@ -52,9 +52,11 @@ zero_impl!(f32, 0.0f32); zero_impl!(f64, 0.0f64); impl Zero for Wrapping where Wrapping: Add> { + #[inline] fn is_zero(&self) -> bool { self.0.is_zero() } + #[inline] fn zero() -> Self { Wrapping(T::zero()) } @@ -106,6 +108,7 @@ one_impl!(f32, 1.0f32); one_impl!(f64, 1.0f64); impl One for Wrapping where Wrapping: Mul> { + #[inline] fn one() -> Self { Wrapping(T::one()) } diff --git a/traits/src/lib.rs b/traits/src/lib.rs index 0cf7e34..ce5599b 100644 --- a/traits/src/lib.rs +++ b/traits/src/lib.rs @@ -81,6 +81,7 @@ impl Num for Wrapping + Mul> + Div> + Rem> { type FromStrRadixErr = T::FromStrRadixErr; + #[inline] fn from_str_radix(str: &str, radix: u32) -> Result { T::from_str_radix(str, radix).map(Wrapping) } diff --git a/traits/src/ops/checked.rs b/traits/src/ops/checked.rs index 4437acb..a2df6d1 100644 --- a/traits/src/ops/checked.rs +++ b/traits/src/ops/checked.rs @@ -98,21 +98,25 @@ checked_impl!(CheckedDiv, checked_div, isize); // and only have a handful of places where they want to perform checked ops; // - This allows Wrapping to implement PrimInt. impl CheckedAdd for Wrapping where Wrapping: Add>{ + #[inline] fn checked_add(&self, v: &Self) -> Option { self.0.checked_add(&v.0).map(Wrapping) } } impl CheckedSub for Wrapping where Wrapping: Sub> { + #[inline] fn checked_sub(&self, v: &Self) -> Option { self.0.checked_sub(&v.0).map(Wrapping) } } impl CheckedMul for Wrapping where Wrapping: Mul>{ + #[inline] fn checked_mul(&self, v: &Self) -> Option { self.0.checked_mul(&v.0).map(Wrapping) } } impl CheckedDiv for Wrapping where Wrapping: Div> { + #[inline] fn checked_div(&self, v: &Self) -> Option { self.0.checked_div(&v.0).map(Wrapping) } diff --git a/traits/src/ops/saturating.rs b/traits/src/ops/saturating.rs index ebbbe51..2a4f711 100644 --- a/traits/src/ops/saturating.rs +++ b/traits/src/ops/saturating.rs @@ -30,6 +30,8 @@ macro_rules! saturating_impl { saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64); impl Saturating for Wrapping { + #[inline] fn saturating_add(self, v: Self) -> Self { Wrapping(self.0.saturating_add(v.0)) } + #[inline] fn saturating_sub(self, v: Self) -> Self { Wrapping(self.0.saturating_sub(v.0)) } } diff --git a/traits/src/ops/wrapping.rs b/traits/src/ops/wrapping.rs index cd68ac4..29981a4 100644 --- a/traits/src/ops/wrapping.rs +++ b/traits/src/ops/wrapping.rs @@ -79,16 +79,19 @@ wrapping_impl!(WrappingMul, wrapping_mul, isize); // Well this is a bit funny, but all the more appropriate. impl WrappingAdd for Wrapping where Wrapping: Add> { + #[inline] fn wrapping_add(&self, v: &Self) -> Self { Wrapping(self.0.wrapping_add(&v.0)) } } impl WrappingSub for Wrapping where Wrapping: Sub> { + #[inline] fn wrapping_sub(&self, v: &Self) -> Self { Wrapping(self.0.wrapping_sub(&v.0)) } } impl WrappingMul for Wrapping where Wrapping: Mul> { + #[inline] fn wrapping_mul(&self, v: &Self) -> Self { Wrapping(self.0.wrapping_mul(&v.0)) } From 81aa6dbe486d06b58e136bf3e15904e360072c2b Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sun, 30 Apr 2017 08:29:21 +0200 Subject: [PATCH 09/17] Revert impl for Checked and Saturating --- traits/src/ops/checked.rs | 31 ------------------------------- traits/src/ops/saturating.rs | 9 --------- 2 files changed, 40 deletions(-) diff --git a/traits/src/ops/checked.rs b/traits/src/ops/checked.rs index a2df6d1..45e6716 100644 --- a/traits/src/ops/checked.rs +++ b/traits/src/ops/checked.rs @@ -1,5 +1,4 @@ use std::ops::{Add, Sub, Mul, Div}; -use std::num::Wrapping; /// Performs addition that returns `None` instead of wrapping around on /// overflow. @@ -91,33 +90,3 @@ checked_impl!(CheckedDiv, checked_div, i32); checked_impl!(CheckedDiv, checked_div, i64); checked_impl!(CheckedDiv, checked_div, isize); -// Was skeptical at first, since checked ops somewhat defeat the point of -// Wrapping, but there are more pros than cons IMO : -// - These are methods, so users still have to be explicit about their intent; -// - Wrapping could be used for to enforce wrapping semantics _most of the time_, -// and only have a handful of places where they want to perform checked ops; -// - This allows Wrapping to implement PrimInt. -impl CheckedAdd for Wrapping where Wrapping: Add>{ - #[inline] - fn checked_add(&self, v: &Self) -> Option { - self.0.checked_add(&v.0).map(Wrapping) - } -} -impl CheckedSub for Wrapping where Wrapping: Sub> { - #[inline] - fn checked_sub(&self, v: &Self) -> Option { - self.0.checked_sub(&v.0).map(Wrapping) - } -} -impl CheckedMul for Wrapping where Wrapping: Mul>{ - #[inline] - fn checked_mul(&self, v: &Self) -> Option { - self.0.checked_mul(&v.0).map(Wrapping) - } -} -impl CheckedDiv for Wrapping where Wrapping: Div> { - #[inline] - fn checked_div(&self, v: &Self) -> Option { - self.0.checked_div(&v.0).map(Wrapping) - } -} diff --git a/traits/src/ops/saturating.rs b/traits/src/ops/saturating.rs index 2a4f711..e9db749 100644 --- a/traits/src/ops/saturating.rs +++ b/traits/src/ops/saturating.rs @@ -1,5 +1,3 @@ -use std::num::Wrapping; - /// Saturating math operations pub trait Saturating { /// Saturating addition operator. @@ -28,10 +26,3 @@ macro_rules! saturating_impl { } saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64); - -impl Saturating for Wrapping { - #[inline] - fn saturating_add(self, v: Self) -> Self { Wrapping(self.0.saturating_add(v.0)) } - #[inline] - fn saturating_sub(self, v: Self) -> Self { Wrapping(self.0.saturating_sub(v.0)) } -} From f4e0b47cebb0f6a20a63c3721e51953283cdec59 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sun, 30 Apr 2017 08:32:25 +0200 Subject: [PATCH 10/17] Revert #[inline] hints --- traits/src/cast.rs | 9 ++++----- traits/src/identities.rs | 3 --- traits/src/lib.rs | 1 - traits/src/ops/wrapping.rs | 3 --- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/traits/src/cast.rs b/traits/src/cast.rs index 7d1807d..eda58f5 100644 --- a/traits/src/cast.rs +++ b/traits/src/cast.rs @@ -388,12 +388,12 @@ impl_from_primitive!(f64, to_f64); impl ToPrimitive for Wrapping { - #[inline] fn to_i64(&self) -> Option { self.0.to_i64() } - #[inline] fn to_u64(&self) -> Option { self.0.to_u64() } + fn to_i64(&self) -> Option { self.0.to_i64() } + fn to_u64(&self) -> Option { self.0.to_u64() } } impl FromPrimitive for Wrapping { - #[inline] fn from_u64(n: u64) -> Option { T::from_u64(n).map(Wrapping) } - #[inline] fn from_i64(n: i64) -> Option { T::from_i64(n).map(Wrapping) } + fn from_u64(n: u64) -> Option { T::from_u64(n).map(Wrapping) } + fn from_i64(n: i64) -> Option { T::from_i64(n).map(Wrapping) } } @@ -447,7 +447,6 @@ impl_num_cast!(f32, to_f32); impl_num_cast!(f64, to_f64); impl NumCast for Wrapping { - #[inline] fn from(n: U) -> Option { T::from(n).map(Wrapping) } diff --git a/traits/src/identities.rs b/traits/src/identities.rs index dea7b9c..889b11d 100644 --- a/traits/src/identities.rs +++ b/traits/src/identities.rs @@ -52,11 +52,9 @@ zero_impl!(f32, 0.0f32); zero_impl!(f64, 0.0f64); impl Zero for Wrapping where Wrapping: Add> { - #[inline] fn is_zero(&self) -> bool { self.0.is_zero() } - #[inline] fn zero() -> Self { Wrapping(T::zero()) } @@ -108,7 +106,6 @@ one_impl!(f32, 1.0f32); one_impl!(f64, 1.0f64); impl One for Wrapping where Wrapping: Mul> { - #[inline] fn one() -> Self { Wrapping(T::one()) } diff --git a/traits/src/lib.rs b/traits/src/lib.rs index ce5599b..0cf7e34 100644 --- a/traits/src/lib.rs +++ b/traits/src/lib.rs @@ -81,7 +81,6 @@ impl Num for Wrapping + Mul> + Div> + Rem> { type FromStrRadixErr = T::FromStrRadixErr; - #[inline] fn from_str_radix(str: &str, radix: u32) -> Result { T::from_str_radix(str, radix).map(Wrapping) } diff --git a/traits/src/ops/wrapping.rs b/traits/src/ops/wrapping.rs index 29981a4..cd68ac4 100644 --- a/traits/src/ops/wrapping.rs +++ b/traits/src/ops/wrapping.rs @@ -79,19 +79,16 @@ wrapping_impl!(WrappingMul, wrapping_mul, isize); // Well this is a bit funny, but all the more appropriate. impl WrappingAdd for Wrapping where Wrapping: Add> { - #[inline] fn wrapping_add(&self, v: &Self) -> Self { Wrapping(self.0.wrapping_add(&v.0)) } } impl WrappingSub for Wrapping where Wrapping: Sub> { - #[inline] fn wrapping_sub(&self, v: &Self) -> Self { Wrapping(self.0.wrapping_sub(&v.0)) } } impl WrappingMul for Wrapping where Wrapping: Mul> { - #[inline] fn wrapping_mul(&self, v: &Self) -> Self { Wrapping(self.0.wrapping_mul(&v.0)) } From b90cfaaa7f2ec590d30c6cbef315a2cb783f2c83 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sun, 30 Apr 2017 08:32:59 +0200 Subject: [PATCH 11/17] Revert "impl PrimInt for Wrapping" This reverts commit 579466d95cde00b5e7cb313141330775bba2e070. --- traits/src/int.rs | 104 ---------------------------------------------- 1 file changed, 104 deletions(-) diff --git a/traits/src/int.rs b/traits/src/int.rs index ec88b6d..4f9221f 100644 --- a/traits/src/int.rs +++ b/traits/src/int.rs @@ -1,5 +1,4 @@ use std::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; -use std::num::Wrapping; use {Num, NumCast}; use bounds::Bounded; @@ -375,106 +374,3 @@ prim_int_impl!(i16, i16, u16); prim_int_impl!(i32, i32, u32); prim_int_impl!(i64, i64, u64); prim_int_impl!(isize, isize, usize); - -// While this might violate the possible assumption that -// PrimInt represents genuine primitive integer types, -// Wrapping is _practically_ one too, so this -// shouldn't be a concern. -impl PrimInt for Wrapping - where Wrapping: - Num + NumCast - + Bounded - + Not> - + BitAnd> - + BitOr> - + BitXor> - + Shl> - + Shr> - + CheckedAdd> - + CheckedSub> - + CheckedMul> - + CheckedDiv> - + Saturating -{ - #[inline] - fn count_ones(self) -> u32 { - self.0.count_ones() - } - - #[inline] - fn count_zeros(self) -> u32 { - self.0.count_zeros() - } - - #[inline] - fn leading_zeros(self) -> u32 { - self.0.leading_zeros() - } - - #[inline] - fn trailing_zeros(self) -> u32 { - self.0.trailing_zeros() - } - - #[inline] - fn rotate_left(self, n: u32) -> Self { - Wrapping(self.0.rotate_left(n)) - } - - #[inline] - fn rotate_right(self, n: u32) -> Self { - Wrapping(self.0.rotate_right(n)) - } - - #[inline] - fn signed_shl(self, n: u32) -> Self { - Wrapping(self.0.signed_shl(n)) - } - - #[inline] - fn signed_shr(self, n: u32) -> Self { - Wrapping(self.0.signed_shr(n)) - } - - #[inline] - fn unsigned_shl(self, n: u32) -> Self { - Wrapping(self.0.unsigned_shl(n)) - } - - #[inline] - fn unsigned_shr(self, n: u32) -> Self { - Wrapping(self.0.unsigned_shr(n)) - } - - #[inline] - fn swap_bytes(self) -> Self { - Wrapping(self.0.swap_bytes()) - } - - #[inline] - fn from_be(x: Self) -> Self { - Wrapping(T::from_be(x.0)) - } - - #[inline] - fn from_le(x: Self) -> Self { - Wrapping(T::from_le(x.0)) - } - - #[inline] - fn to_be(self) -> Self { - Wrapping(self.0.to_be()) - } - - #[inline] - fn to_le(self) -> Self { - Wrapping(self.0.to_le()) - } - - // This is (or should be ?) fine because Wrapping only guarantees that - // _standard_ operations (Add, Mul, etc) have wrapping semantics. - #[inline] - fn pow(self, exp: u32) -> Self { - Wrapping(self.0.pow(exp)) - } -} From 807584688c99546bf084d5c64516857c8a185a02 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sun, 30 Apr 2017 10:17:06 +0200 Subject: [PATCH 12/17] Added some tests for Wrapping's impls --- traits/src/cast.rs | 26 ++++++++++++++++++++++++++ traits/src/identities.rs | 18 ++++++++++++++++++ traits/src/lib.rs | 16 ++++++++++++++++ traits/src/ops/wrapping.rs | 3 +++ traits/src/sign.rs | 25 +++++++++++++++++++++++++ 5 files changed, 88 insertions(+) diff --git a/traits/src/cast.rs b/traits/src/cast.rs index eda58f5..429995e 100644 --- a/traits/src/cast.rs +++ b/traits/src/cast.rs @@ -465,3 +465,29 @@ fn to_primitive_float() { assert_eq!((f64::NEG_INFINITY).to_f32(), Some(f32::NEG_INFINITY)); assert!((f64::NAN).to_f32().map_or(false, |f| f.is_nan())); } + +macro_rules! test_wrapping_to_primitive { + ($($t:ty)+) => { + $( + let i: $t = 0; + let w = Wrapping(i); + assert_eq!(i.to_u8(), w.to_u8()); + assert_eq!(i.to_u16(), w.to_u16()); + assert_eq!(i.to_u32(), w.to_u32()); + assert_eq!(i.to_u64(), w.to_u64()); + assert_eq!(i.to_usize(), w.to_usize()); + assert_eq!(i.to_i8(), w.to_i8()); + assert_eq!(i.to_i16(), w.to_i16()); + assert_eq!(i.to_i32(), w.to_i32()); + assert_eq!(i.to_i64(), w.to_i64()); + assert_eq!(i.to_isize(), w.to_isize()); + assert_eq!(i.to_f32(), w.to_f32()); + assert_eq!(i.to_f64(), w.to_f64()); + )+ + }; +} + +#[test] +fn wrapping_to_primitive() { + test_wrapping_to_primitive!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); +} diff --git a/traits/src/identities.rs b/traits/src/identities.rs index 889b11d..e269882 100644 --- a/traits/src/identities.rs +++ b/traits/src/identities.rs @@ -118,3 +118,21 @@ impl One for Wrapping where Wrapping: Mul> { /// Returns the multiplicative identity, `1`. #[inline(always)] pub fn one() -> T { One::one() } + + +macro_rules! test_wrapping_identities { + ($($t:ty)+) => { + $( + assert_eq!(zero::<$t>(), zero::>().0); + assert_eq!(one::<$t>(), one::>().0); + assert_eq!((0 as $t).is_zero(), Wrapping(0 as $t).is_zero()); + assert_eq!((1 as $t).is_zero(), Wrapping(1 as $t).is_zero()); + )+ + }; +} + +#[test] +fn wrapping_identities() { + test_wrapping_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64); +} + diff --git a/traits/src/lib.rs b/traits/src/lib.rs index 0cf7e34..1144ffd 100644 --- a/traits/src/lib.rs +++ b/traits/src/lib.rs @@ -294,3 +294,19 @@ fn from_str_radix_unwrap() { let f: f32 = Num::from_str_radix("0.0", 10).unwrap(); assert_eq!(f, 0.0); } + +macro_rules! test_wrapping_from_str_radix { + ($($t:ty)+) => { + $( + for &(s, r) in &[("42", 10), ("42", 2), ("-13.0", 10), ("foo", 10)] { + let w = Wrapping::<$t>::from_str_radix(s, r).map(|w| w.0); + assert_eq!(w, <$t as Num>::from_str_radix(s, r)); + } + )+ + }; +} + +#[test] +fn wrapping_from_str_radix() { + test_wrapping_from_str_radix!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); +} diff --git a/traits/src/ops/wrapping.rs b/traits/src/ops/wrapping.rs index cd68ac4..fbf15fd 100644 --- a/traits/src/ops/wrapping.rs +++ b/traits/src/ops/wrapping.rs @@ -103,4 +103,7 @@ fn test_wrapping_traits() { assert_eq!(wrapping_add(255, 1), 0u8); assert_eq!(wrapping_sub(0, 1), 255u8); assert_eq!(wrapping_mul(255, 2), 254u8); + assert_eq!(wrapping_add(255, 1), (Wrapping(255u8) + Wrapping(1u8)).0); + assert_eq!(wrapping_sub(0, 1), (Wrapping(0u8) - Wrapping(1u8)).0); + assert_eq!(wrapping_mul(255, 2), (Wrapping(255u8) * Wrapping(2u8)).0); } diff --git a/traits/src/sign.rs b/traits/src/sign.rs index e91e9fa..56abf45 100644 --- a/traits/src/sign.rs +++ b/traits/src/sign.rs @@ -186,3 +186,28 @@ macro_rules! empty_trait_impl { empty_trait_impl!(Unsigned for usize u8 u16 u32 u64); impl Unsigned for Wrapping where Wrapping: Num {} + + +macro_rules! test_signed_wrapping { + ($($t:ty)+) => { + $( + let range = -1 as $t .. 2 as $t; + for i in range.clone() { + let w = Wrapping(i); + assert_eq!(signum(i), signum(w).0); + assert_eq!(abs(i), abs(w).0); + for j in range.clone() { + assert_eq!(abs_sub(i, j), abs_sub(w, Wrapping(j)).0); + } + assert_eq!(i.is_positive(), w.is_positive()); + assert_eq!(i.is_negative(), w.is_negative()); + } + )+ + }; +} + +#[test] +fn signed_wrapping() { + test_signed_wrapping!(isize i8 i16 i32 i64); +} + From 3f6ea76e60ea11bb8b2bbebb59cf93b6cdc76911 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sun, 30 Apr 2017 10:17:44 +0200 Subject: [PATCH 13/17] Removed some #[inline] hints again --- traits/src/bounds.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/traits/src/bounds.rs b/traits/src/bounds.rs index 0b8fbf4..56e0cea 100644 --- a/traits/src/bounds.rs +++ b/traits/src/bounds.rs @@ -37,8 +37,8 @@ bounded_impl!(i32, i32::MIN, i32::MAX); bounded_impl!(i64, i64::MIN, i64::MAX); impl Bounded for Wrapping { - #[inline] fn min_value() -> Self { Wrapping(T::min_value()) } - #[inline] fn max_value() -> Self { Wrapping(T::max_value()) } + fn min_value() -> Self { Wrapping(T::min_value()) } + fn max_value() -> Self { Wrapping(T::max_value()) } } bounded_impl!(f32, f32::MIN, f32::MAX); From 3896c64dc7a228501183ac6ae23b5899fc565ea6 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sun, 30 Apr 2017 10:33:35 +0200 Subject: [PATCH 14/17] Attempt to work around E0425 in test macros on Rust 1.8 --- traits/src/cast.rs | 4 ++-- traits/src/sign.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/traits/src/cast.rs b/traits/src/cast.rs index 429995e..7058216 100644 --- a/traits/src/cast.rs +++ b/traits/src/cast.rs @@ -468,7 +468,7 @@ fn to_primitive_float() { macro_rules! test_wrapping_to_primitive { ($($t:ty)+) => { - $( + $({ let i: $t = 0; let w = Wrapping(i); assert_eq!(i.to_u8(), w.to_u8()); @@ -483,7 +483,7 @@ macro_rules! test_wrapping_to_primitive { assert_eq!(i.to_isize(), w.to_isize()); assert_eq!(i.to_f32(), w.to_f32()); assert_eq!(i.to_f64(), w.to_f64()); - )+ + })+ }; } diff --git a/traits/src/sign.rs b/traits/src/sign.rs index 56abf45..2912782 100644 --- a/traits/src/sign.rs +++ b/traits/src/sign.rs @@ -190,7 +190,7 @@ impl Unsigned for Wrapping where Wrapping: Num {} macro_rules! test_signed_wrapping { ($($t:ty)+) => { - $( + $({ let range = -1 as $t .. 2 as $t; for i in range.clone() { let w = Wrapping(i); @@ -202,7 +202,7 @@ macro_rules! test_signed_wrapping { assert_eq!(i.is_positive(), w.is_positive()); assert_eq!(i.is_negative(), w.is_negative()); } - )+ + })+ }; } From 3b7a775f38063f6324b116b10414fe581c74f3f4 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Sun, 30 Apr 2017 10:45:51 +0200 Subject: [PATCH 15/17] Remove Signed Wrapping test because Wrapping doesn't impl Neg in Rust 1.8 --- traits/src/sign.rs | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/traits/src/sign.rs b/traits/src/sign.rs index 2912782..ba06edc 100644 --- a/traits/src/sign.rs +++ b/traits/src/sign.rs @@ -187,27 +187,3 @@ empty_trait_impl!(Unsigned for usize u8 u16 u32 u64); impl Unsigned for Wrapping where Wrapping: Num {} - -macro_rules! test_signed_wrapping { - ($($t:ty)+) => { - $({ - let range = -1 as $t .. 2 as $t; - for i in range.clone() { - let w = Wrapping(i); - assert_eq!(signum(i), signum(w).0); - assert_eq!(abs(i), abs(w).0); - for j in range.clone() { - assert_eq!(abs_sub(i, j), abs_sub(w, Wrapping(j)).0); - } - assert_eq!(i.is_positive(), w.is_positive()); - assert_eq!(i.is_negative(), w.is_negative()); - } - })+ - }; -} - -#[test] -fn signed_wrapping() { - test_signed_wrapping!(isize i8 i16 i32 i64); -} - From fd50c9196b3b265ac4aae22dc866bdf775ca3493 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Mon, 1 May 2017 13:42:30 +0200 Subject: [PATCH 16/17] Added trait bounds tests for Wrapping --- traits/src/bounds.rs | 22 ++++++++++++++++++++++ traits/src/cast.rs | 18 ++++++++++++++++++ traits/src/identities.rs | 10 ++++++++++ traits/src/lib.rs | 7 ++++++- traits/src/ops/wrapping.rs | 18 ++++++++++++++++++ traits/src/sign.rs | 10 ++++++++++ 6 files changed, 84 insertions(+), 1 deletion(-) diff --git a/traits/src/bounds.rs b/traits/src/bounds.rs index 56e0cea..ea5c811 100644 --- a/traits/src/bounds.rs +++ b/traits/src/bounds.rs @@ -75,3 +75,25 @@ macro_rules! bounded_tuple { for_each_tuple!(bounded_tuple); bounded_impl!(f64, f64::MIN, f64::MAX); + + +macro_rules! test_wrapping_bounded { + ($($t:ty)+) => { + $( + assert_eq!(Wrapping::<$t>::min_value().0, <$t>::min_value()); + assert_eq!(Wrapping::<$t>::max_value().0, <$t>::max_value()); + )+ + }; +} + +#[test] +fn wrapping_bounded() { + test_wrapping_bounded!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); +} + +#[test] +fn wrapping_is_bounded() { + fn require_bounded(_: &T) {} + require_bounded(&Wrapping(42_u32)); + require_bounded(&Wrapping(-42)); +} diff --git a/traits/src/cast.rs b/traits/src/cast.rs index 7058216..8949834 100644 --- a/traits/src/cast.rs +++ b/traits/src/cast.rs @@ -491,3 +491,21 @@ macro_rules! test_wrapping_to_primitive { fn wrapping_to_primitive() { test_wrapping_to_primitive!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); } + +#[test] +fn wrapping_is_toprimitive() { + fn require_toprimitive(_: &T) {} + require_toprimitive(&Wrapping(42)); +} + +#[test] +fn wrapping_is_fromprimitive() { + fn require_fromprimitive(_: &T) {} + require_fromprimitive(&Wrapping(42)); +} + +#[test] +fn wrapping_is_numcast() { + fn require_numcast(_: &T) {} + require_numcast(&Wrapping(42)); +} diff --git a/traits/src/identities.rs b/traits/src/identities.rs index e269882..2f520e0 100644 --- a/traits/src/identities.rs +++ b/traits/src/identities.rs @@ -136,3 +136,13 @@ fn wrapping_identities() { test_wrapping_identities!(isize i8 i16 i32 i64 usize u8 u16 u32 u64); } +#[test] +fn wrapping_is_zero() { + fn require_zero(_: &T) {} + require_zero(&Wrapping(42)); +} +#[test] +fn wrapping_is_one() { + fn require_one(_: &T) {} + require_one(&Wrapping(42)); +} diff --git a/traits/src/lib.rs b/traits/src/lib.rs index 1144ffd..083fe41 100644 --- a/traits/src/lib.rs +++ b/traits/src/lib.rs @@ -305,7 +305,12 @@ macro_rules! test_wrapping_from_str_radix { )+ }; } - +#[test] +fn wrapping_is_num() { + fn require_num(_: &T) {} + require_num(&Wrapping(42_u32)); + require_num(&Wrapping(-42)); +} #[test] fn wrapping_from_str_radix() { test_wrapping_from_str_radix!(usize u8 u16 u32 u64 isize i8 i16 i32 i64); diff --git a/traits/src/ops/wrapping.rs b/traits/src/ops/wrapping.rs index fbf15fd..f989058 100644 --- a/traits/src/ops/wrapping.rs +++ b/traits/src/ops/wrapping.rs @@ -107,3 +107,21 @@ fn test_wrapping_traits() { assert_eq!(wrapping_sub(0, 1), (Wrapping(0u8) - Wrapping(1u8)).0); assert_eq!(wrapping_mul(255, 2), (Wrapping(255u8) * Wrapping(2u8)).0); } + +#[test] +fn wrapping_is_wrappingadd() { + fn require_wrappingadd(_: &T) {} + require_wrappingadd(&Wrapping(42)); +} + +#[test] +fn wrapping_is_wrappingsub() { + fn require_wrappingsub(_: &T) {} + require_wrappingsub(&Wrapping(42)); +} + +#[test] +fn wrapping_is_wrappingmul() { + fn require_wrappingmul(_: &T) {} + require_wrappingmul(&Wrapping(42)); +} diff --git a/traits/src/sign.rs b/traits/src/sign.rs index ba06edc..6b2f5ee 100644 --- a/traits/src/sign.rs +++ b/traits/src/sign.rs @@ -187,3 +187,13 @@ empty_trait_impl!(Unsigned for usize u8 u16 u32 u64); impl Unsigned for Wrapping where Wrapping: Num {} +#[test] +fn unsigned_wrapping_is_unsigned() { + fn require_unsigned(_: &T) {} + require_unsigned(&Wrapping(42_u32)); +} +#[test] +fn signed_wrapping_is_signed() { + fn require_signed(_: &T) {} + require_signed(&Wrapping(-42)); +} From 9d8c808db6c43f0ef1433796e62b6395eb0fae85 Mon Sep 17 00:00:00 2001 From: Yoan Lecoq Date: Mon, 1 May 2017 14:11:10 +0200 Subject: [PATCH 17/17] comment out wrapping_is_signed test to make Rust 1.8 happy --- traits/src/sign.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/traits/src/sign.rs b/traits/src/sign.rs index 6b2f5ee..4b43c89 100644 --- a/traits/src/sign.rs +++ b/traits/src/sign.rs @@ -192,8 +192,13 @@ fn unsigned_wrapping_is_unsigned() { fn require_unsigned(_: &T) {} require_unsigned(&Wrapping(42_u32)); } +/* +// Commenting this out since it doesn't compile on Rust 1.8, +// because on this version Wrapping doesn't implement Neg and therefore can't +// implement Signed. #[test] fn signed_wrapping_is_signed() { fn require_signed(_: &T) {} require_signed(&Wrapping(-42)); } +*/