use core::ops::{Add, Div, Mul, Neg, Sub};
c0nst::c0nst! {
pub c0nst trait Saturating {
fn saturating_add(self, v: Self) -> Self;
fn saturating_sub(self, v: Self) -> Self;
}
}
macro_rules! deprecated_saturating_impl {
($trait_name:ident for $($t:ty)*) => {$(
c0nst::c0nst! {
c0nst impl $trait_name for $t {
#[inline]
fn saturating_add(self, v: Self) -> Self {
Self::saturating_add(self, v)
}
#[inline]
fn saturating_sub(self, v: Self) -> Self {
Self::saturating_sub(self, v)
}
}
}
)*}
}
deprecated_saturating_impl!(Saturating for isize i8 i16 i32 i64 i128);
deprecated_saturating_impl!(Saturating for usize u8 u16 u32 u64 u128);
macro_rules! saturating_impl {
($trait_name:ident, $method:ident, $t:ty) => {
c0nst::c0nst! {
c0nst impl $trait_name for $t {
#[inline]
fn $method(self, v: Self) -> Self {
<$t>::$method(self, v)
}
}
}
};
}
c0nst::c0nst! {
pub c0nst trait SaturatingAdd: Sized + [c0nst] Add<Self> {
fn saturating_add(self, v: Self) -> <Self as Add<Self>>::Output;
}
}
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);
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);
saturating_impl!(SaturatingAdd, saturating_add, i128);
c0nst::c0nst! {
pub c0nst trait SaturatingSub: Sized + [c0nst] Sub<Self> {
fn saturating_sub(self, v: Self) -> <Self as Sub<Self>>::Output;
}
}
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);
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);
saturating_impl!(SaturatingSub, saturating_sub, i128);
c0nst::c0nst! {
pub c0nst trait SaturatingMul: Sized + [c0nst] Mul<Self> {
fn saturating_mul(self, v: Self) -> <Self as Mul<Self>>::Output;
}
}
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);
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);
saturating_impl!(SaturatingMul, saturating_mul, i128);
c0nst::c0nst! {
pub c0nst trait SaturatingDiv: Sized + [c0nst] Div<Self> {
fn saturating_div(self, v: Self) -> <Self as Div<Self>>::Output;
}
}
saturating_impl!(SaturatingDiv, saturating_div, u8);
saturating_impl!(SaturatingDiv, saturating_div, u16);
saturating_impl!(SaturatingDiv, saturating_div, u32);
saturating_impl!(SaturatingDiv, saturating_div, u64);
saturating_impl!(SaturatingDiv, saturating_div, usize);
saturating_impl!(SaturatingDiv, saturating_div, u128);
saturating_impl!(SaturatingDiv, saturating_div, i8);
saturating_impl!(SaturatingDiv, saturating_div, i16);
saturating_impl!(SaturatingDiv, saturating_div, i32);
saturating_impl!(SaturatingDiv, saturating_div, i64);
saturating_impl!(SaturatingDiv, saturating_div, isize);
saturating_impl!(SaturatingDiv, saturating_div, i128);
macro_rules! saturating_unary_impl {
($trait_name:ident, $method:ident, $t:ty) => {
c0nst::c0nst! {
c0nst impl $trait_name for $t {
#[inline]
fn $method(self) -> $t {
<$t>::$method(self)
}
}
}
};
}
c0nst::c0nst! {
pub c0nst trait SaturatingNeg: Sized + [c0nst] Neg {
fn saturating_neg(self) -> <Self as Neg>::Output;
}
}
saturating_unary_impl!(SaturatingNeg, saturating_neg, i8);
saturating_unary_impl!(SaturatingNeg, saturating_neg, i16);
saturating_unary_impl!(SaturatingNeg, saturating_neg, i32);
saturating_unary_impl!(SaturatingNeg, saturating_neg, i64);
saturating_unary_impl!(SaturatingNeg, saturating_neg, isize);
saturating_unary_impl!(SaturatingNeg, saturating_neg, i128);
c0nst::c0nst! {
pub c0nst trait SaturatingAbs: Sized + [c0nst] Neg {
fn saturating_abs(self) -> <Self as Neg>::Output;
}
}
saturating_unary_impl!(SaturatingAbs, saturating_abs, i8);
saturating_unary_impl!(SaturatingAbs, saturating_abs, i16);
saturating_unary_impl!(SaturatingAbs, saturating_abs, i32);
saturating_unary_impl!(SaturatingAbs, saturating_abs, i64);
saturating_unary_impl!(SaturatingAbs, saturating_abs, isize);
saturating_unary_impl!(SaturatingAbs, saturating_abs, i128);
macro_rules! saturating_pow_impl {
($t:ty) => {
c0nst::c0nst! {
c0nst impl SaturatingPow for $t {
#[inline]
fn saturating_pow(self, exp: u32) -> $t {
<$t>::saturating_pow(self, exp)
}
}
}
};
}
c0nst::c0nst! {
pub c0nst trait SaturatingPow: Sized + [c0nst] Mul<Self> {
fn saturating_pow(self, exp: u32) -> <Self as Mul<Self>>::Output;
}
}
saturating_pow_impl!(u8);
saturating_pow_impl!(u16);
saturating_pow_impl!(u32);
saturating_pow_impl!(u64);
saturating_pow_impl!(usize);
saturating_pow_impl!(u128);
saturating_pow_impl!(i8);
saturating_pow_impl!(i16);
saturating_pow_impl!(i32);
saturating_pow_impl!(i64);
saturating_pow_impl!(isize);
saturating_pow_impl!(i128);
#[test]
fn test_saturating_div_neg_abs_pow() {
assert_eq!(SaturatingDiv::saturating_div(i8::MIN, -1), i8::MAX);
assert_eq!(SaturatingDiv::saturating_div(100u8, 7), 14);
assert_eq!(SaturatingNeg::saturating_neg(i16::MIN), i16::MAX);
assert_eq!(SaturatingNeg::saturating_neg(7i16), -7);
assert_eq!(SaturatingAbs::saturating_abs(i16::MIN), i16::MAX);
assert_eq!(SaturatingAbs::saturating_abs(-7i16), 7);
assert_eq!(SaturatingPow::saturating_pow(2u16, 17), u16::MAX);
assert_eq!(SaturatingPow::saturating_pow(-2i16, 15), i16::MIN);
}
#[test]
fn test_saturating_traits() {
fn saturating_add<T: SaturatingAdd<Output = T>>(a: T, b: T) -> T {
a.saturating_add(b)
}
fn saturating_sub<T: SaturatingSub<Output = T>>(a: T, b: T) -> T {
a.saturating_sub(b)
}
fn saturating_mul<T: SaturatingMul<Output = T>>(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);
}