diff --git a/src/lib.rs b/src/lib.rs index 5cbe8d8..09bc502 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,6 +38,23 @@ impl F8 { assert!(e <= E_STORAGE_MAX); Self((e << M_BITS) | m) } + + fn merge_unbias(in_m: u8, in_e: i8) -> Self { + if in_m == 0 { + return Self(0); + } + let base_e = in_m.ilog2() as u8; + let off = base_e as i8 - M_BITS as i8; + let m = if off >= 0 { in_m >> off } else { in_m << -off }; + let e = (base_e as i8) + in_e + (E_BIAS as i8); + if e < 0 { + return Self(0); + } + if e > E_STORAGE_MAX as i8 { + return Self(0xff); + } + Self::merge(m & M_STORAGE_MAX, e as u8) + } } impl std::fmt::Binary for F8 { @@ -134,6 +151,21 @@ mod tests { } } + #[test] + fn test_merge() { + assert_eq!(f32::from(F8::merge_unbias(0, 0)), 0.0); + assert_eq!(f32::from(F8::merge_unbias(1, 0)), 1.0); + assert_eq!(f32::from(F8::merge_unbias(1, 1)), 2.0); + assert_eq!(f32::from(F8::merge_unbias(1, -1)), 0.5); + assert_eq!(f32::from(F8::merge_unbias(3, 0)), 3.0); + assert_eq!(f32::from(F8::merge_unbias(3, 1)), 6.0); + assert_eq!(f32::from(F8::merge_unbias(3, -1)), 1.5); + assert_eq!( + f32::from(F8::merge_unbias(EXACT_INT_MAX, 0)), + EXACT_INT_MAX as f32 + ); + } + #[test] fn test_display() { fn fmt_split(m: u8, e: u8) -> String {