123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- use std::ops::{Add, Sub, Mul};
- use std::num::Wrapping;
- macro_rules! wrapping_impl {
- ($trait_name:ident, $method:ident, $t:ty) => {
- impl $trait_name for $t {
- #[inline]
- fn $method(&self, v: &Self) -> Self {
- <$t>::$method(*self, *v)
- }
- }
- };
- ($trait_name:ident, $method:ident, $t:ty, $rhs:ty) => {
- impl $trait_name<$rhs> for $t {
- #[inline]
- fn $method(&self, v: &$rhs) -> Self {
- <$t>::$method(*self, *v)
- }
- }
- }
- }
- /// Performs addition that wraps around on overflow.
- pub trait WrappingAdd: Sized + Add<Self, Output=Self> {
- /// Wrapping (modular) addition. Computes `self + other`, wrapping around at the boundary of
- /// the type.
- fn wrapping_add(&self, v: &Self) -> Self;
- }
- 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, 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);
- /// Performs subtraction that wraps around on overflow.
- pub trait WrappingSub: Sized + Sub<Self, Output=Self> {
- /// Wrapping (modular) subtraction. Computes `self - other`, wrapping around at the boundary
- /// of the type.
- fn wrapping_sub(&self, v: &Self) -> Self;
- }
- 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, 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);
- /// Performs multiplication that wraps around on overflow.
- pub trait WrappingMul: Sized + Mul<Self, Output=Self> {
- /// Wrapping (modular) multiplication. Computes `self * other`, wrapping around at the boundary
- /// of the type.
- fn wrapping_mul(&self, v: &Self) -> Self;
- }
- 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, 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);
- // Well this is a bit funny, but all the more appropriate.
- impl<T: WrappingAdd> WrappingAdd for Wrapping<T> where Wrapping<T>: Add<Output = Wrapping<T>> {
- fn wrapping_add(&self, v: &Self) -> Self {
- Wrapping(self.0.wrapping_add(&v.0))
- }
- }
- impl<T: WrappingSub> WrappingSub for Wrapping<T> where Wrapping<T>: Sub<Output = Wrapping<T>> {
- fn wrapping_sub(&self, v: &Self) -> Self {
- Wrapping(self.0.wrapping_sub(&v.0))
- }
- }
- impl<T: WrappingMul> WrappingMul for Wrapping<T> where Wrapping<T>: Mul<Output = Wrapping<T>> {
- fn wrapping_mul(&self, v: &Self) -> Self {
- Wrapping(self.0.wrapping_mul(&v.0))
- }
- }
- #[test]
- fn test_wrapping_traits() {
- fn wrapping_add<T: WrappingAdd>(a: T, b: T) -> T { a.wrapping_add(&b) }
- fn wrapping_sub<T: WrappingSub>(a: T, b: T) -> T { a.wrapping_sub(&b) }
- fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T { a.wrapping_mul(&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_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);
- }
- #[test]
- fn wrapping_is_wrappingadd() {
- fn require_wrappingadd<T: WrappingAdd>(_: &T) {}
- require_wrappingadd(&Wrapping(42));
- }
- #[test]
- fn wrapping_is_wrappingsub() {
- fn require_wrappingsub<T: WrappingSub>(_: &T) {}
- require_wrappingsub(&Wrapping(42));
- }
- #[test]
- fn wrapping_is_wrappingmul() {
- fn require_wrappingmul<T: WrappingMul>(_: &T) {}
- require_wrappingmul(&Wrapping(42));
- }
|