From 037109ad8ea150fd5652d79e11dd3a6e7aaff9e0 Mon Sep 17 00:00:00 2001 From: Mike Boutin Date: Fri, 27 Jan 2023 13:49:30 -0500 Subject: [PATCH 1/2] Disable comparing subnormal values on ARM for `f32` and `f64`. Replaces dca2031 where specific tests were disabled. With the change `f{32|64}::Test` implementation considers zero and subnormal values equal. Part of #392. --- src/si/area.rs | 2 -- src/si/volume.rs | 2 -- src/tests/mod.rs | 44 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/src/si/area.rs b/src/si/area.rs index 58a5cccf..cab19d3b 100644 --- a/src/si/area.rs +++ b/src/si/area.rs @@ -84,8 +84,6 @@ mod tests { } #[test] - // #392: Disable tests on ARM until issues with floating point behavior can be resolved. - #[cfg(not(target_arch = "arm"))] fn check_units() { // Values too large for f32. if TypeId::of::() == TypeId::of::() { diff --git a/src/si/volume.rs b/src/si/volume.rs index 4939e878..309e02f4 100644 --- a/src/si/volume.rs +++ b/src/si/volume.rs @@ -157,8 +157,6 @@ mod tests { } #[test] - // #392: Disable tests on ARM until issues with floating point behavior can be resolved. - #[cfg(not(target_arch = "arm"))] fn check_units() { // Values too large for f32. if TypeId::of::() == TypeId::of::() { diff --git a/src/tests/mod.rs b/src/tests/mod.rs index c6e705f0..c0d69846 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -108,8 +108,14 @@ mod test_trait { impl super::super::Test for V { /// Assert that `lhs` and `rhs` are exactly equal. fn assert_eq(lhs: &Self, rhs: &Self) { - match (lhs.is_nan(), rhs.is_nan()) { - (true, true) => {} + use crate::lib::num::FpCategory::*; + + match (lhs.classify(), rhs.classify()) { + (Nan, Nan) => {} + // #392: Disable on ARM until floating point behavior issues can be resolved. + #[cfg(target_arch = "arm")] + (Zero, Subnormal) + | (Subnormal, Zero) => {} _ => { assert_eq!(lhs, rhs); } } } @@ -117,8 +123,14 @@ mod test_trait { /// Assert that `lhs` and `rhs` are approximately equal for floating point types or /// exactly equal for other types. fn assert_approx_eq(lhs: &Self, rhs: &Self) { - match (lhs.is_nan(), rhs.is_nan()) { - (true, true) => {} + use crate::lib::num::FpCategory::*; + + match (lhs.classify(), rhs.classify()) { + (Nan, Nan) => {} + // #392: Disable on ARM until floating point behavior issues can be resolved. + #[cfg(target_arch = "arm")] + (Zero, Subnormal) + | (Subnormal, Zero) => {} _ => { assert_ulps_eq!(lhs, rhs, epsilon = EPS_FACTOR * V::epsilon(), max_ulps = ULPS); @@ -128,15 +140,31 @@ mod test_trait { /// Exactly compare `lhs` and `rhs` and return the result. fn eq(lhs: &Self, rhs: &Self) -> bool { - (lhs.is_nan() && rhs.is_nan()) - || lhs == rhs + use crate::lib::num::FpCategory::*; + + match (lhs.classify(), rhs.classify()) { + (Nan, Nan) => true, + // #392: Disable on ARM until floating point behavior issues can be resolved. + #[cfg(target_arch = "arm")] + (Zero, Subnormal) + | (Subnormal, Zero) => true, + _ => lhs == rhs, + } } /// Approximately compare `lhs` and `rhs` for floating point types or exactly compare /// for other types and return the result. fn approx_eq(lhs: &Self, rhs: &Self) -> bool { - (lhs.is_nan() && rhs.is_nan()) - || ulps_eq!(lhs, rhs, epsilon = EPS_FACTOR * V::epsilon(), max_ulps = ULPS) + use crate::lib::num::FpCategory::*; + + match (lhs.classify(), rhs.classify()) { + (Nan, Nan) => true, + // #392: Disable on ARM until floating point behavior issues can be resolved. + #[cfg(target_arch = "arm")] + (Zero, Subnormal) + | (Subnormal, Zero) => true, + _ => ulps_eq!(lhs, rhs, epsilon = EPS_FACTOR * V::epsilon(), max_ulps = ULPS), + } } } } From 5315dbf3681dc40763a3b01a6a8c0eb7a7d3b5b8 Mon Sep 17 00:00:00 2001 From: Mike Boutin Date: Fri, 27 Jan 2023 14:34:24 -0500 Subject: [PATCH 2/2] Disable comparing subnormal values on ARM for `Complex32` and `Complex64`. Part of #392. --- src/tests/mod.rs | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/src/tests/mod.rs b/src/tests/mod.rs index c0d69846..b31c99a8 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -178,49 +178,33 @@ mod test_trait { storage_types! { types: Complex; - use crate::num::Float; - - // const EPSILON: VV = 64.0 * VV::epsilon(); //error[E0015]; calls in constants are limited... - const EPS_FACTOR: VV = 0.5; - const ULPS: u32 = 3; + use super::super::Test; - impl super::super::Test for V { + impl Test for V { /// Assert that `lhs` and `rhs` are exactly equal. fn assert_eq(lhs: &Self, rhs: &Self) { - match (lhs.is_nan(), rhs.is_nan()) { - (true, true) => {} - _ => { assert_eq!(lhs, rhs); } - } + Test::assert_eq(&lhs.re, &rhs.re); + Test::assert_eq(&lhs.im, &rhs.im); } /// Assert that `lhs` and `rhs` are approximately equal for floating point types or /// exactly equal for other types. fn assert_approx_eq(lhs: &Self, rhs: &Self) { - match (lhs.is_nan(), rhs.is_nan()) { - (true, true) => {} - _ => { - assert_ulps_eq!(lhs.re, rhs.re, epsilon = EPS_FACTOR * VV::epsilon(), - max_ulps = ULPS); - assert_ulps_eq!(lhs.im, rhs.im, epsilon = EPS_FACTOR * VV::epsilon(), - max_ulps = ULPS); - } - } + Test::assert_approx_eq(&lhs.re, &rhs.re); + Test::assert_approx_eq(&lhs.im, &rhs.im); } /// Exactly compare `lhs` and `rhs` and return the result. fn eq(lhs: &Self, rhs: &Self) -> bool { - (lhs.is_nan() && rhs.is_nan()) - || lhs == rhs + Test::eq(&lhs.re, &rhs.re) + && Test::eq(&lhs.im, &rhs.im) } /// Approximately compare `lhs` and `rhs` for floating point types or exactly compare /// for other types and return the result. fn approx_eq(lhs: &Self, rhs: &Self) -> bool { - (lhs.is_nan() && rhs.is_nan()) - || ulps_eq!(lhs.re, rhs.re, - epsilon = EPS_FACTOR * VV::epsilon(), max_ulps = ULPS) - || ulps_eq!(lhs.im, rhs.im, - epsilon = EPS_FACTOR * VV::epsilon(), max_ulps = ULPS) + Test::approx_eq(&lhs.re, &rhs.re) + && Test::approx_eq(&lhs.im, &rhs.im) } } }