use crate::num::basic::unsigneds::PrimitiveUnsigned;
use crate::num::conversion::traits::{HasHalf, JoinHalves, SplitInHalf, WrappingFrom};
#[inline]
fn join_halves<T: From<H> + PrimitiveUnsigned, H: PrimitiveUnsigned>(upper: H, lower: H) -> T {
(T::from(upper) << H::WIDTH) | T::from(lower)
}
#[inline]
fn upper_half<T: PrimitiveUnsigned, H: PrimitiveUnsigned + WrappingFrom<T>>(x: &T) -> H {
H::wrapping_from(*x >> H::WIDTH)
}
macro_rules! impl_half_traits {
($t:ident, $ht: ident) => {
impl HasHalf for $t {
type Half = $ht;
}
impl JoinHalves for $t {
#[inline]
fn join_halves(upper: Self::Half, lower: Self::Half) -> Self {
join_halves(upper, lower)
}
}
impl SplitInHalf for $t {
#[inline]
fn lower_half(&self) -> Self::Half {
$ht::wrapping_from(*self)
}
#[inline]
fn upper_half(&self) -> Self::Half {
upper_half(self)
}
}
};
}
impl_half_traits!(u16, u8);
impl_half_traits!(u32, u16);
impl_half_traits!(u64, u32);
impl_half_traits!(u128, u64);
#[inline]
fn wide_lower_half<T: PrimitiveUnsigned>(x: T) -> T {
x.mod_power_of_2(T::WIDTH >> 1)
}
#[inline]
pub(crate) fn wide_upper_half<T: PrimitiveUnsigned>(x: T) -> T {
x >> (T::WIDTH >> 1)
}
#[inline]
pub(crate) fn wide_split_in_half<T: PrimitiveUnsigned>(x: T) -> (T, T) {
(wide_upper_half(x), wide_lower_half(x))
}
#[inline]
pub(crate) fn wide_join_halves<T: PrimitiveUnsigned>(hi: T, lo: T) -> T {
(hi << (T::WIDTH >> 1)) | lo
}