use core::num::Wrapping;
macro_rules! wrapping_impl {
($trait_name:ident, $method:ident, $t:ty) => {
c0nst::c0nst! {
c0nst impl $trait_name for $t {
type Output = $t;
#[inline]
fn $method(self, v: Self) -> Self {
<$t>::$method(self, v)
}
}
}
};
($trait_name:ident, $method:ident, $t:ty, $rhs:ty) => {
c0nst::c0nst! {
c0nst impl $trait_name<$rhs> for $t {
type Output = $t;
#[inline]
fn $method(self, v: $rhs) -> Self {
<$t>::$method(self, v)
}
}
}
};
}
c0nst::c0nst! {
pub c0nst trait WrappingAdd: Sized {
type Output;
fn wrapping_add(self, v: Self) -> Self::Output;
}
}
wrapping_impl!(WrappingAdd, wrapping_add, u8);
wrapping_impl!(WrappingAdd, wrapping_add, u16);
wrapping_impl!(WrappingAdd, wrapping_add, u32);
wrapping_impl!(WrappingAdd, wrapping_add, u64);
wrapping_impl!(WrappingAdd, wrapping_add, usize);
wrapping_impl!(WrappingAdd, wrapping_add, u128);
wrapping_impl!(WrappingAdd, wrapping_add, i8);
wrapping_impl!(WrappingAdd, wrapping_add, i16);
wrapping_impl!(WrappingAdd, wrapping_add, i32);
wrapping_impl!(WrappingAdd, wrapping_add, i64);
wrapping_impl!(WrappingAdd, wrapping_add, isize);
wrapping_impl!(WrappingAdd, wrapping_add, i128);
c0nst::c0nst! {
pub c0nst trait WrappingSub: Sized {
type Output;
fn wrapping_sub(self, v: Self) -> Self::Output;
}
}
wrapping_impl!(WrappingSub, wrapping_sub, u8);
wrapping_impl!(WrappingSub, wrapping_sub, u16);
wrapping_impl!(WrappingSub, wrapping_sub, u32);
wrapping_impl!(WrappingSub, wrapping_sub, u64);
wrapping_impl!(WrappingSub, wrapping_sub, usize);
wrapping_impl!(WrappingSub, wrapping_sub, u128);
wrapping_impl!(WrappingSub, wrapping_sub, i8);
wrapping_impl!(WrappingSub, wrapping_sub, i16);
wrapping_impl!(WrappingSub, wrapping_sub, i32);
wrapping_impl!(WrappingSub, wrapping_sub, i64);
wrapping_impl!(WrappingSub, wrapping_sub, isize);
wrapping_impl!(WrappingSub, wrapping_sub, i128);
c0nst::c0nst! {
pub c0nst trait WrappingMul: Sized {
type Output;
fn wrapping_mul(self, v: Self) -> Self::Output;
}
}
wrapping_impl!(WrappingMul, wrapping_mul, u8);
wrapping_impl!(WrappingMul, wrapping_mul, u16);
wrapping_impl!(WrappingMul, wrapping_mul, u32);
wrapping_impl!(WrappingMul, wrapping_mul, u64);
wrapping_impl!(WrappingMul, wrapping_mul, usize);
wrapping_impl!(WrappingMul, wrapping_mul, u128);
wrapping_impl!(WrappingMul, wrapping_mul, i8);
wrapping_impl!(WrappingMul, wrapping_mul, i16);
wrapping_impl!(WrappingMul, wrapping_mul, i32);
wrapping_impl!(WrappingMul, wrapping_mul, i64);
wrapping_impl!(WrappingMul, wrapping_mul, isize);
wrapping_impl!(WrappingMul, wrapping_mul, i128);
macro_rules! wrapping_neg_impl {
($($t:ty)*) => {$(
c0nst::c0nst! {
c0nst impl WrappingNeg for $t {
type Output = $t;
#[inline]
fn wrapping_neg(self) -> $t {
<$t>::wrapping_neg(self)
}
}
}
)*};
}
macro_rules! wrapping_unary_impl {
($trait_name:ident, $method:ident, $t:ty) => {
c0nst::c0nst! {
c0nst impl $trait_name for $t {
type Output = $t;
#[inline]
fn $method(self) -> $t {
<$t>::$method(self)
}
}
}
};
}
c0nst::c0nst! {
pub c0nst trait WrappingNeg: Sized {
type Output;
fn wrapping_neg(self) -> Self::Output;
}
}
wrapping_neg_impl!(u8 u16 u32 u64 usize u128 i8 i16 i32 i64 isize i128);
macro_rules! wrapping_shift_impl {
($trait_name:ident, $method:ident, $t:ty) => {
c0nst::c0nst! {
c0nst impl $trait_name for $t {
type Output = $t;
#[inline]
fn $method(self, rhs: u32) -> $t {
<$t>::$method(self, rhs)
}
}
}
};
}
c0nst::c0nst! {
pub c0nst trait WrappingShl: Sized {
type Output;
fn wrapping_shl(self, rhs: u32) -> Self::Output;
}
}
wrapping_shift_impl!(WrappingShl, wrapping_shl, u8);
wrapping_shift_impl!(WrappingShl, wrapping_shl, u16);
wrapping_shift_impl!(WrappingShl, wrapping_shl, u32);
wrapping_shift_impl!(WrappingShl, wrapping_shl, u64);
wrapping_shift_impl!(WrappingShl, wrapping_shl, usize);
wrapping_shift_impl!(WrappingShl, wrapping_shl, u128);
wrapping_shift_impl!(WrappingShl, wrapping_shl, i8);
wrapping_shift_impl!(WrappingShl, wrapping_shl, i16);
wrapping_shift_impl!(WrappingShl, wrapping_shl, i32);
wrapping_shift_impl!(WrappingShl, wrapping_shl, i64);
wrapping_shift_impl!(WrappingShl, wrapping_shl, isize);
wrapping_shift_impl!(WrappingShl, wrapping_shl, i128);
c0nst::c0nst! {
pub c0nst trait WrappingShr: Sized {
type Output;
fn wrapping_shr(self, rhs: u32) -> Self::Output;
}
}
wrapping_shift_impl!(WrappingShr, wrapping_shr, u8);
wrapping_shift_impl!(WrappingShr, wrapping_shr, u16);
wrapping_shift_impl!(WrappingShr, wrapping_shr, u32);
wrapping_shift_impl!(WrappingShr, wrapping_shr, u64);
wrapping_shift_impl!(WrappingShr, wrapping_shr, usize);
wrapping_shift_impl!(WrappingShr, wrapping_shr, u128);
wrapping_shift_impl!(WrappingShr, wrapping_shr, i8);
wrapping_shift_impl!(WrappingShr, wrapping_shr, i16);
wrapping_shift_impl!(WrappingShr, wrapping_shr, i32);
wrapping_shift_impl!(WrappingShr, wrapping_shr, i64);
wrapping_shift_impl!(WrappingShr, wrapping_shr, isize);
wrapping_shift_impl!(WrappingShr, wrapping_shr, i128);
c0nst::c0nst! {
pub c0nst trait WrappingDiv: Sized {
type Output;
fn wrapping_div(self, v: Self) -> Self::Output;
}
}
wrapping_impl!(WrappingDiv, wrapping_div, u8);
wrapping_impl!(WrappingDiv, wrapping_div, u16);
wrapping_impl!(WrappingDiv, wrapping_div, u32);
wrapping_impl!(WrappingDiv, wrapping_div, u64);
wrapping_impl!(WrappingDiv, wrapping_div, usize);
wrapping_impl!(WrappingDiv, wrapping_div, u128);
wrapping_impl!(WrappingDiv, wrapping_div, i8);
wrapping_impl!(WrappingDiv, wrapping_div, i16);
wrapping_impl!(WrappingDiv, wrapping_div, i32);
wrapping_impl!(WrappingDiv, wrapping_div, i64);
wrapping_impl!(WrappingDiv, wrapping_div, isize);
wrapping_impl!(WrappingDiv, wrapping_div, i128);
c0nst::c0nst! {
pub c0nst trait WrappingRem: Sized {
type Output;
fn wrapping_rem(self, v: Self) -> Self::Output;
}
}
wrapping_impl!(WrappingRem, wrapping_rem, u8);
wrapping_impl!(WrappingRem, wrapping_rem, u16);
wrapping_impl!(WrappingRem, wrapping_rem, u32);
wrapping_impl!(WrappingRem, wrapping_rem, u64);
wrapping_impl!(WrappingRem, wrapping_rem, usize);
wrapping_impl!(WrappingRem, wrapping_rem, u128);
wrapping_impl!(WrappingRem, wrapping_rem, i8);
wrapping_impl!(WrappingRem, wrapping_rem, i16);
wrapping_impl!(WrappingRem, wrapping_rem, i32);
wrapping_impl!(WrappingRem, wrapping_rem, i64);
wrapping_impl!(WrappingRem, wrapping_rem, isize);
wrapping_impl!(WrappingRem, wrapping_rem, i128);
c0nst::c0nst! {
pub c0nst trait WrappingAbs: Sized {
type Output;
fn wrapping_abs(self) -> Self::Output;
}
}
wrapping_unary_impl!(WrappingAbs, wrapping_abs, i8);
wrapping_unary_impl!(WrappingAbs, wrapping_abs, i16);
wrapping_unary_impl!(WrappingAbs, wrapping_abs, i32);
wrapping_unary_impl!(WrappingAbs, wrapping_abs, i64);
wrapping_unary_impl!(WrappingAbs, wrapping_abs, isize);
wrapping_unary_impl!(WrappingAbs, wrapping_abs, i128);
c0nst::c0nst! {
pub c0nst trait WrappingPow: Sized {
type Output;
fn wrapping_pow(self, exp: u32) -> Self::Output;
}
}
wrapping_shift_impl!(WrappingPow, wrapping_pow, u8);
wrapping_shift_impl!(WrappingPow, wrapping_pow, u16);
wrapping_shift_impl!(WrappingPow, wrapping_pow, u32);
wrapping_shift_impl!(WrappingPow, wrapping_pow, u64);
wrapping_shift_impl!(WrappingPow, wrapping_pow, usize);
wrapping_shift_impl!(WrappingPow, wrapping_pow, u128);
wrapping_shift_impl!(WrappingPow, wrapping_pow, i8);
wrapping_shift_impl!(WrappingPow, wrapping_pow, i16);
wrapping_shift_impl!(WrappingPow, wrapping_pow, i32);
wrapping_shift_impl!(WrappingPow, wrapping_pow, i64);
wrapping_shift_impl!(WrappingPow, wrapping_pow, isize);
wrapping_shift_impl!(WrappingPow, wrapping_pow, i128);
#[test]
fn test_wrapping_div_rem_abs_pow() {
assert_eq!(WrappingDiv::wrapping_div(i8::MIN, -1), i8::MIN);
assert_eq!(WrappingDiv::wrapping_div(100u8, 7), 14);
assert_eq!(WrappingRem::wrapping_rem(i8::MIN, -1), 0);
assert_eq!(WrappingRem::wrapping_rem(100u8, 7), 2);
assert_eq!(WrappingAbs::wrapping_abs(i16::MIN), i16::MIN);
assert_eq!(WrappingAbs::wrapping_abs(-7i16), 7);
assert_eq!(WrappingPow::wrapping_pow(3i8, 5), -13);
assert_eq!(WrappingPow::wrapping_pow(2u16, 16), 0);
}
impl<T: WrappingAdd<Output = T>> WrappingAdd for Wrapping<T> {
type Output = Wrapping<T>;
fn wrapping_add(self, v: Self) -> Self {
Wrapping(self.0.wrapping_add(v.0))
}
}
impl<T: WrappingSub<Output = T>> WrappingSub for Wrapping<T> {
type Output = Wrapping<T>;
fn wrapping_sub(self, v: Self) -> Self {
Wrapping(self.0.wrapping_sub(v.0))
}
}
impl<T: WrappingMul<Output = T>> WrappingMul for Wrapping<T> {
type Output = Wrapping<T>;
fn wrapping_mul(self, v: Self) -> Self {
Wrapping(self.0.wrapping_mul(v.0))
}
}
impl<T: WrappingNeg<Output = T>> WrappingNeg for Wrapping<T> {
type Output = Wrapping<T>;
fn wrapping_neg(self) -> Self {
Wrapping(self.0.wrapping_neg())
}
}
impl<T: WrappingShl<Output = T>> WrappingShl for Wrapping<T> {
type Output = Wrapping<T>;
fn wrapping_shl(self, rhs: u32) -> Self {
Wrapping(self.0.wrapping_shl(rhs))
}
}
impl<T: WrappingShr<Output = T>> WrappingShr for Wrapping<T> {
type Output = Wrapping<T>;
fn wrapping_shr(self, rhs: u32) -> Self {
Wrapping(self.0.wrapping_shr(rhs))
}
}
#[test]
fn test_wrapping_traits() {
fn wrapping_add<T: WrappingAdd<Output = T>>(a: T, b: T) -> T {
a.wrapping_add(b)
}
fn wrapping_sub<T: WrappingSub<Output = T>>(a: T, b: T) -> T {
a.wrapping_sub(b)
}
fn wrapping_mul<T: WrappingMul<Output = T>>(a: T, b: T) -> T {
a.wrapping_mul(b)
}
fn wrapping_neg<T: WrappingNeg<Output = T>>(a: T) -> T {
a.wrapping_neg()
}
fn wrapping_shl<T: WrappingShl<Output = T>>(a: T, b: u32) -> T {
a.wrapping_shl(b)
}
fn wrapping_shr<T: WrappingShr<Output = T>>(a: T, b: u32) -> T {
a.wrapping_shr(b)
}
assert_eq!(wrapping_add(255, 1), 0u8);
assert_eq!(wrapping_sub(0, 1), 255u8);
assert_eq!(wrapping_mul(255, 2), 254u8);
assert_eq!(wrapping_neg(255), 1u8);
assert_eq!(wrapping_shl(255, 8), 255u8);
assert_eq!(wrapping_shr(255, 8), 255u8);
assert_eq!(wrapping_add(255, 1), (Wrapping(255u8) + Wrapping(1u8)).0);
assert_eq!(wrapping_sub(0, 1), (Wrapping(0u8) - Wrapping(1u8)).0);
assert_eq!(wrapping_mul(255, 2), (Wrapping(255u8) * Wrapping(2u8)).0);
assert_eq!(wrapping_neg(255), (-Wrapping(255u8)).0);
assert_eq!(wrapping_shl(255, 8), (Wrapping(255u8) << 8).0);
assert_eq!(wrapping_shr(255, 8), (Wrapping(255u8) >> 8).0);
}
#[test]
fn wrapping_is_wrappingadd() {
fn require_wrappingadd<T: WrappingAdd<Output = T>>(_: &T) {}
require_wrappingadd(&Wrapping(42));
}
#[test]
fn wrapping_is_wrappingsub() {
fn require_wrappingsub<T: WrappingSub<Output = T>>(_: &T) {}
require_wrappingsub(&Wrapping(42));
}
#[test]
fn wrapping_is_wrappingmul() {
fn require_wrappingmul<T: WrappingMul<Output = T>>(_: &T) {}
require_wrappingmul(&Wrapping(42));
}
#[test]
fn wrapping_is_wrappingneg() {
fn require_wrappingneg<T: WrappingNeg<Output = T>>(_: &T) {}
require_wrappingneg(&Wrapping(42));
}
#[test]
fn wrapping_is_wrappingshl() {
fn require_wrappingshl<T: WrappingShl<Output = T>>(_: &T) {}
require_wrappingshl(&Wrapping(42));
}
#[test]
fn wrapping_is_wrappingshr() {
fn require_wrappingshr<T: WrappingShr<Output = T>>(_: &T) {}
require_wrappingshr(&Wrapping(42));
}