use core::ops::{Add, Neg, Sub};
use crate::Num;
pub const fn max(a: u32, b: u32) -> u32 {
if a > b {
a
} else {
b
}
}
macro_rules! fp_impl {
($Name:ident, $Iname:ident) => {
use crate::$Name;
impl<const B0: u32, const B1: u32, const S: i32> Add<$Name<B1, S>> for $Name<B0, S>
where
[(); (max(B0, B1) + 1) as usize]:,
{
type Output = $Name<{ max(B0, B1) + 1 }, S>;
fn add(self: $Name<B0, S>, other: $Name<B1, S>) -> Self::Output {
unsafe {
Self::Output::new_unchecked(
self.raw().unchecked_add(other.raw()),
)
}
}
}
impl<const B0: u32, const B1: u32, const S: i32> Sub<$Name<B1, S>> for $Name<B0, S>
where
[(); (max(B0, B1) + 1) as usize]:,
{
type Output = $Iname<{ max(B0, B1) + 1 }, S>;
fn sub(self: $Name<B0, S>, other: $Name<B1, S>) -> Self::Output {
let self_raw = self.raw() as <Self::Output as Num>::Raw;
let other_raw = other.raw() as <Self::Output as Num>::Raw;
unsafe {
Self::Output::new_unchecked(
self_raw.unchecked_sub(other_raw),
)
}
}
}
impl<const B: u32, const S: i32> Neg for $Name<B, S>
where
[(); (B + 1) as usize]:,
{
type Output = $Iname<{ B + 1 }, S>;
fn neg(self: $Name<B, S>) -> Self::Output {
unsafe { Self::Output::new_unchecked(-(self.raw() as <Self::Output as Num>::Raw)) }
}
}
};
}
fp_impl!(U8, I8);
fp_impl!(I8, I8);
fp_impl!(U16, I16);
fp_impl!(I16, I16);
fp_impl!(U32, I32);
fp_impl!(I32, I32);
fp_impl!(U64, I64);
fp_impl!(I64, I64);
fp_impl!(U128, I128);
fp_impl!(I128, I128);
fp_impl!(Usize, Isize);
fp_impl!(Isize, Isize);