pub use crate::support::{CastFrom, CastInto, Int, MinInt};
pub trait DInt: MinInt {
type H: HInt<D = Self>;
fn lo(self) -> Self::H;
fn hi(self) -> Self::H;
fn lo_hi(self) -> (Self::H, Self::H) {
(self.lo(), self.hi())
}
fn from_lo_hi(lo: Self::H, hi: Self::H) -> Self {
lo.zero_widen() | hi.widen_hi()
}
}
pub trait HInt: Int {
type D: DInt<H = Self> + MinInt;
fn widen(self) -> Self::D;
fn zero_widen(self) -> Self::D;
fn widen_hi(self) -> Self::D;
fn zero_widen_mul(self, rhs: Self) -> Self::D;
fn widen_mul(self, rhs: Self) -> Self::D;
}
macro_rules! impl_d_int {
($($X:ident $D:ident),*) => {
$(
impl DInt for $D {
type H = $X;
fn lo(self) -> Self::H {
self as $X
}
fn hi(self) -> Self::H {
(self >> <$X as MinInt>::BITS) as $X
}
}
)*
};
}
macro_rules! impl_h_int {
($($H:ident $uH:ident $X:ident),*) => {
$(
impl HInt for $H {
type D = $X;
fn widen(self) -> Self::D {
self as $X
}
fn zero_widen(self) -> Self::D {
(self as $uH) as $X
}
fn zero_widen_mul(self, rhs: Self) -> Self::D {
self.zero_widen().wrapping_mul(rhs.zero_widen())
}
fn widen_mul(self, rhs: Self) -> Self::D {
self.widen().wrapping_mul(rhs.widen())
}
fn widen_hi(self) -> Self::D {
(self as $X) << <Self as MinInt>::BITS
}
}
)*
};
}
impl_d_int!(u8 u16, u16 u32, u32 u64, u64 u128, i8 i16, i16 i32, i32 i64, i64 i128);
impl_h_int!(
u8 u8 u16,
u16 u16 u32,
u32 u32 u64,
u64 u64 u128,
i8 u8 i16,
i16 u16 i32,
i32 u32 i64,
i64 u64 i128
);