num_traits/ops/
saturating.rs

1use core::ops::{Add, Mul, Sub};
2
3/// Saturating math operations. Deprecated, use `SaturatingAdd`, `SaturatingSub` and
4/// `SaturatingMul` instead.
5pub trait Saturating {
6    /// Saturating addition operator.
7    /// Returns a+b, saturating at the numeric bounds instead of overflowing.
8    fn saturating_add(self, v: Self) -> Self;
9
10    /// Saturating subtraction operator.
11    /// Returns a-b, saturating at the numeric bounds instead of overflowing.
12    fn saturating_sub(self, v: Self) -> Self;
13}
14
15macro_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
31deprecated_saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
32#[cfg(has_i128)]
33deprecated_saturating_impl!(Saturating for i128 u128);
34
35macro_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.
47pub 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.
50    fn saturating_add(&self, v: &Self) -> Self;
51}
52
53saturating_impl!(SaturatingAdd, saturating_add, u8);
54saturating_impl!(SaturatingAdd, saturating_add, u16);
55saturating_impl!(SaturatingAdd, saturating_add, u32);
56saturating_impl!(SaturatingAdd, saturating_add, u64);
57saturating_impl!(SaturatingAdd, saturating_add, usize);
58#[cfg(has_i128)]
59saturating_impl!(SaturatingAdd, saturating_add, u128);
60
61saturating_impl!(SaturatingAdd, saturating_add, i8);
62saturating_impl!(SaturatingAdd, saturating_add, i16);
63saturating_impl!(SaturatingAdd, saturating_add, i32);
64saturating_impl!(SaturatingAdd, saturating_add, i64);
65saturating_impl!(SaturatingAdd, saturating_add, isize);
66#[cfg(has_i128)]
67saturating_impl!(SaturatingAdd, saturating_add, i128);
68
69/// Performs subtraction that saturates at the numeric bounds instead of overflowing.
70pub 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.
73    fn saturating_sub(&self, v: &Self) -> Self;
74}
75
76saturating_impl!(SaturatingSub, saturating_sub, u8);
77saturating_impl!(SaturatingSub, saturating_sub, u16);
78saturating_impl!(SaturatingSub, saturating_sub, u32);
79saturating_impl!(SaturatingSub, saturating_sub, u64);
80saturating_impl!(SaturatingSub, saturating_sub, usize);
81#[cfg(has_i128)]
82saturating_impl!(SaturatingSub, saturating_sub, u128);
83
84saturating_impl!(SaturatingSub, saturating_sub, i8);
85saturating_impl!(SaturatingSub, saturating_sub, i16);
86saturating_impl!(SaturatingSub, saturating_sub, i32);
87saturating_impl!(SaturatingSub, saturating_sub, i64);
88saturating_impl!(SaturatingSub, saturating_sub, isize);
89#[cfg(has_i128)]
90saturating_impl!(SaturatingSub, saturating_sub, i128);
91
92/// Performs multiplication that saturates at the numeric bounds instead of overflowing.
93pub 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.
96    fn saturating_mul(&self, v: &Self) -> Self;
97}
98
99saturating_impl!(SaturatingMul, saturating_mul, u8);
100saturating_impl!(SaturatingMul, saturating_mul, u16);
101saturating_impl!(SaturatingMul, saturating_mul, u32);
102saturating_impl!(SaturatingMul, saturating_mul, u64);
103saturating_impl!(SaturatingMul, saturating_mul, usize);
104#[cfg(has_i128)]
105saturating_impl!(SaturatingMul, saturating_mul, u128);
106
107saturating_impl!(SaturatingMul, saturating_mul, i8);
108saturating_impl!(SaturatingMul, saturating_mul, i16);
109saturating_impl!(SaturatingMul, saturating_mul, i32);
110saturating_impl!(SaturatingMul, saturating_mul, i64);
111saturating_impl!(SaturatingMul, saturating_mul, isize);
112#[cfg(has_i128)]
113saturating_impl!(SaturatingMul, saturating_mul, i128);
114
115// TODO: add SaturatingNeg for signed integer primitives once the saturating_neg() API is stable.
116
117#[test]
118fn 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}