* To help us fund GROMACS development, we humbly ask that you cite
* the research papers on the package. Check out http://www.gromacs.org.
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+#include "gmxpre.h"
+
+#include "gromacs/simd/simd_math.h"
+
+#include "config.h"
#include <vector>
+
#include "gromacs/math/utilities.h"
-#include "gromacs/simd/simd.h"
-#include "gromacs/simd/simd_math.h"
#include "gromacs/options/basicoptions.h"
+#include "gromacs/simd/simd.h"
#include "simd.h"
public:
::testing::AssertionResult
compareSimdMathFunction(const char * refFuncExpr, const char *simdFuncExpr,
- real refFunc(real x), gmx_simd_real_t simdFunc(gmx_simd_real_t x));
+ real refFunc(real x), gmx_simd_real_t gmx_simdcall simdFunc(gmx_simd_real_t x));
};
/*! \brief Test approximate equality of SIMD vs reference version of a function.
*/
::testing::AssertionResult
SimdMathTest::compareSimdMathFunction(const char * refFuncExpr, const char *simdFuncExpr,
- real refFunc(real x), gmx_simd_real_t simdFunc(gmx_simd_real_t x))
+ real refFunc(real x), gmx_simd_real_t gmx_simdcall simdFunc(gmx_simd_real_t x))
{
std::vector<real> vx(GMX_SIMD_REAL_WIDTH);
std::vector<real> vref(GMX_SIMD_REAL_WIDTH);
}
/*! \brief Function wrapper to return first result when testing \ref gmx_simd_invsqrt_pair_r */
-gmx_simd_real_t
+gmx_simd_real_t gmx_simdcall
tst_invsqrt_pair0(gmx_simd_real_t x)
{
gmx_simd_real_t r0, r1;
}
/*! \brief Function wrapper to return second result when testing \ref gmx_simd_invsqrt_pair_r */
-gmx_simd_real_t
+gmx_simd_real_t gmx_simdcall
tst_invsqrt_pair1(gmx_simd_real_t x)
{
gmx_simd_real_t r0, r1;
{
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
{
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.