use std::ops::{Add, Sub};
pub trait RotaryAdd<T: Add<Output = T> + Sub<Output = T> + PartialEq + Copy> {
fn rotary_add(&self, other: &T) -> T;
fn rotary_sub(&self, other: &T) -> T;
}
macro_rules! impl_rotary_add {
($t:ty,$u:ty, $max:expr) => {
impl RotaryAdd<$t> for $t {
fn rotary_add(&self, other: &$t) -> $t {
let diff = $max - *other;
if *self < diff {
*self + *other
} else {
let radix = $max as $u + 1;
let result = *self as $u + *other as $u;
(result % radix) as $t
}
}
fn rotary_sub(&self, other: &$t) -> $t {
if *self < *other {
let radix = $max as $u + 1;
let result = *other as $u - *self as $u;
(radix - result) as $t
} else {
*self - *other
}
}
}
};
}
impl_rotary_add!(u8, u16, u8::MAX);
impl_rotary_add!(u16, u32, u16::MAX);
impl_rotary_add!(u32, u64, u32::MAX);