Added tests for denormal and underflow for simd exp()
authorErik Lindahl <erik@kth.se>
Thu, 31 Jul 2014 14:32:30 +0000 (16:32 +0200)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Fri, 1 Aug 2014 21:20:20 +0000 (23:20 +0200)
The SIMD math functions are not expected to handle
the denormal range correctly, but it should at least
be clamped to zero rather than producing garbage
values. No changes required to the math function,
so it appears to pass these tests as-is.

Change-Id: I841c2948c81f6b62f42e60ff30ffd5e4f77926fa

src/gromacs/simd/tests/simd_math.cpp

index a064ae1fae16a5879f3fc80eb19b71e893459aee..b892070c45a7a6b7c6a1f1d4bb1c9ed004435012 100644 (file)
@@ -281,6 +281,23 @@ TEST_F(SimdMathTest, gmxSimdExp2R)
 {
     setRange(-100, 100);
     GMX_EXPECT_SIMD_FUNC_NEAR(ref_exp2, gmx_simd_exp2_r);
+
+    // We do not care about the SIMD implementation getting denormal values right,
+    // but they must be clamped to zero rather than producing garbage.
+    // Check by setting the absolute tolerance to machine precision.
+    setAbsTol(GMX_REAL_EPS);
+
+    // First two values will have denormal results in single, third value in double too.
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(ref_exp2(-150.0), ref_exp2(-300.0), ref_exp2(-1050.0)),
+                              gmx_simd_exp2_r(setSimdRealFrom3R(-150.0, -300.0, -1050.0)));
+
+    // Reset absolute tolerance to enforce ULP checking
+    setAbsTol(0.0);
+
+    // Make sure that underflowing values are set to zero.
+    // First two values underflow in single, third value in double too.
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(ref_exp2(-200.0), ref_exp2(-600.0), ref_exp2(-1500.0)),
+                              gmx_simd_exp2_r(setSimdRealFrom3R(-200.0, -600.0, -1500.0)));
 }
 #endif
 
@@ -294,6 +311,22 @@ TEST_F(SimdMathTest, gmxSimdExpR)
 {
     setRange(-75, 75);
     GMX_EXPECT_SIMD_FUNC_NEAR(ref_exp, gmx_simd_exp_r);
+
+    // We do not care about the SIMD implementation getting denormal values right,
+    // but they must be clamped to zero rather than producing garbage.
+    // Check by setting the absolute tolerance to machine precision.
+    setAbsTol(GMX_REAL_EPS);
+    // First two values will have denormal results in single, third value in double too.
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(ref_exp(-90.0), ref_exp(-100.0), ref_exp(-725.0)),
+                              gmx_simd_exp_r(setSimdRealFrom3R(-90.0, -100.0, -725.0)));
+
+    // Reset absolute tolerance to enforce ULP checking
+    setAbsTol(0.0);
+
+    // Make sure that underflowing values are set to zero.
+    // First two values underflow in single, third value in double too.
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(ref_exp(-150.0), ref_exp(-300.0), ref_exp(-800.0)),
+                              gmx_simd_exp_r(setSimdRealFrom3R(-150.0, -300.0, -800.0)));
 }
 
 /*! \brief Function wrapper for erf(x), with argument/return in default Gromacs precision.