pub(crate) const fn f64_to_fp4(x: f64) -> u8 {
let (
fp4_exp_bias,
fp4_significand_bits,
fp4_mantissa_mask,
fp4_mindenorm_o2,
fp4_overflow_threshold,
fp4_maxnorm,
fp4_minnorm,
) = (
1u16, 2u64, 0x1u8, 0x3FD0_0000_0000_0000u64, 0x4018_0000_0000_0000u64, 0x7u8, 0x3FF0_0000_0000_0000u64, );
let xbits = x.to_bits();
let absx = xbits & 0x7FFF_FFFF_FFFF_FFFFu64;
const DP_INF_BITS: u64 = 0x7FF0_0000_0000_0000u64;
let mut sign = ((xbits >> 63) as u8) << 3;
let exp_field = ((xbits >> 52) & 0x7FF) as u16;
let exp = (exp_field as i16 - 1023 + fp4_exp_bias as i16) as i8;
let mantissa = ((xbits >> (53 - fp4_significand_bits)) as u8) & fp4_mantissa_mask;
let fp4_dp_half_ulp: u64 = 1u64 << (53 - fp4_significand_bits - 1);
let mut res: u8;
if absx <= fp4_mindenorm_o2 {
res = 0;
} else if absx > fp4_overflow_threshold {
if absx > DP_INF_BITS {
sign = 0; }
res = fp4_maxnorm;
} else if absx >= fp4_minnorm {
res = ((exp as u8) << (fp4_significand_bits - 1)) | mantissa;
let round = xbits & ((fp4_dp_half_ulp << 1) - 1);
let halfway = fp4_dp_half_ulp;
if round > halfway || (round == halfway && (mantissa & 1) != 0) {
res = res.wrapping_add(1);
}
} else {
let shift = if exp >= 1 { 0 } else { (1 - exp) as u8 };
let denorm_mant = mantissa | (1 << (fp4_significand_bits - 1));
res = denorm_mant >> shift;
let round_mask = (fp4_dp_half_ulp << (shift as u64 + 1)) - 1;
let round = (xbits | (1u64 << 52)) & round_mask;
if round > (fp4_dp_half_ulp << shift)
|| (round == (fp4_dp_half_ulp << shift) && (res & 1) != 0)
{
res = res.wrapping_add(1);
}
}
res | sign
}
pub(crate) fn fp4_to_f64(fp4_bits: u8) -> f64 {
let sign = (fp4_bits >> 3) & 1;
let exp_bits = (fp4_bits >> 1) & 0x3;
let mant_bit = fp4_bits & 1;
let fp4_exp_bias = 1;
if exp_bits == 0 {
let value = mant_bit as f64 * 0.5;
if sign != 0 { -value } else { value }
} else {
let actual_exp = exp_bits as i32 - fp4_exp_bias;
let significand = 1.0 + (mant_bit as f64 * 0.5);
let value = significand * 2.0_f64.powi(actual_exp);
if sign != 0 { -value } else { value }
}
}