use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
pub trait Num:
Default
+ PartialEq
+ PartialOrd
+ Copy
+ AddAssign
+ MulAssign
+ SubAssign
+ DivAssign
+ Add<Output = Self>
+ Mul<Output = Self>
+ Sub<Output = Self>
+ Div<Output = Self>
{
fn zero() -> Self;
fn one() -> Self;
fn two() -> Self;
fn four() -> Self;
fn get_max(self, b: Self) -> Self;
fn get_min(self, b: Self) -> Self;
fn saturating_sub(self, rhs: Self) -> Self;
fn saturating_add(self, rhs: Self) -> Self;
fn from_f32(value: f32) -> Self;
fn to_f32(self) -> f32;
fn round_up(self) -> Self;
fn round_down(self) -> Self;
}
mod macros {
use super::Num;
macro_rules! impl_int_num {
($t:ty) => {
impl Num for $t {
#[inline(always)]
fn zero() -> Self {
0
}
#[inline(always)]
fn one() -> Self {
1
}
#[inline(always)]
fn two() -> Self {
2
}
#[inline(always)]
fn four() -> Self {
4
}
#[inline(always)]
fn get_max(self, b: Self) -> Self {
self.max(b)
}
#[inline(always)]
fn get_min(self, b: Self) -> Self {
self.min(b)
}
#[inline(always)]
fn saturating_sub(self, rhs: Self) -> Self {
self.saturating_sub(rhs)
}
#[inline(always)]
fn saturating_add(self, rhs: Self) -> Self {
self.saturating_add(rhs)
}
#[inline(always)]
fn from_f32(value: f32) -> Self {
value as Self
}
#[inline(always)]
fn to_f32(self) -> f32 {
self as f32
}
#[inline(always)]
fn round_up(self) -> Self {
self
}
fn round_down(self) -> Self {
self
}
}
};
}
macro_rules! impl_float_num {
($t:ty) => {
impl Num for $t {
#[inline(always)]
fn zero() -> Self {
0.0
}
#[inline(always)]
fn one() -> Self {
1.0
}
#[inline(always)]
fn two() -> Self {
2.0
}
#[inline(always)]
fn four() -> Self {
4.0
}
#[inline(always)]
fn get_max(self, b: Self) -> Self {
self.max(b)
}
#[inline(always)]
fn get_min(self, b: Self) -> Self {
self.min(b)
}
#[inline(always)]
fn saturating_sub(self, rhs: Self) -> Self {
if rhs > self { Self::zero() } else { self - rhs }
}
#[inline(always)]
fn saturating_add(self, rhs: Self) -> Self {
self + rhs
}
#[inline(always)]
fn from_f32(value: f32) -> Self {
value as Self
}
#[inline(always)]
fn to_f32(self) -> f32 {
self as f32
}
#[inline(always)]
fn round_down(self) -> Self {
(self as i64) as Self
}
#[inline(always)]
fn round_up(self) -> Self {
(self as i64 + 1) as Self
}
}
};
}
impl_int_num!(u8);
impl_int_num!(u16);
impl_int_num!(u32);
impl_int_num!(u64);
impl_int_num!(usize);
impl_int_num!(i8);
impl_int_num!(i16);
impl_int_num!(i32);
impl_int_num!(i64);
impl_int_num!(isize);
impl_float_num!(f32);
impl_float_num!(f64);
}