use super::FloatCastHelper;
use crate::Exponent;
use crate::cast::CastFrom;
use crate::helpers::{Bits, One};
use core::ops::{Add, Shr};
pub trait CastFloatFromUintHelper: Bits + Shr<Exponent, Output = Self> {
fn trailing_zeros(self) -> Exponent;
}
macro_rules! impl_cast_float_from_uint_helper_for_primitive_uint {
($($uint: ty), *) => {
$(
impl CastFloatFromUintHelper for $uint {
#[inline]
fn trailing_zeros(self) -> Exponent {
Self::trailing_zeros(self) as Exponent
}
}
)*
};
}
impl_cast_float_from_uint_helper_for_primitive_uint!(u8, u16, u32, u64, u128, usize);
pub fn cast_float_from_uint<U, F>(value: U) -> F
where
F: FloatCastHelper,
F::SignedExp: TryFrom<Exponent> + One + Add<F::SignedExp, Output = F::SignedExp>,
F::Mantissa: CastFrom<U> + One,
U: CastFloatFromUintHelper + Copy,
{
let bit_width = value.bit_width(); if bit_width == 0 {
return F::ZERO;
}
let exponent = bit_width - 1;
match F::SignedExp::try_from(exponent) {
Ok(mut exponent) => {
if exponent >= F::MAX_EXP {
return F::INFINITY;
}
let mantissa = if bit_width <= F::MANTISSA_DIGITS {
F::Mantissa::cast_from(value) << (F::MANTISSA_DIGITS - bit_width)
} else {
let shift = bit_width - F::MANTISSA_DIGITS;
let gte_half = value.bit(shift - 1); let mut shifted_mantissa = F::Mantissa::cast_from(value >> shift);
if gte_half && (shifted_mantissa.bit(0) || value.trailing_zeros() != shift - 1) {
shifted_mantissa = shifted_mantissa + F::Mantissa::ONE;
if shifted_mantissa.bit(F::MANTISSA_DIGITS) {
shifted_mantissa = shifted_mantissa >> 1;
exponent = exponent + F::SignedExp::ONE;
}
}
shifted_mantissa
};
F::from_signed_parts(false, exponent, mantissa)
}
_ => F::INFINITY, }
}