wrapping.rs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. use std::ops::{Add, Sub, Mul};
  2. use std::num::Wrapping;
  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. wrapping_impl!(WrappingAdd, wrapping_add, i8);
  33. wrapping_impl!(WrappingAdd, wrapping_add, i16);
  34. wrapping_impl!(WrappingAdd, wrapping_add, i32);
  35. wrapping_impl!(WrappingAdd, wrapping_add, i64);
  36. wrapping_impl!(WrappingAdd, wrapping_add, isize);
  37. /// Performs subtraction that wraps around on overflow.
  38. pub trait WrappingSub: Sized + Sub<Self, Output=Self> {
  39. /// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary
  40. /// of the type.
  41. fn wrapping_sub(&self, v: &Self) -> Self;
  42. }
  43. wrapping_impl!(WrappingSub, wrapping_sub, u8);
  44. wrapping_impl!(WrappingSub, wrapping_sub, u16);
  45. wrapping_impl!(WrappingSub, wrapping_sub, u32);
  46. wrapping_impl!(WrappingSub, wrapping_sub, u64);
  47. wrapping_impl!(WrappingSub, wrapping_sub, usize);
  48. wrapping_impl!(WrappingSub, wrapping_sub, i8);
  49. wrapping_impl!(WrappingSub, wrapping_sub, i16);
  50. wrapping_impl!(WrappingSub, wrapping_sub, i32);
  51. wrapping_impl!(WrappingSub, wrapping_sub, i64);
  52. wrapping_impl!(WrappingSub, wrapping_sub, isize);
  53. /// Performs multiplication that wraps around on overflow.
  54. pub trait WrappingMul: Sized + Mul<Self, Output=Self> {
  55. /// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary
  56. /// of the type.
  57. fn wrapping_mul(&self, v: &Self) -> Self;
  58. }
  59. wrapping_impl!(WrappingMul, wrapping_mul, u8);
  60. wrapping_impl!(WrappingMul, wrapping_mul, u16);
  61. wrapping_impl!(WrappingMul, wrapping_mul, u32);
  62. wrapping_impl!(WrappingMul, wrapping_mul, u64);
  63. wrapping_impl!(WrappingMul, wrapping_mul, usize);
  64. wrapping_impl!(WrappingMul, wrapping_mul, i8);
  65. wrapping_impl!(WrappingMul, wrapping_mul, i16);
  66. wrapping_impl!(WrappingMul, wrapping_mul, i32);
  67. wrapping_impl!(WrappingMul, wrapping_mul, i64);
  68. wrapping_impl!(WrappingMul, wrapping_mul, isize);
  69. // Well this is a bit funny, but all the more appropriate.
  70. impl<T: WrappingAdd> WrappingAdd for Wrapping<T> where Wrapping<T>: Add<Output = Wrapping<T>> {
  71. fn wrapping_add(&self, v: &Self) -> Self {
  72. Wrapping(self.0.wrapping_add(&v.0))
  73. }
  74. }
  75. impl<T: WrappingSub> WrappingSub for Wrapping<T> where Wrapping<T>: Sub<Output = Wrapping<T>> {
  76. fn wrapping_sub(&self, v: &Self) -> Self {
  77. Wrapping(self.0.wrapping_sub(&v.0))
  78. }
  79. }
  80. impl<T: WrappingMul> WrappingMul for Wrapping<T> where Wrapping<T>: Mul<Output = Wrapping<T>> {
  81. fn wrapping_mul(&self, v: &Self) -> Self {
  82. Wrapping(self.0.wrapping_mul(&v.0))
  83. }
  84. }
  85. #[test]
  86. fn test_wrapping_traits() {
  87. fn wrapping_add<T: WrappingAdd>(a: T, b: T) -> T { a.wrapping_add(&b) }
  88. fn wrapping_sub<T: WrappingSub>(a: T, b: T) -> T { a.wrapping_sub(&b) }
  89. fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T { a.wrapping_mul(&b) }
  90. assert_eq!(wrapping_add(255, 1), 0u8);
  91. assert_eq!(wrapping_sub(0, 1), 255u8);
  92. assert_eq!(wrapping_mul(255, 2), 254u8);
  93. assert_eq!(wrapping_add(255, 1), (Wrapping(255u8) + Wrapping(1u8)).0);
  94. assert_eq!(wrapping_sub(0, 1), (Wrapping(0u8) - Wrapping(1u8)).0);
  95. assert_eq!(wrapping_mul(255, 2), (Wrapping(255u8) * Wrapping(2u8)).0);
  96. }
  97. #[test]
  98. fn wrapping_is_wrappingadd() {
  99. fn require_wrappingadd<T: WrappingAdd>(_: &T) {}
  100. require_wrappingadd(&Wrapping(42));
  101. }
  102. #[test]
  103. fn wrapping_is_wrappingsub() {
  104. fn require_wrappingsub<T: WrappingSub>(_: &T) {}
  105. require_wrappingsub(&Wrapping(42));
  106. }
  107. #[test]
  108. fn wrapping_is_wrappingmul() {
  109. fn require_wrappingmul<T: WrappingMul>(_: &T) {}
  110. require_wrappingmul(&Wrapping(42));
  111. }