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