From: Erik Lindahl Date: Mon, 7 Jul 2014 11:43:58 +0000 (+0200) Subject: Make IEEE754 check more robust X-Git-Url: http://biod.pnpi.spb.ru/gitweb/?a=commitdiff_plain;h=ea3e8aa8bfdd6865973d09ab852a9c64a6a1d180;p=alexxy%2Fgromacs.git Make IEEE754 check more robust This change should prevent compilers from optimizing away the structure used for checking strings in the binary by also using it to produce a return values. There are now also clearer warnings, and if IEEE754 cannot be detected we fall by to using the OS versions of erf/erfc() in double precision. Fixes compiles on Power7. Change-Id: I8ed834d5b87baf33e03725d2ab93a60a76c34a12 --- diff --git a/cmake/TestFloatFormat.c b/cmake/TestFloatFormat.c index 7467f805a6..d0676d5dfa 100644 --- a/cmake/TestFloatFormat.c +++ b/cmake/TestFloatFormat.c @@ -3,8 +3,10 @@ main() { /* Check that a double is 8 bytes - compilation dies if it isnt */ extern char xyz [sizeof(double) == 8 ? 1 : -1]; + int i; + double d; - double abc [] = { + double abc [10] = { /* Zero-terminated strings encoded as floating-point numbers */ /* "GROMACSX" in ascii */ (double) 3.80279098314984902657e+35 , (double) 0.0, @@ -18,5 +20,13 @@ main() (double) -5.22995989424860458374e+10 , (double) 0.0, }; - return 0; + /* Make sure some compilers do not optimize away the entire structure + * with floating-point data by using it to produce a return value. + */ + for(i=0,d=0;i<10;i++) + { + d+=abc[i]; + } + + return (d==12345.0); } diff --git a/cmake/gmxTestFloatFormat.cmake b/cmake/gmxTestFloatFormat.cmake index 00671573fc..e20c49d8c4 100644 --- a/cmake/gmxTestFloatFormat.cmake +++ b/cmake/gmxTestFloatFormat.cmake @@ -104,6 +104,7 @@ MACRO(GMX_TEST_FLOAT_FORMAT FP_IEEE754 FP_BIG_ENDIAN_BYTE FP_BIG_ENDIAN_WORD) MESSAGE(STATUS "Checking floating point format - IEEE754 (LE byte, LE word)") else() MESSAGE(STATUS "Checking floating point format - unknown") + MESSAGE(WARNING "Cannot detect your floating-point format. It is extremely unlikely to be anything else than IEEE754, but if we do not know the endian we need to rely on your OS providing the math functions erfd() and erfcd() rather than using our built-in ones.") endif() ENDIF() ENDMACRO(GMX_TEST_FLOAT_FORMAT FP_IEEE754 FP_BIG_ENDIAN_BYTE FP_BIG_ENDIAN_WORD) diff --git a/src/gromacs/math/utilities.c b/src/gromacs/math/utilities.c index ec2b9d4e60..ca46dbff25 100644 --- a/src/gromacs/math/utilities.c +++ b/src/gromacs/math/utilities.c @@ -173,6 +173,7 @@ static const double double gmx_erfd(double x) { +#ifdef GMX_FLOAT_FORMAT_IEEE754 gmx_int32_t hx, ix, i; double R, S, P, Q, s, y, z, r; @@ -185,9 +186,7 @@ double gmx_erfd(double x) conv.d = x; - /* In release-4-6 and later branches, only the test for - * GMX_IEEE754_BIG_ENDIAN_WORD_ORDER will be required. */ -#if defined(IEEE754_BIG_ENDIAN_WORD_ORDER) || defined(GMX_IEEE754_BIG_ENDIAN_WORD_ORDER) +#ifdef GMX_IEEE754_BIG_ENDIAN_WORD_ORDER hx = conv.i[0]; #else hx = conv.i[1]; @@ -263,9 +262,7 @@ double gmx_erfd(double x) conv.d = x; - /* In release-4-6 and later branches, only the test for - * GMX_IEEE754_BIG_ENDIAN_WORD_ORDER will be required. */ -#if defined(IEEE754_BIG_ENDIAN_WORD_ORDER) || defined(GMX_IEEE754_BIG_ENDIAN_WORD_ORDER) +#ifdef GMX_IEEE754_BIG_ENDIAN_WORD_ORDER conv.i[1] = 0; #else conv.i[0] = 0; @@ -282,11 +279,16 @@ double gmx_erfd(double x) { return r/x-one; } +#else + /* No IEEE754 information. We need to trust that the OS provides erf(). */ + return erf(x); +#endif } double gmx_erfcd(double x) { +#ifdef GMX_FLOAT_FORMAT_IEEE754 gmx_int32_t hx, ix; double R, S, P, Q, s, y, z, r; @@ -299,9 +301,7 @@ double gmx_erfcd(double x) conv.d = x; - /* In release-4-6 and later branches, only the test for - * GMX_IEEE754_BIG_ENDIAN_WORD_ORDER will be required. */ -#if defined(IEEE754_BIG_ENDIAN_WORD_ORDER) || defined(GMX_IEEE754_BIG_ENDIAN_WORD_ORDER) +#ifdef GMX_IEEE754_BIG_ENDIAN_WORD_ORDER hx = conv.i[0]; #else hx = conv.i[1]; @@ -379,9 +379,7 @@ double gmx_erfcd(double x) conv.d = x; - /* In release-4-6 and later branches, only the test for - * GMX_IEEE754_BIG_ENDIAN_WORD_ORDER will be required. */ -#if defined(IEEE754_BIG_ENDIAN_WORD_ORDER) || defined(GMX_IEEE754_BIG_ENDIAN_WORD_ORDER) +#ifdef GMX_IEEE754_BIG_ENDIAN_WORD_ORDER conv.i[1] = 0; #else conv.i[0] = 0; @@ -411,6 +409,10 @@ double gmx_erfcd(double x) return two-tiny; } } +#else + /* No IEEE754 information. We need to trust that the OS provides erfc(). */ + return erfc(x); +#endif }