Browse Source

wrapping: add WrappingNeg trait

Olivier Chassé St-Laurent 5 năm trước cách đây
mục cha
commit
54c9c257f7
2 tập tin đã thay đổi với 70 bổ sung2 xóa
  1. 3 1
      src/lib.rs
  2. 67 1
      src/ops/wrapping.rs

+ 3 - 1
src/lib.rs

@@ -43,7 +43,9 @@ pub use ops::checked::{
 pub use ops::inv::Inv;
 pub use ops::mul_add::{MulAdd, MulAddAssign};
 pub use ops::saturating::Saturating;
-pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingShl, WrappingShr, WrappingSub};
+pub use ops::wrapping::{
+    WrappingAdd, WrappingMul, WrappingNeg, WrappingShl, WrappingShr, WrappingSub,
+};
 pub use pow::{checked_pow, pow, Pow};
 pub use sign::{abs, abs_sub, signum, Signed, Unsigned};
 

+ 67 - 1
src/ops/wrapping.rs

@@ -1,5 +1,5 @@
 use core::num::Wrapping;
-use core::ops::{Add, Mul, Shl, Shr, Sub};
+use core::ops::{Add, Mul, Neg, Shl, Shr, Sub};
 
 macro_rules! wrapping_impl {
     ($trait_name:ident, $method:ident, $t:ty) => {
@@ -89,6 +89,53 @@ wrapping_impl!(WrappingMul, wrapping_mul, isize);
 #[cfg(has_i128)]
 wrapping_impl!(WrappingMul, wrapping_mul, i128);
 
+macro_rules! wrapping_unary_impl {
+    ($trait_name:ident, $method:ident, $t:ty) => {
+        impl $trait_name for $t {
+            #[inline]
+            fn $method(&self) -> $t {
+                <$t>::$method(*self)
+            }
+        }
+    };
+}
+
+/// Performs a negation that does not panic.
+pub trait WrappingNeg: Sized {
+    /// Wrapping (modular) negation. Computes `-self`,
+    /// wrapping around at the boundary of the type.
+    ///
+    /// Since unsigned types do not have negative equivalents
+    /// all applications of this function will wrap (except for `-0`).
+    /// For values smaller than the corresponding signed type's maximum
+    /// the result is the same as casting the corresponding signed value.
+    /// Any larger values are equivalent to `MAX + 1 - (val - MAX - 1)` where
+    /// `MAX` is the corresponding signed type's maximum.
+    ///
+    /// ```
+    /// use num_traits::WrappingNeg;
+    ///
+    /// assert_eq!(100i8.wrapping_neg(), -100);
+    /// assert_eq!((-128i8).wrapping_neg(), -128);
+    /// ```
+    fn wrapping_neg(&self) -> Self;
+}
+
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u8);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u16);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u32);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u64);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, usize);
+#[cfg(has_i128)]
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, u128);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i8);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i16);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i32);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i64);
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, isize);
+#[cfg(has_i128)]
+wrapping_unary_impl!(WrappingNeg, wrapping_neg, i128);
+
 macro_rules! wrapping_shift_impl {
     ($trait_name:ident, $method:ident, $t:ty) => {
         impl $trait_name for $t {
@@ -195,6 +242,14 @@ where
         Wrapping(self.0.wrapping_mul(&v.0))
     }
 }
+impl<T: WrappingNeg> WrappingNeg for Wrapping<T>
+where
+    Wrapping<T>: Neg<Output = Wrapping<T>>,
+{
+    fn wrapping_neg(&self) -> Self {
+        Wrapping(self.0.wrapping_neg())
+    }
+}
 impl<T: WrappingShl> WrappingShl for Wrapping<T>
 where
     Wrapping<T>: Shl<usize, Output = Wrapping<T>>,
@@ -223,6 +278,9 @@ fn test_wrapping_traits() {
     fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T {
         a.wrapping_mul(&b)
     }
+    fn wrapping_neg<T: WrappingNeg>(a: T) -> T {
+        a.wrapping_neg()
+    }
     fn wrapping_shl<T: WrappingShl>(a: T, b: u32) -> T {
         a.wrapping_shl(b)
     }
@@ -232,11 +290,13 @@ 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_neg(255), 1u8);
     assert_eq!(wrapping_shl(255, 8), 255u8);
     assert_eq!(wrapping_shr(255, 8), 255u8);
     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);
+    assert_eq!(wrapping_neg(255), (-Wrapping(255u8)).0);
     assert_eq!(wrapping_shl(255, 8), (Wrapping(255u8) << 8).0);
     assert_eq!(wrapping_shr(255, 8), (Wrapping(255u8) >> 8).0);
 }
@@ -259,6 +319,12 @@ fn wrapping_is_wrappingmul() {
     require_wrappingmul(&Wrapping(42));
 }
 
+#[test]
+fn wrapping_is_wrappingneg() {
+    fn require_wrappingneg<T: WrappingNeg>(_: &T) {}
+    require_wrappingneg(&Wrapping(42))
+}
+
 #[test]
 fn wrapping_is_wrappingshl() {
     fn require_wrappingshl<T: WrappingShl>(_: &T) {}