Make IEEE754 check more robust
authorErik Lindahl <erik@kth.se>
Mon, 7 Jul 2014 11:43:58 +0000 (13:43 +0200)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Tue, 8 Jul 2014 18:53:10 +0000 (20:53 +0200)
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

cmake/TestFloatFormat.c
cmake/gmxTestFloatFormat.cmake
src/gromacs/math/utilities.c

index 7467f805a6b5cc4ebc47bfb5d39e19059e1d913a..d0676d5dfa7eb0bde37309de2c721cc9df32e9b0 100644 (file)
@@ -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);
 }
index 00671573fc875732032f309c6718ba06d209cbe3..e20c49d8c4f8a37946f69345311a3437f40ad945 100644 (file)
@@ -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)
index ec2b9d4e60a09cb1ab0b5056a2dcfcd7681510ad..ca46dbff25003a9ea74b219d5085a6b03dd79042 100644 (file)
@@ -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
 }