use num::Float;
use std::{
fmt::{Display, Formatter, Result},
num::FpCategory,
};
pub struct HexFloat<T: Float>(pub T);
impl<T: Float> Display for HexFloat<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let sign = if self.0.is_sign_negative() { "-" } else { "" };
match self.0.classify() {
FpCategory::Nan => return write!(f, "NaN"),
FpCategory::Infinite => return write!(f, "{sign}Infinity"),
FpCategory::Zero => return write!(f, "{sign}0.0"),
_ => (),
};
let (significand, mut exponent, _) = self.0.integer_decode();
let mut hex_sig = format!("{significand:x}");
while hex_sig.ends_with('0') {
hex_sig.pop();
exponent += 4;
}
match hex_sig.len() {
0 => write!(f, "{sign}0.0"),
1 => write!(f, "{sign}0x{hex_sig}.0p{exponent}"),
len => write!(
f,
"{sign}0x{}.{}p{}",
hex_sig.chars().next().unwrap(),
&hex_sig[1..],
exponent + 4 * (len as i16 - 1)
),
}
}
}
#[cfg(test)]
mod hex_float_tests {
use crate::hexfloat::HexFloat;
use num::Float;
#[test]
fn test() {
assert_eq!(format!("{}", HexFloat(1.0)), "0x1.0p0");
assert_eq!(format!("{}", HexFloat(123.0)), "0x1.ecp6");
assert_eq!(format!("{}", HexFloat(1.0 / 16.0)), "0x1.0p-4");
assert_eq!(format!("{}", HexFloat(f64::infinity())), "Infinity");
assert_eq!(format!("{}", HexFloat(f64::neg_infinity())), "-Infinity");
assert_eq!(format!("{}", HexFloat(f64::nan())), "NaN");
assert_eq!(format!("{}", HexFloat(0.0)), "0.0");
assert_eq!(format!("{}", HexFloat(f64::neg_zero())), "-0.0");
}
}