saturating.rs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. use core::ops::{Add, Mul, Sub};
  2. /// Saturating math operations. Deprecated, use `SaturatingAdd`, `SaturatingSub` and
  3. /// `SaturatingMul` instead.
  4. pub trait Saturating {
  5. /// Saturating addition operator.
  6. /// Returns a+b, saturating at the numeric bounds instead of overflowing.
  7. fn saturating_add(self, v: Self) -> Self;
  8. /// Saturating subtraction operator.
  9. /// Returns a-b, saturating at the numeric bounds instead of overflowing.
  10. fn saturating_sub(self, v: Self) -> Self;
  11. }
  12. macro_rules! deprecated_saturating_impl {
  13. ($trait_name:ident for $($t:ty)*) => {$(
  14. impl $trait_name for $t {
  15. #[inline]
  16. fn saturating_add(self, v: Self) -> Self {
  17. Self::saturating_add(self, v)
  18. }
  19. #[inline]
  20. fn saturating_sub(self, v: Self) -> Self {
  21. Self::saturating_sub(self, v)
  22. }
  23. }
  24. )*}
  25. }
  26. deprecated_saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
  27. #[cfg(has_i128)]
  28. deprecated_saturating_impl!(Saturating for i128 u128);
  29. macro_rules! saturating_impl {
  30. ($trait_name:ident, $method:ident, $t:ty) => {
  31. impl $trait_name for $t {
  32. #[inline]
  33. fn $method(&self, v: &Self) -> Self {
  34. <$t>::$method(*self, *v)
  35. }
  36. }
  37. };
  38. }
  39. /// Performs addition that saturates at the numeric bounds instead of overflowing.
  40. pub trait SaturatingAdd: Sized + Add<Self, Output = Self> {
  41. /// Saturating addition. Computes `self + other`, saturating at the relevant high or low boundary of
  42. /// the type.
  43. fn saturating_add(&self, v: &Self) -> Self;
  44. }
  45. saturating_impl!(SaturatingAdd, saturating_add, u8);
  46. saturating_impl!(SaturatingAdd, saturating_add, u16);
  47. saturating_impl!(SaturatingAdd, saturating_add, u32);
  48. saturating_impl!(SaturatingAdd, saturating_add, u64);
  49. saturating_impl!(SaturatingAdd, saturating_add, usize);
  50. #[cfg(has_i128)]
  51. saturating_impl!(SaturatingAdd, saturating_add, u128);
  52. saturating_impl!(SaturatingAdd, saturating_add, i8);
  53. saturating_impl!(SaturatingAdd, saturating_add, i16);
  54. saturating_impl!(SaturatingAdd, saturating_add, i32);
  55. saturating_impl!(SaturatingAdd, saturating_add, i64);
  56. saturating_impl!(SaturatingAdd, saturating_add, isize);
  57. #[cfg(has_i128)]
  58. saturating_impl!(SaturatingAdd, saturating_add, i128);
  59. /// Performs subtraction that saturates at the numeric bounds instead of overflowing.
  60. pub trait SaturatingSub: Sized + Sub<Self, Output = Self> {
  61. /// Saturating subtraction. Computes `self - other`, saturating at the relevant high or low boundary of
  62. /// the type.
  63. fn saturating_sub(&self, v: &Self) -> Self;
  64. }
  65. saturating_impl!(SaturatingSub, saturating_sub, u8);
  66. saturating_impl!(SaturatingSub, saturating_sub, u16);
  67. saturating_impl!(SaturatingSub, saturating_sub, u32);
  68. saturating_impl!(SaturatingSub, saturating_sub, u64);
  69. saturating_impl!(SaturatingSub, saturating_sub, usize);
  70. #[cfg(has_i128)]
  71. saturating_impl!(SaturatingSub, saturating_sub, u128);
  72. saturating_impl!(SaturatingSub, saturating_sub, i8);
  73. saturating_impl!(SaturatingSub, saturating_sub, i16);
  74. saturating_impl!(SaturatingSub, saturating_sub, i32);
  75. saturating_impl!(SaturatingSub, saturating_sub, i64);
  76. saturating_impl!(SaturatingSub, saturating_sub, isize);
  77. #[cfg(has_i128)]
  78. saturating_impl!(SaturatingSub, saturating_sub, i128);
  79. /// Performs multiplication that saturates at the numeric bounds instead of overflowing.
  80. pub trait SaturatingMul: Sized + Mul<Self, Output = Self> {
  81. /// Saturating multiplication. Computes `self * other`, saturating at the relevant high or low boundary of
  82. /// the type.
  83. fn saturating_mul(&self, v: &Self) -> Self;
  84. }
  85. saturating_impl!(SaturatingMul, saturating_mul, u8);
  86. saturating_impl!(SaturatingMul, saturating_mul, u16);
  87. saturating_impl!(SaturatingMul, saturating_mul, u32);
  88. saturating_impl!(SaturatingMul, saturating_mul, u64);
  89. saturating_impl!(SaturatingMul, saturating_mul, usize);
  90. #[cfg(has_i128)]
  91. saturating_impl!(SaturatingMul, saturating_mul, u128);
  92. saturating_impl!(SaturatingMul, saturating_mul, i8);
  93. saturating_impl!(SaturatingMul, saturating_mul, i16);
  94. saturating_impl!(SaturatingMul, saturating_mul, i32);
  95. saturating_impl!(SaturatingMul, saturating_mul, i64);
  96. saturating_impl!(SaturatingMul, saturating_mul, isize);
  97. #[cfg(has_i128)]
  98. saturating_impl!(SaturatingMul, saturating_mul, i128);
  99. // TODO: add SaturatingNeg for signed integer primitives once the saturating_neg() API is stable.
  100. #[test]
  101. fn test_saturating_traits() {
  102. fn saturating_add<T: SaturatingAdd>(a: T, b: T) -> T {
  103. a.saturating_add(&b)
  104. }
  105. fn saturating_sub<T: SaturatingSub>(a: T, b: T) -> T {
  106. a.saturating_sub(&b)
  107. }
  108. fn saturating_mul<T: SaturatingMul>(a: T, b: T) -> T {
  109. a.saturating_mul(&b)
  110. }
  111. assert_eq!(saturating_add(255, 1), 255u8);
  112. assert_eq!(saturating_add(127, 1), 127i8);
  113. assert_eq!(saturating_add(-128, -1), -128i8);
  114. assert_eq!(saturating_sub(0, 1), 0u8);
  115. assert_eq!(saturating_sub(-128, 1), -128i8);
  116. assert_eq!(saturating_sub(127, -1), 127i8);
  117. assert_eq!(saturating_mul(255, 2), 255u8);
  118. assert_eq!(saturating_mul(127, 2), 127i8);
  119. assert_eq!(saturating_mul(-128, 2), -128i8);
  120. }