pub(crate) const F8E5_ZERO: u8 = 0x00;
pub(crate) const F8E5_NEG_ZERO: u8 = 0x80;
pub(crate) const F8E5_ONE: u8 = 0x3c;
pub(crate) fn f8_e5_to_f32(bits: u8) -> f32 {
let sign = ((bits >> 7) & 1) as u32;
let exp = ((bits >> 2) & 0x1f) as u32;
let mant = (bits & 0x3) as u32;
match exp {
0 => {
let m = mant as f32 / 65536.0;
if sign == 1 { -m } else { m }
}
0x1f => {
let f = if mant == 0 { f32::INFINITY } else { f32::NAN };
if sign == 1 { -f } else { f }
}
_ => f32::from_bits((sign << 31) | ((exp + 127 - 15) << 23) | (mant << 21)),
}
}
pub(crate) fn f8_e5_from_f32(v: f32) -> u8 {
if v.is_nan() {
return 0x7e; }
let sign = if v.is_sign_negative() { 0x80u8 } else { 0 };
let a = v.abs();
if a.is_infinite() {
return sign | 0x7c; }
if a == 0.0 {
return sign;
}
let n = a.to_bits();
let unbiased_exp = ((n >> 23) & 0xff) as i32 - 127;
let man = n & 0x7fffff;
let biased = unbiased_exp + 15;
if biased >= 0x1f {
return sign | 0x7c; }
if biased <= 0 {
let sub = (a * 65536.0).round() as u32;
return sign | (sub.min(3) as u8);
}
let mut mant2 = man >> 21;
let mut exp = biased as u32;
if (man >> 20) & 1 == 1 {
mant2 += 1;
if mant2 == 4 {
mant2 = 0;
exp += 1;
if exp >= 0x1f {
return sign | 0x7c;
}
}
}
sign | ((exp as u8) << 2) | (mant2 as u8)
}
pub(crate) fn f8_e5_is_zero(bits: u8) -> bool {
bits == F8E5_ZERO || bits == F8E5_NEG_ZERO
}