diff --git a/sub_crates/rmath/src/utils.rs b/sub_crates/rmath/src/utils.rs index 051e956..7af13a3 100644 --- a/sub_crates/rmath/src/utils.rs +++ b/sub_crates/rmath/src/utils.rs @@ -1,6 +1,13 @@ const TOP_BIT: u32 = 1 << 31; /// Compute how different two floats are in ulps. +/// +/// Notes: +/// - Treats 0.0 and -0.0 as zero ulps apart, and extends the +/// implications of that to the rest of the numbers. E.g. the numbers +/// just above/below 0.0/-0.0 are only two ulps apart, not three. +/// - Infinity is one ulp past float max, and converse for -infinity. +/// - This doesn't handle NaNs in any really useful way. #[inline(always)] pub fn ulp_diff(a: f32, b: f32) -> u32 { let a = a.to_bits(); @@ -34,12 +41,20 @@ mod tests { assert_eq!(ulp_diff(0.0, 0.0), 0); assert_eq!(ulp_diff(0.0, -0.0), 0); assert_eq!(ulp_diff(1.0, 2.0), 1 << 23); - assert_eq!(ulp_diff(0.0, f32::from_bits(0.0f32.to_bits() + 1)), 1); - assert_eq!(ulp_diff(-0.0, f32::from_bits(0.0f32.to_bits() + 1)), 1); + assert_eq!(ulp_diff(2.0, 4.0), 1 << 23); + assert_eq!(ulp_diff(-1.0, -2.0), 1 << 23); + assert_eq!(ulp_diff(-2.0, -4.0), 1 << 23); + assert_eq!(ulp_diff(-1.0, 1.0), 0x7f000000); + assert_eq!(ulp_diff(0.0, 1.0), 0x3f800000); + assert_eq!(ulp_diff(-0.0, 1.0), 0x3f800000); + assert_eq!(ulp_diff(0.0, -1.0), 0x3f800000); + assert_eq!(ulp_diff(-0.0, -1.0), 0x3f800000); assert_eq!( ulp_diff(std::f32::INFINITY, -std::f32::INFINITY), 0xff000000 ); + assert_eq!(ulp_diff(0.0, f32::from_bits(0.0f32.to_bits() + 1)), 1); + assert_eq!(ulp_diff(-0.0, f32::from_bits(0.0f32.to_bits() + 1)), 1); } #[test]