wrapping.rs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. use core::num::Wrapping;
  2. use core::ops::{Add, Mul, Sub};
  3. macro_rules! wrapping_impl {
  4. ($trait_name:ident, $method:ident, $t:ty) => {
  5. impl $trait_name for $t {
  6. #[inline]
  7. fn $method(&self, v: &Self) -> Self {
  8. <$t>::$method(*self, *v)
  9. }
  10. }
  11. };
  12. ($trait_name:ident, $method:ident, $t:ty, $rhs:ty) => {
  13. impl $trait_name<$rhs> for $t {
  14. #[inline]
  15. fn $method(&self, v: &$rhs) -> Self {
  16. <$t>::$method(*self, *v)
  17. }
  18. }
  19. };
  20. }
  21. /// Performs addition that wraps around on overflow.
  22. pub trait WrappingAdd: Sized + Add<Self, Output = Self> {
  23. /// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of
  24. /// the type.
  25. fn wrapping_add(&self, v: &Self) -> Self;
  26. }
  27. wrapping_impl!(WrappingAdd, wrapping_add, u8);
  28. wrapping_impl!(WrappingAdd, wrapping_add, u16);
  29. wrapping_impl!(WrappingAdd, wrapping_add, u32);
  30. wrapping_impl!(WrappingAdd, wrapping_add, u64);
  31. wrapping_impl!(WrappingAdd, wrapping_add, usize);
  32. #[cfg(has_i128)]
  33. wrapping_impl!(WrappingAdd, wrapping_add, u128);
  34. wrapping_impl!(WrappingAdd, wrapping_add, i8);
  35. wrapping_impl!(WrappingAdd, wrapping_add, i16);
  36. wrapping_impl!(WrappingAdd, wrapping_add, i32);
  37. wrapping_impl!(WrappingAdd, wrapping_add, i64);
  38. wrapping_impl!(WrappingAdd, wrapping_add, isize);
  39. #[cfg(has_i128)]
  40. wrapping_impl!(WrappingAdd, wrapping_add, i128);
  41. /// Performs subtraction that wraps around on overflow.
  42. pub trait WrappingSub: Sized + Sub<Self, Output = Self> {
  43. /// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary
  44. /// of the type.
  45. fn wrapping_sub(&self, v: &Self) -> Self;
  46. }
  47. wrapping_impl!(WrappingSub, wrapping_sub, u8);
  48. wrapping_impl!(WrappingSub, wrapping_sub, u16);
  49. wrapping_impl!(WrappingSub, wrapping_sub, u32);
  50. wrapping_impl!(WrappingSub, wrapping_sub, u64);
  51. wrapping_impl!(WrappingSub, wrapping_sub, usize);
  52. #[cfg(has_i128)]
  53. wrapping_impl!(WrappingSub, wrapping_sub, u128);
  54. wrapping_impl!(WrappingSub, wrapping_sub, i8);
  55. wrapping_impl!(WrappingSub, wrapping_sub, i16);
  56. wrapping_impl!(WrappingSub, wrapping_sub, i32);
  57. wrapping_impl!(WrappingSub, wrapping_sub, i64);
  58. wrapping_impl!(WrappingSub, wrapping_sub, isize);
  59. #[cfg(has_i128)]
  60. wrapping_impl!(WrappingSub, wrapping_sub, i128);
  61. /// Performs multiplication that wraps around on overflow.
  62. pub trait WrappingMul: Sized + Mul<Self, Output = Self> {
  63. /// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary
  64. /// of the type.
  65. fn wrapping_mul(&self, v: &Self) -> Self;
  66. }
  67. wrapping_impl!(WrappingMul, wrapping_mul, u8);
  68. wrapping_impl!(WrappingMul, wrapping_mul, u16);
  69. wrapping_impl!(WrappingMul, wrapping_mul, u32);
  70. wrapping_impl!(WrappingMul, wrapping_mul, u64);
  71. wrapping_impl!(WrappingMul, wrapping_mul, usize);
  72. #[cfg(has_i128)]
  73. wrapping_impl!(WrappingMul, wrapping_mul, u128);
  74. wrapping_impl!(WrappingMul, wrapping_mul, i8);
  75. wrapping_impl!(WrappingMul, wrapping_mul, i16);
  76. wrapping_impl!(WrappingMul, wrapping_mul, i32);
  77. wrapping_impl!(WrappingMul, wrapping_mul, i64);
  78. wrapping_impl!(WrappingMul, wrapping_mul, isize);
  79. #[cfg(has_i128)]
  80. wrapping_impl!(WrappingMul, wrapping_mul, i128);
  81. // Well this is a bit funny, but all the more appropriate.
  82. impl<T: WrappingAdd> WrappingAdd for Wrapping<T>
  83. where
  84. Wrapping<T>: Add<Output = Wrapping<T>>,
  85. {
  86. fn wrapping_add(&self, v: &Self) -> Self {
  87. Wrapping(self.0.wrapping_add(&v.0))
  88. }
  89. }
  90. impl<T: WrappingSub> WrappingSub for Wrapping<T>
  91. where
  92. Wrapping<T>: Sub<Output = Wrapping<T>>,
  93. {
  94. fn wrapping_sub(&self, v: &Self) -> Self {
  95. Wrapping(self.0.wrapping_sub(&v.0))
  96. }
  97. }
  98. impl<T: WrappingMul> WrappingMul for Wrapping<T>
  99. where
  100. Wrapping<T>: Mul<Output = Wrapping<T>>,
  101. {
  102. fn wrapping_mul(&self, v: &Self) -> Self {
  103. Wrapping(self.0.wrapping_mul(&v.0))
  104. }
  105. }
  106. #[test]
  107. fn test_wrapping_traits() {
  108. fn wrapping_add<T: WrappingAdd>(a: T, b: T) -> T {
  109. a.wrapping_add(&b)
  110. }
  111. fn wrapping_sub<T: WrappingSub>(a: T, b: T) -> T {
  112. a.wrapping_sub(&b)
  113. }
  114. fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T {
  115. a.wrapping_mul(&b)
  116. }
  117. assert_eq!(wrapping_add(255, 1), 0u8);
  118. assert_eq!(wrapping_sub(0, 1), 255u8);
  119. assert_eq!(wrapping_mul(255, 2), 254u8);
  120. assert_eq!(wrapping_add(255, 1), (Wrapping(255u8) + Wrapping(1u8)).0);
  121. assert_eq!(wrapping_sub(0, 1), (Wrapping(0u8) - Wrapping(1u8)).0);
  122. assert_eq!(wrapping_mul(255, 2), (Wrapping(255u8) * Wrapping(2u8)).0);
  123. }
  124. #[test]
  125. fn wrapping_is_wrappingadd() {
  126. fn require_wrappingadd<T: WrappingAdd>(_: &T) {}
  127. require_wrappingadd(&Wrapping(42));
  128. }
  129. #[test]
  130. fn wrapping_is_wrappingsub() {
  131. fn require_wrappingsub<T: WrappingSub>(_: &T) {}
  132. require_wrappingsub(&Wrapping(42));
  133. }
  134. #[test]
  135. fn wrapping_is_wrappingmul() {
  136. fn require_wrappingmul<T: WrappingMul>(_: &T) {}
  137. require_wrappingmul(&Wrapping(42));
  138. }