|
@@ -1,4 +1,7 @@
|
|
|
-/// Saturating math operations
|
|
|
+use core::ops::{Add, Mul, Sub};
|
|
|
+
|
|
|
+/// Saturating math operations. Deprecated, use `SaturatingAdd`, `SaturatingSub` and
|
|
|
+/// `SaturatingMul` instead.
|
|
|
pub trait Saturating {
|
|
|
/// Saturating addition operator.
|
|
|
/// Returns a+b, saturating at the numeric bounds instead of overflowing.
|
|
@@ -9,7 +12,7 @@ pub trait Saturating {
|
|
|
fn saturating_sub(self, v: Self) -> Self;
|
|
|
}
|
|
|
|
|
|
-macro_rules! saturating_impl {
|
|
|
+macro_rules! deprecated_saturating_impl {
|
|
|
($trait_name:ident for $($t:ty)*) => {$(
|
|
|
impl $trait_name for $t {
|
|
|
#[inline]
|
|
@@ -25,6 +28,110 @@ macro_rules! saturating_impl {
|
|
|
)*}
|
|
|
}
|
|
|
|
|
|
-saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
|
|
|
+deprecated_saturating_impl!(Saturating for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
|
|
|
+#[cfg(has_i128)]
|
|
|
+deprecated_saturating_impl!(Saturating for i128 u128);
|
|
|
+
|
|
|
+macro_rules! saturating_impl {
|
|
|
+ ($trait_name:ident, $method:ident, $t:ty) => {
|
|
|
+ impl $trait_name for $t {
|
|
|
+ #[inline]
|
|
|
+ fn $method(&self, v: &Self) -> Self {
|
|
|
+ <$t>::$method(*self, *v)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+/// Performs addition that saturates at the numeric bounds instead of overflowing.
|
|
|
+pub trait SaturatingAdd: Sized + Add<Self, Output = Self> {
|
|
|
+ /// Saturating addition. Computes `self + other`, saturating at the relevant high or low boundary of
|
|
|
+ /// the type.
|
|
|
+ fn saturating_add(&self, v: &Self) -> Self;
|
|
|
+}
|
|
|
+
|
|
|
+saturating_impl!(SaturatingAdd, saturating_add, u8);
|
|
|
+saturating_impl!(SaturatingAdd, saturating_add, u16);
|
|
|
+saturating_impl!(SaturatingAdd, saturating_add, u32);
|
|
|
+saturating_impl!(SaturatingAdd, saturating_add, u64);
|
|
|
+saturating_impl!(SaturatingAdd, saturating_add, usize);
|
|
|
+#[cfg(has_i128)]
|
|
|
+saturating_impl!(SaturatingAdd, saturating_add, u128);
|
|
|
+
|
|
|
+saturating_impl!(SaturatingAdd, saturating_add, i8);
|
|
|
+saturating_impl!(SaturatingAdd, saturating_add, i16);
|
|
|
+saturating_impl!(SaturatingAdd, saturating_add, i32);
|
|
|
+saturating_impl!(SaturatingAdd, saturating_add, i64);
|
|
|
+saturating_impl!(SaturatingAdd, saturating_add, isize);
|
|
|
+#[cfg(has_i128)]
|
|
|
+saturating_impl!(SaturatingAdd, saturating_add, i128);
|
|
|
+
|
|
|
+/// Performs subtraction that saturates at the numeric bounds instead of overflowing.
|
|
|
+pub trait SaturatingSub: Sized + Sub<Self, Output = Self> {
|
|
|
+ /// Saturating subtraction. Computes `self - other`, saturating at the relevant high or low boundary of
|
|
|
+ /// the type.
|
|
|
+ fn saturating_sub(&self, v: &Self) -> Self;
|
|
|
+}
|
|
|
+
|
|
|
+saturating_impl!(SaturatingSub, saturating_sub, u8);
|
|
|
+saturating_impl!(SaturatingSub, saturating_sub, u16);
|
|
|
+saturating_impl!(SaturatingSub, saturating_sub, u32);
|
|
|
+saturating_impl!(SaturatingSub, saturating_sub, u64);
|
|
|
+saturating_impl!(SaturatingSub, saturating_sub, usize);
|
|
|
#[cfg(has_i128)]
|
|
|
-saturating_impl!(Saturating for i128 u128);
|
|
|
+saturating_impl!(SaturatingSub, saturating_sub, u128);
|
|
|
+
|
|
|
+saturating_impl!(SaturatingSub, saturating_sub, i8);
|
|
|
+saturating_impl!(SaturatingSub, saturating_sub, i16);
|
|
|
+saturating_impl!(SaturatingSub, saturating_sub, i32);
|
|
|
+saturating_impl!(SaturatingSub, saturating_sub, i64);
|
|
|
+saturating_impl!(SaturatingSub, saturating_sub, isize);
|
|
|
+#[cfg(has_i128)]
|
|
|
+saturating_impl!(SaturatingSub, saturating_sub, i128);
|
|
|
+
|
|
|
+/// Performs multiplication that saturates at the numeric bounds instead of overflowing.
|
|
|
+pub trait SaturatingMul: Sized + Mul<Self, Output = Self> {
|
|
|
+ /// Saturating multiplication. Computes `self * other`, saturating at the relevant high or low boundary of
|
|
|
+ /// the type.
|
|
|
+ fn saturating_mul(&self, v: &Self) -> Self;
|
|
|
+}
|
|
|
+
|
|
|
+saturating_impl!(SaturatingMul, saturating_mul, u8);
|
|
|
+saturating_impl!(SaturatingMul, saturating_mul, u16);
|
|
|
+saturating_impl!(SaturatingMul, saturating_mul, u32);
|
|
|
+saturating_impl!(SaturatingMul, saturating_mul, u64);
|
|
|
+saturating_impl!(SaturatingMul, saturating_mul, usize);
|
|
|
+#[cfg(has_i128)]
|
|
|
+saturating_impl!(SaturatingMul, saturating_mul, u128);
|
|
|
+
|
|
|
+saturating_impl!(SaturatingMul, saturating_mul, i8);
|
|
|
+saturating_impl!(SaturatingMul, saturating_mul, i16);
|
|
|
+saturating_impl!(SaturatingMul, saturating_mul, i32);
|
|
|
+saturating_impl!(SaturatingMul, saturating_mul, i64);
|
|
|
+saturating_impl!(SaturatingMul, saturating_mul, isize);
|
|
|
+#[cfg(has_i128)]
|
|
|
+saturating_impl!(SaturatingMul, saturating_mul, i128);
|
|
|
+
|
|
|
+// TODO: add SaturatingNeg for signed integer primitives once the saturating_neg() API is stable.
|
|
|
+
|
|
|
+#[test]
|
|
|
+fn test_saturating_traits() {
|
|
|
+ fn saturating_add<T: SaturatingAdd>(a: T, b: T) -> T {
|
|
|
+ a.saturating_add(&b)
|
|
|
+ }
|
|
|
+ fn saturating_sub<T: SaturatingSub>(a: T, b: T) -> T {
|
|
|
+ a.saturating_sub(&b)
|
|
|
+ }
|
|
|
+ fn saturating_mul<T: SaturatingMul>(a: T, b: T) -> T {
|
|
|
+ a.saturating_mul(&b)
|
|
|
+ }
|
|
|
+ assert_eq!(saturating_add(255, 1), 255u8);
|
|
|
+ assert_eq!(saturating_add(127, 1), 127i8);
|
|
|
+ assert_eq!(saturating_add(-128, -1), -128i8);
|
|
|
+ assert_eq!(saturating_sub(0, 1), 0u8);
|
|
|
+ assert_eq!(saturating_sub(-128, 1), -128i8);
|
|
|
+ assert_eq!(saturating_sub(127, -1), 127i8);
|
|
|
+ assert_eq!(saturating_mul(255, 2), 255u8);
|
|
|
+ assert_eq!(saturating_mul(127, 2), 127i8);
|
|
|
+ assert_eq!(saturating_mul(-128, 2), -128i8);
|
|
|
+}
|