diff --git a/Cargo.toml b/Cargo.toml index b0ddbe27..af4c1e42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ categories = ["algorithms", "science", "no-std"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-num/num-traits" name = "num-traits" -version = "0.2.19" +version = "0.3.0" readme = "README.md" build = "build.rs" exclude = ["/ci/*", "/.github/*"] diff --git a/src/ops/wrapping.rs b/src/ops/wrapping.rs index 3a8b3311..0628399f 100644 --- a/src/ops/wrapping.rs +++ b/src/ops/wrapping.rs @@ -3,28 +3,25 @@ use core::ops::{Add, Mul, Neg, Shl, Shr, Sub}; macro_rules! wrapping_impl { ($trait_name:ident, $method:ident, $t:ty) => { - impl $trait_name for $t { - #[inline] - fn $method(&self, v: &Self) -> Self { - <$t>::$method(*self, *v) - } - } - }; - ($trait_name:ident, $method:ident, $t:ty, $rhs:ty) => { - impl $trait_name<$rhs> for $t { + impl $trait_name for $t { + type WrappingOutput = $t; + #[inline] - fn $method(&self, v: &$rhs) -> Self { - <$t>::$method(*self, *v) + fn $method(self, v: Self) -> Self { + <$t>::$method(self, v) } } }; } /// Performs addition that wraps around on overflow. -pub trait WrappingAdd: Sized + Add { +pub trait WrappingAdd: Sized + Add { + /// The result type. + type WrappingOutput; + /// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of /// the type. - fn wrapping_add(&self, v: &Self) -> Self; + fn wrapping_add(self, v: Rhs) -> Self::WrappingOutput; } wrapping_impl!(WrappingAdd, wrapping_add, u8); @@ -42,10 +39,13 @@ wrapping_impl!(WrappingAdd, wrapping_add, isize); wrapping_impl!(WrappingAdd, wrapping_add, i128); /// Performs subtraction that wraps around on overflow. -pub trait WrappingSub: Sized + Sub { +pub trait WrappingSub: Sized + Sub { + /// The result type. + type WrappingOutput; + /// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary /// of the type. - fn wrapping_sub(&self, v: &Self) -> Self; + fn wrapping_sub(self, v: Rhs) -> Self::WrappingOutput; } wrapping_impl!(WrappingSub, wrapping_sub, u8); @@ -63,10 +63,13 @@ wrapping_impl!(WrappingSub, wrapping_sub, isize); wrapping_impl!(WrappingSub, wrapping_sub, i128); /// Performs multiplication that wraps around on overflow. -pub trait WrappingMul: Sized + Mul { +pub trait WrappingMul: Sized + Mul { + /// The result type. + type WrappingOutput; + /// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary /// of the type. - fn wrapping_mul(&self, v: &Self) -> Self; + fn wrapping_mul(self, v: Rhs) -> Self::WrappingOutput; } wrapping_impl!(WrappingMul, wrapping_mul, u8); @@ -86,9 +89,11 @@ wrapping_impl!(WrappingMul, wrapping_mul, i128); macro_rules! wrapping_unary_impl { ($trait_name:ident, $method:ident, $t:ty) => { impl $trait_name for $t { + type WrappingOutput = Self; + #[inline] - fn $method(&self) -> $t { - <$t>::$method(*self) + fn $method(self) -> Self { + <$t>::$method(self) } } }; @@ -96,6 +101,9 @@ macro_rules! wrapping_unary_impl { /// Performs a negation that does not panic. pub trait WrappingNeg: Sized { + /// The result type. + type WrappingOutput; + /// Wrapping (modular) negation. Computes `-self`, /// wrapping around at the boundary of the type. /// @@ -113,7 +121,7 @@ pub trait WrappingNeg: Sized { /// assert_eq!((-100i8).wrapping_neg(), 100); /// assert_eq!((-128i8).wrapping_neg(), -128); // wrapped! /// ``` - fn wrapping_neg(&self) -> Self; + fn wrapping_neg(self) -> Self::WrappingOutput; } wrapping_unary_impl!(WrappingNeg, wrapping_neg, u8); @@ -132,9 +140,11 @@ wrapping_unary_impl!(WrappingNeg, wrapping_neg, i128); macro_rules! wrapping_shift_impl { ($trait_name:ident, $method:ident, $t:ty) => { impl $trait_name for $t { + type WrappingOutput = Self; + #[inline] - fn $method(&self, rhs: u32) -> $t { - <$t>::$method(*self, rhs) + fn $method(self, rhs: u32) -> Self::WrappingOutput { + <$t>::$method(self, rhs) } } }; @@ -142,6 +152,9 @@ macro_rules! wrapping_shift_impl { /// Performs a left shift that does not panic. pub trait WrappingShl: Sized + Shl { + /// The result type. + type WrappingOutput; + /// Panic-free bitwise shift-left; yields `self << mask(rhs)`, /// where `mask` removes any high order bits of `rhs` that would /// cause the shift to exceed the bitwidth of the type. @@ -151,12 +164,12 @@ pub trait WrappingShl: Sized + Shl { /// /// let x: u16 = 0x0001; /// - /// assert_eq!(WrappingShl::wrapping_shl(&x, 0), 0x0001); - /// assert_eq!(WrappingShl::wrapping_shl(&x, 1), 0x0002); - /// assert_eq!(WrappingShl::wrapping_shl(&x, 15), 0x8000); - /// assert_eq!(WrappingShl::wrapping_shl(&x, 16), 0x0001); + /// assert_eq!(WrappingShl::wrapping_shl(x, 0), 0x0001); + /// assert_eq!(WrappingShl::wrapping_shl(x, 1), 0x0002); + /// assert_eq!(WrappingShl::wrapping_shl(x, 15), 0x8000); + /// assert_eq!(WrappingShl::wrapping_shl(x, 16), 0x0001); /// ``` - fn wrapping_shl(&self, rhs: u32) -> Self; + fn wrapping_shl(self, rhs: u32) -> Self::WrappingOutput; } wrapping_shift_impl!(WrappingShl, wrapping_shl, u8); @@ -175,6 +188,9 @@ wrapping_shift_impl!(WrappingShl, wrapping_shl, i128); /// Performs a right shift that does not panic. pub trait WrappingShr: Sized + Shr { + /// The result type. + type WrappingOutput; + /// Panic-free bitwise shift-right; yields `self >> mask(rhs)`, /// where `mask` removes any high order bits of `rhs` that would /// cause the shift to exceed the bitwidth of the type. @@ -184,12 +200,12 @@ pub trait WrappingShr: Sized + Shr { /// /// let x: u16 = 0x8000; /// - /// assert_eq!(WrappingShr::wrapping_shr(&x, 0), 0x8000); - /// assert_eq!(WrappingShr::wrapping_shr(&x, 1), 0x4000); - /// assert_eq!(WrappingShr::wrapping_shr(&x, 15), 0x0001); - /// assert_eq!(WrappingShr::wrapping_shr(&x, 16), 0x8000); + /// assert_eq!(WrappingShr::wrapping_shr(x, 0), 0x8000); + /// assert_eq!(WrappingShr::wrapping_shr(x, 1), 0x4000); + /// assert_eq!(WrappingShr::wrapping_shr(x, 15), 0x0001); + /// assert_eq!(WrappingShr::wrapping_shr(x, 16), 0x8000); /// ``` - fn wrapping_shr(&self, rhs: u32) -> Self; + fn wrapping_shr(self, rhs: u32) -> Self::WrappingOutput; } wrapping_shift_impl!(WrappingShr, wrapping_shr, u8); @@ -207,73 +223,93 @@ wrapping_shift_impl!(WrappingShr, wrapping_shr, isize); wrapping_shift_impl!(WrappingShr, wrapping_shr, i128); // Well this is a bit funny, but all the more appropriate. -impl WrappingAdd for Wrapping +impl WrappingAdd for Wrapping where - Wrapping: Add>, + T: WrappingAdd, + Wrapping: Add, { - fn wrapping_add(&self, v: &Self) -> Self { - Wrapping(self.0.wrapping_add(&v.0)) + type WrappingOutput = Self; + + fn wrapping_add(self, v: Self) -> Self { + Wrapping(self.0.wrapping_add(v.0)) } } -impl WrappingSub for Wrapping + +impl WrappingSub for Wrapping where + T: WrappingSub, Wrapping: Sub>, { - fn wrapping_sub(&self, v: &Self) -> Self { - Wrapping(self.0.wrapping_sub(&v.0)) + type WrappingOutput = Self; + + fn wrapping_sub(self, v: Self) -> Self { + Wrapping(self.0.wrapping_sub(v.0)) } } -impl WrappingMul for Wrapping + +impl WrappingMul for Wrapping where + T: WrappingMul, Wrapping: Mul>, { - fn wrapping_mul(&self, v: &Self) -> Self { - Wrapping(self.0.wrapping_mul(&v.0)) + type WrappingOutput = Self; + + fn wrapping_mul(self, v: Self) -> Self { + Wrapping(self.0.wrapping_mul(v.0)) } } impl WrappingNeg for Wrapping where + T: WrappingNeg, Wrapping: Neg>, { - fn wrapping_neg(&self) -> Self { + type WrappingOutput = Self; + + fn wrapping_neg(self) -> Self { Wrapping(self.0.wrapping_neg()) } } impl WrappingShl for Wrapping where + T: WrappingShl, Wrapping: Shl>, { - fn wrapping_shl(&self, rhs: u32) -> Self { + type WrappingOutput = Self; + + fn wrapping_shl(self, rhs: u32) -> Self { Wrapping(self.0.wrapping_shl(rhs)) } } impl WrappingShr for Wrapping where + T: WrappingShr, Wrapping: Shr>, { - fn wrapping_shr(&self, rhs: u32) -> Self { + type WrappingOutput = Self; + + fn wrapping_shr(self, rhs: u32) -> Self { Wrapping(self.0.wrapping_shr(rhs)) } } #[test] fn test_wrapping_traits() { - fn wrapping_add(a: T, b: T) -> T { - a.wrapping_add(&b) + fn wrapping_add>(a: T, b: T) -> T { + a.wrapping_add(b) } - fn wrapping_sub(a: T, b: T) -> T { - a.wrapping_sub(&b) + fn wrapping_sub>(a: T, b: T) -> T { + a.wrapping_sub(b) } - fn wrapping_mul(a: T, b: T) -> T { - a.wrapping_mul(&b) + fn wrapping_mul>(a: T, b: T) -> T { + a.wrapping_mul(b) } - fn wrapping_neg(a: T) -> T { + fn wrapping_neg>(a: T) -> T { a.wrapping_neg() } - fn wrapping_shl(a: T, b: u32) -> T { + fn wrapping_shl>(a: T, b: u32) -> T { a.wrapping_shl(b) } - fn wrapping_shr(a: T, b: u32) -> T { + fn wrapping_shr>(a: T, b: u32) -> T { a.wrapping_shr(b) } assert_eq!(wrapping_add(255, 1), 0u8);