nam_num_traits/ops/
saturating.rs

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