Improved SIMD test data to use all bits
authorErik Lindahl <erik@kth.se>
Thu, 25 May 2017 18:01:57 +0000 (20:01 +0200)
committerRoland Schulz <roland.schulz@intel.com>
Mon, 28 Aug 2017 20:17:57 +0000 (22:17 +0200)
The SIMD test data now uses all available bits in the
current precision floating-point numbers, to catch errors
where we lose precision or have mistakes in single/double
conversions (e.g. return values). Since some operations now
depend on the least significant bit, a few tests have been
relaxed to allow a tolerance rather than require exact
binary matching.

The new tests caught a precision loss in a reduction
function for the SIMD-mimicking scalar functions, but this
has never been used apart from testing, and should be harmless.

Fixes #2163.

Change-Id: I6d8f19d2aafeee8f42a2034c6100fcb10f6d2e81

18 files changed:
src/gromacs/simd/scalar/scalar_util.h
src/gromacs/simd/tests/CMakeLists.txt
src/gromacs/simd/tests/data.cpp [new file with mode: 0644]
src/gromacs/simd/tests/data.h [new file with mode: 0644]
src/gromacs/simd/tests/scalar.cpp
src/gromacs/simd/tests/scalar_math.cpp
src/gromacs/simd/tests/scalar_util.cpp
src/gromacs/simd/tests/simd.cpp
src/gromacs/simd/tests/simd.h
src/gromacs/simd/tests/simd4.cpp
src/gromacs/simd/tests/simd4.h
src/gromacs/simd/tests/simd4_floatingpoint.cpp
src/gromacs/simd/tests/simd4_vector_operations.cpp
src/gromacs/simd/tests/simd_floatingpoint.cpp
src/gromacs/simd/tests/simd_floatingpoint_util.cpp
src/gromacs/simd/tests/simd_integer.cpp
src/gromacs/simd/tests/simd_math.cpp
src/gromacs/simd/tests/simd_vector_operations.cpp

index 16818f49d51459a72af4608e10f2d84f1a324922..66550477f0bbb50ec85a7fef46afa5757a2b7778 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2016, by the GROMACS development team, led by
+ * Copyright (c) 2016,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -629,7 +629,7 @@ gatherLoadBySimdIntTranspose(const double *      base,
  *       write templated SIMD/non-SIMD code. For clarity it should not be used
  *       outside such code.
  */
-static inline float
+static inline double
 reduceIncr4ReturnSum(double *           m,
                      double             v0,
                      double             v1,
index dd23216959af72fda168861bd52557129a8fdaa8..2f8b30a0742135333640cbdd999011489fc6476d 100644 (file)
@@ -1,7 +1,7 @@
 #
 # This file is part of the GROMACS molecular simulation package.
 #
-# Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+# Copyright (c) 2014,2015,2016,2017, by the GROMACS development team, led by
 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
 # and including many others, as listed in the AUTHORS file in the
 # top-level source directory and at http://www.gromacs.org.
@@ -35,6 +35,7 @@
 gmx_add_unit_test(SimdUnitTests simd-test
                   bootstrap_loadstore.cpp
                  base.cpp
+                  data.cpp
                   simd.cpp
                  simd_floatingpoint.cpp
                   simd_floatingpoint_util.cpp
diff --git a/src/gromacs/simd/tests/data.cpp b/src/gromacs/simd/tests/data.cpp
new file mode 100644 (file)
index 0000000..1e3ab7b
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2014,2015,2016,2017, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+#include "gmxpre.h"
+
+#include "data.h"
+
+#include "gromacs/utility/real.h"
+
+
+namespace gmx
+{
+namespace test
+{
+
+/*! \cond internal */
+/*! \addtogroup module_simd */
+/*! \{ */
+
+// Common test data constants used both for SIMD, SIMD4, and scalar tests.
+// We both want numbers that are easy to identify with integer part from 0 to 9,
+// and to fill all digits in the mantissa and avoid identical differences
+// between adjacent numbers we add a fraction of primes.
+const real czero = 0.0;
+const real c0    = 0.0 + 1.0/3.0;
+const real c1    = 1.0 + 5.0/7.0;
+const real c2    = 2.0 + 9.0/13.0;
+const real c3    = 3.0 + 17.0/19.0;
+const real c4    = 4.0 + 23.0/29.0;
+const real c5    = 5.0 + 31.0/37.0;
+const real c6    = 6.0 + 41.0/43.0;
+const real c7    = 7.0 + 47.0/53.0;
+const real c8    = 8.0 + 59.0/61.0;
+
+/*! \} */
+/*! \endcond */
+
+} // namespace test
+
+} // namespace gmx
diff --git a/src/gromacs/simd/tests/data.h b/src/gromacs/simd/tests/data.h
new file mode 100644 (file)
index 0000000..b66abce
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the GROMACS molecular simulation package.
+ *
+ * Copyright (c) 2014,2015,2016,2017, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
+ *
+ * GROMACS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * GROMACS is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GROMACS; if not, see
+ * http://www.gnu.org/licenses, or write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
+ *
+ * If you want to redistribute modifications to GROMACS, please
+ * consider that scientific software is very special. Version
+ * control is crucial - bugs must be traceable. We will be happy to
+ * consider code for inclusion in the official distribution, but
+ * derived work must not be called official GROMACS. Details are found
+ * in the README & COPYING files - if they are missing, get the
+ * official version at http://www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org.
+ */
+#ifndef GMX_SIMD_TESTS_DATA_H
+#define GMX_SIMD_TESTS_DATA_H
+
+/*! \internal \file
+ * \brief Common test data constants for SIMD, SIMD4 and scalar tests
+ *
+ * To avoid silent bugs due to double/float truncation if we ever use the
+ * wrong return type of routines, we want to use test data that fills all
+ * available bits in either single or double precision. The values themselves
+ * are meaningless.
+ * Note that the data is used to initialize the SIMD constants, which for
+ * technical (alignment) reasons in some compilers cannot be placed inside
+ * the text fixture classes. For that reason this data cannot go in the
+ * fixtures either.
+ *
+ * \author Erik Lindahl <erik.lindahl@scilifelab.se>
+ * \ingroup module_simd
+ */
+
+#include "gromacs/utility/real.h"
+
+namespace gmx
+{
+namespace test
+{
+
+/*! \cond internal */
+/*! \addtogroup module_simd */
+/*! \{ */
+extern const real czero; //!< Value 0.0 in real precision
+extern const real c0;    //!< Random fp value using entire mantissa
+extern const real c1;    //!< Random fp value using entire mantissa
+extern const real c2;    //!< Random fp value using entire mantissa
+extern const real c3;    //!< Random fp value using entire mantissa
+extern const real c4;    //!< Random fp value using entire mantissa
+extern const real c5;    //!< Random fp value using entire mantissa
+extern const real c5;    //!< Random fp value using entire mantissa
+extern const real c6;    //!< Random fp value using entire mantissa
+extern const real c7;    //!< Random fp value using entire mantissa
+extern const real c8;    //!< Random fp value using entire mantissa
+extern const real c9;    //!< Random fp value using entire mantissa
+
+/*! \} */
+/*! \endcond */
+
+}      // namespace test
+}      // namespace gmx
+
+#endif
index 2d6418b1c25f0de1650d3caf9bc0fcbf9dd281a5..540d3b1398795aa0af7187cc792bf52fd8fecdb3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -42,6 +42,8 @@
 #include "gromacs/utility/basedefinitions.h"
 #include "gromacs/utility/real.h"
 
+#include "data.h"
+
 namespace gmx
 {
 namespace test
@@ -60,38 +62,34 @@ namespace
 
 TEST(SimdScalarTest, load)
 {
-    real ref = 1.234;
-    real val = load(&ref);
+    real val = load(&c1);
 
-    EXPECT_EQ(ref, val);
+    EXPECT_EQ(c1, val);
 }
 
 TEST(SimdScalarTest, loadU)
 {
-    real ref = 1.234;
-    real val = loadU(&ref);
+    real val = loadU(&c1);
 
-    EXPECT_EQ(ref, val);
+    EXPECT_EQ(c1, val);
 }
 
 TEST(SimdScalarTest, store)
 {
-    real ref = 1.234;
     real val;
 
-    store(&val, ref);
+    store(&val, c1);
 
-    EXPECT_EQ(ref, val);
+    EXPECT_EQ(c1, val);
 }
 
 TEST(SimdScalarTest, storeU)
 {
-    real ref = 1.234;
     real val;
 
-    store(&val, ref);
+    store(&val, c1);
 
-    EXPECT_EQ(ref, val);
+    EXPECT_EQ(c1, val);
 }
 
 TEST(SimdScalarTest, setZero)
@@ -105,61 +103,61 @@ TEST(SimdScalarTest, andNot)
 {
     real signBit = GMX_REAL_NEGZERO;
 
-    EXPECT_EQ(real(1), andNot(signBit, real(-1)));
-    EXPECT_EQ(real(2), andNot(signBit, real(2)));
+    EXPECT_EQ(c1, andNot(signBit, -c1));
+    EXPECT_EQ(c2, andNot(signBit, c2));
 }
 
 TEST(SimdScalarTest, fma)
 {
-    EXPECT_EQ(real(27), fma(real(3), real(6), real(9))); // 3*6+9=27
+    EXPECT_EQ(c1*c2+c3, fma(real(c1), real(c2), real(c3)));
 }
 
 TEST(SimdScalarTest, fms)
 {
-    EXPECT_EQ(real(9), fms(real(3), real(6), real(9))); // 3*6-9=9
+    EXPECT_EQ(c1*c2-c3, fms(c1, c2, c3));
 }
 
 TEST(SimdScalarTest, fnma)
 {
-    EXPECT_EQ(real(-9), fnma(real(3), real(6), real(9))); // -3*6+9=-9
+    EXPECT_EQ(-c1*c2+c3, fnma(c1, c2, c3));
 }
 
 TEST(SimdScalarTest, fnms)
 {
-    EXPECT_EQ(real(-27), fnms(real(3), real(6), real(9))); // -3*6-9=-27
+    EXPECT_EQ(-c1*c2-c3, fnms(c1, c2, c3));
 }
 
 TEST(SimdScalarTest, maskAdd)
 {
-    EXPECT_EQ(real(3), maskAdd(real(3), real(6), false));
-    EXPECT_EQ(real(9), maskAdd(real(3), real(6), true));
+    EXPECT_EQ(c1, maskAdd(c1, c2, false));
+    EXPECT_EQ(c1+c2, maskAdd(c1, c2, true));
 }
 
 TEST(SimdScalarTest, maskzMul)
 {
-    EXPECT_EQ(real(0), maskzMul(real(3), real(6), false));
-    EXPECT_EQ(real(18), maskzMul(real(3), real(6), true));
+    EXPECT_EQ(czero, maskzMul(c1, c2, false));
+    EXPECT_EQ(c1*c2, maskzMul(c1, c2, true));
 }
 
 TEST(SimdScalarTest, maskzFma)
 {
-    EXPECT_EQ(real(0), maskzFma(real(3), real(6), real(9), false));
-    EXPECT_EQ(real(27), maskzFma(real(3), real(6), real(9), true));
+    EXPECT_EQ(czero, maskzFma(c1, c2, c3, false));
+    EXPECT_EQ(c1*c2+c3, maskzFma(c1, c2, c3, true));
 }
 
 TEST(SimdScalarTest, abs)
 {
-    EXPECT_EQ(real(3), abs(real(-3)));
+    EXPECT_EQ(c1, abs(-c1));
 }
 
 TEST(SimdScalarTest, max)
 {
-    EXPECT_EQ(real(3), max(real(1), real(3)));
+    EXPECT_EQ(c3, max(c1, c3));
 }
 
 TEST(SimdScalarTest, min)
 {
-    EXPECT_EQ(real(1), min(real(1), real(3)));
+    EXPECT_EQ(c1, min(c1, c3));
 }
 
 TEST(SimdScalarTest, round)
@@ -180,14 +178,14 @@ TEST(SimdScalarTest, trunc)
 
 TEST(SimdScalarTest, reduce)
 {
-    EXPECT_EQ(real(5), reduce(real(5)));
+    EXPECT_EQ(c1, reduce(c1));
 }
 
 TEST(SimdScalarTest, testBits)
 {
-    EXPECT_TRUE(testBits(real(1)));
+    EXPECT_TRUE(testBits(c1));
     EXPECT_TRUE(testBits(GMX_REAL_NEGZERO));
-    EXPECT_FALSE(testBits(real(0)));
+    EXPECT_FALSE(testBits(czero));
 }
 
 TEST(SimdScalarTest, anyTrue)
@@ -198,20 +196,20 @@ TEST(SimdScalarTest, anyTrue)
 
 TEST(SimdScalarTest, selectByMask)
 {
-    EXPECT_EQ(real(5.0), selectByMask(real(5.0), true));
-    EXPECT_EQ(real(0.0), selectByMask(real(5.0), false));
+    EXPECT_EQ(c1, selectByMask(c1, true));
+    EXPECT_EQ(czero, selectByMask(c1, false));
 }
 
 TEST(SimdScalarTest, selectByNotMask)
 {
-    EXPECT_EQ(real(0.0), selectByNotMask(real(5.0), true));
-    EXPECT_EQ(real(5.0), selectByNotMask(real(5.0), false));
+    EXPECT_EQ(czero, selectByNotMask(c1, true));
+    EXPECT_EQ(c1, selectByNotMask(c1, false));
 }
 
 TEST(SimdScalarTest, blend)
 {
-    EXPECT_EQ(real(5.0), blend(real(3.0), real(5.0), true));
-    EXPECT_EQ(real(3.0), blend(real(3.0), real(5.0), false));
+    EXPECT_EQ(c2, blend(c1, c2, true));
+    EXPECT_EQ(c1, blend(c1, c2, false));
 }
 
 TEST(SimdScalarTest, cvtR2I)
index be92f2466746c554012593eb33b93e031b65cecd..df297937b31de69ed0f53dba5f2169d0e32b949f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -44,6 +44,8 @@
 
 #include "testutils/testasserts.h"
 
+#include "data.h"
+
 namespace gmx
 {
 namespace test
@@ -66,14 +68,14 @@ namespace
 
 TEST(SimdScalarMathTest, copysign)
 {
-    EXPECT_EQ(real(-4), copysign(real(4), real(-5)));
-    EXPECT_EQ(real(5), copysign(real(5), real(2)));
+    EXPECT_EQ(real(-c1), copysign(real(c1), real(-c2)));
+    EXPECT_EQ(real(c2), copysign(real(c2), real(c3)));
 }
 
 TEST(SimdScalarMathTest, invsqrtPair)
 {
-    real x0 = 1.2345;
-    real x1 = 9.8765;
+    real x0 = c1;
+    real x1 = c2;
 
     real out0, out1;
 
@@ -85,14 +87,14 @@ TEST(SimdScalarMathTest, invsqrtPair)
 
 TEST(SimdScalarMathTest, inv)
 {
-    real x0 = 1.2345;
+    real x0 = c0;
 
     EXPECT_EQ(real(1.0)/x0, inv(x0));
 }
 
 TEST(SimdScalarMathTest, maskzInvsqrt)
 {
-    real x0 = 1.2345;
+    real x0 = c0;
 
     EXPECT_EQ(invsqrt(x0), maskzInvsqrt(x0, true));
     EXPECT_EQ(real(0), maskzInvsqrt(x0, false));
@@ -100,42 +102,42 @@ TEST(SimdScalarMathTest, maskzInvsqrt)
 
 TEST(SimdScalarMathTest, log)
 {
-    real x0 = 1.2345;
+    real x0 = c0;
 
     EXPECT_EQ(std::log(x0), log(x0));
 }
 
 TEST(SimdScalarMathTest, exp2)
 {
-    real x0 = 1.2345;
+    real x0 = c0;
 
     EXPECT_EQ(std::exp2(x0), exp2(x0));
 }
 
 TEST(SimdScalarMathTest, exp)
 {
-    real x0 = 1.2345;
+    real x0 = c0;
 
     EXPECT_EQ(std::exp(x0), exp(x0));
 }
 
 TEST(SimdScalarMathTest, erf)
 {
-    real x0 = 0.51256;
+    real x0 = c0;
 
     EXPECT_EQ(std::erf(x0), erf(x0));
 }
 
 TEST(SimdScalarMathTest, erfc)
 {
-    real x0 = 0.51256;
+    real x0 = c0;
 
     EXPECT_EQ(std::erfc(x0), erfc(x0));
 }
 
 TEST(SimdScalarMathTest, sincos)
 {
-    real x0 = 0.51256;
+    real x0 = c0;
     real s, c;
 
     sincos(x0, &s, &c);
@@ -146,21 +148,21 @@ TEST(SimdScalarMathTest, sincos)
 
 TEST(SimdScalarMathTest, sin)
 {
-    real x0 = 0.51256;
+    real x0 = c0;
 
     EXPECT_EQ(std::sin(x0), sin(x0));
 }
 
 TEST(SimdScalarMathTest, cos)
 {
-    real x0 = 0.51256;
+    real x0 = c0;
 
     EXPECT_EQ(std::cos(x0), cos(x0));
 }
 
 TEST(SimdScalarMathTest, tan)
 {
-    real x0 = 0.51256;
+    real x0 = c0;
 
     EXPECT_EQ(std::tan(x0), tan(x0));
 }
@@ -168,29 +170,29 @@ TEST(SimdScalarMathTest, tan)
 
 TEST(SimdScalarMathTest, asin)
 {
-    real x0 = 0.51256;
+    real x0 = c0;
 
     EXPECT_EQ(std::asin(x0), asin(x0));
 }
 
 TEST(SimdScalarMathTest, acos)
 {
-    real x0 = 0.51256;
+    real x0 = c0;
 
     EXPECT_EQ(std::acos(x0), acos(x0));
 }
 
 TEST(SimdScalarMathTest, atan)
 {
-    real x0 = 0.51256;
+    real x0 = c0;
 
     EXPECT_EQ(std::atan(x0), atan(x0));
 }
 
 TEST(SimdScalarMathTest, atan2)
 {
-    real x = 0.5;
-    real y = std::sqrt(0.75);
+    real x = c0;
+    real y = std::sqrt(c0);
 
 
     EXPECT_EQ(std::atan2(y, x), atan2(y, x));
@@ -198,7 +200,7 @@ TEST(SimdScalarMathTest, atan2)
 
 TEST(SimdScalarMathTest, pmeForceCorrection)
 {
-    real z2 = 0.51256;
+    real z2 = c0;
 
     // Calculate reference value for z2!=0
     real z   = std::sqrt(z2);
@@ -216,7 +218,7 @@ TEST(SimdScalarMathTest, pmeForceCorrection)
 
 TEST(SimdScalarMathTest, pmePotentialCorrection)
 {
-    real z2 = 0.51256;
+    real z2 = c0;
 
     // Calculate reference value for z2!=0
     real z   = std::sqrt(z2);
@@ -238,8 +240,8 @@ TEST(SimdScalarMathTest, pmePotentialCorrection)
 
 TEST(SimdScalarMathTest, invsqrtPairSingleAccuracy)
 {
-    double x0 = 1.2345;
-    double x1 = 9.8765;
+    double x0 = c1;
+    double x1 = c2;
 
     double out0, out1;
 
@@ -251,7 +253,7 @@ TEST(SimdScalarMathTest, invsqrtPairSingleAccuracy)
 
 TEST(SimdScalarMathTest, invSingleAccuracy)
 {
-    double x0 = 1.2345;
+    double x0 = c1;
 
     EXPECT_EQ(1.0f/static_cast<float>(x0),
               static_cast<float>(invSingleAccuracy(x0)));
@@ -259,7 +261,7 @@ TEST(SimdScalarMathTest, invSingleAccuracy)
 
 TEST(SimdScalarMathTest, maskzInvsqrtSingleAccuracy)
 {
-    double x0 = 1.2345;
+    double x0 = c1;
 
     EXPECT_EQ(invsqrt(static_cast<float>(x0)),
               static_cast<float>(maskzInvsqrtSingleAccuracy(x0, true)));
@@ -269,7 +271,7 @@ TEST(SimdScalarMathTest, maskzInvsqrtSingleAccuracy)
 
 TEST(SimdScalarMathTest, logSingleAccuracy)
 {
-    double x0 = 1.2345;
+    double x0 = c1;
 
     EXPECT_EQ(std::log(static_cast<float>(x0)),
               static_cast<float>(logSingleAccuracy(x0)));
@@ -277,7 +279,7 @@ TEST(SimdScalarMathTest, logSingleAccuracy)
 
 TEST(SimdScalarMathTest, exp2SingleAccuracy)
 {
-    double x0 = 1.2345;
+    double x0 = c1;
 
     EXPECT_EQ(std::exp2(static_cast<float>(x0)),
               static_cast<float>(exp2SingleAccuracy(x0)));
@@ -285,7 +287,7 @@ TEST(SimdScalarMathTest, exp2SingleAccuracy)
 
 TEST(SimdScalarMathTest, expSingleAccuracy)
 {
-    double x0 = 1.2345;
+    double x0 = c1;
 
     EXPECT_EQ(std::exp(static_cast<float>(x0)),
               static_cast<float>(expSingleAccuracy(x0)));
@@ -293,21 +295,21 @@ TEST(SimdScalarMathTest, expSingleAccuracy)
 
 TEST(SimdScalarMathTest, erfSingleAccuracy)
 {
-    double x0 = 0.51256;
+    double x0 = c0;
 
     EXPECT_EQ(std::erf(static_cast<float>(x0)), static_cast<float>(erfSingleAccuracy(x0)));
 }
 
 TEST(SimdScalarMathTest, erfcSingleAccuracy)
 {
-    double x0 = 0.51256;
+    double x0 = c0;
 
     EXPECT_EQ(std::erfc(static_cast<float>(x0)), static_cast<float>(erfcSingleAccuracy(x0)));
 }
 
 TEST(SimdScalarMathTest, sincosSingleAccuracy)
 {
-    double x0 = 0.51256;
+    double x0 = c0;
     double s, c;
 
     sincosSingleAccuracy(x0, &s, &c);
@@ -318,7 +320,7 @@ TEST(SimdScalarMathTest, sincosSingleAccuracy)
 
 TEST(SimdScalarMathTest, sinSingleAccuracy)
 {
-    double x0 = 0.51256;
+    double x0 = c0;
 
     EXPECT_EQ(std::sin(static_cast<float>(x0)),
               static_cast<float>(sinSingleAccuracy(x0)));
@@ -326,7 +328,7 @@ TEST(SimdScalarMathTest, sinSingleAccuracy)
 
 TEST(SimdScalarMathTest, cosSingleAccuracy)
 {
-    double x0 = 0.51256;
+    double x0 = c0;
 
     EXPECT_EQ(std::cos(static_cast<float>(x0)),
               static_cast<float>(cosSingleAccuracy(x0)));
@@ -334,7 +336,7 @@ TEST(SimdScalarMathTest, cosSingleAccuracy)
 
 TEST(SimdScalarMathTest, tanSingleAccuracy)
 {
-    double x0 = 0.51256;
+    double x0 = c0;
 
     EXPECT_EQ(std::tan(static_cast<float>(x0)),
               static_cast<float>(tanSingleAccuracy(x0)));
@@ -343,7 +345,7 @@ TEST(SimdScalarMathTest, tanSingleAccuracy)
 
 TEST(SimdScalarMathTest, asinSingleAccuracy)
 {
-    double x0 = 0.51256;
+    double x0 = c0;
 
     EXPECT_EQ(std::asin(static_cast<float>(x0)),
               static_cast<float>(asinSingleAccuracy(x0)));
@@ -351,7 +353,7 @@ TEST(SimdScalarMathTest, asinSingleAccuracy)
 
 TEST(SimdScalarMathTest, acosSingleAccuracy)
 {
-    double x0 = 0.51256;
+    double x0 = c0;
 
     EXPECT_EQ(std::acos(static_cast<float>(x0)),
               static_cast<float>(acosSingleAccuracy(x0)));
@@ -359,7 +361,7 @@ TEST(SimdScalarMathTest, acosSingleAccuracy)
 
 TEST(SimdScalarMathTest, atanSingleAccuracy)
 {
-    double x0 = 0.51256;
+    double x0 = c0;
 
     EXPECT_EQ(std::atan(static_cast<float>(x0)),
               static_cast<float>(atanSingleAccuracy(x0)));
@@ -367,8 +369,8 @@ TEST(SimdScalarMathTest, atanSingleAccuracy)
 
 TEST(SimdScalarMathTest, atan2SingleAccuracy)
 {
-    double x = 0.5;
-    double y = std::sqrt(0.75);
+    double x = c0;
+    double y = std::sqrt(c0);
 
 
     EXPECT_EQ(std::atan2(static_cast<float>(y), static_cast<float>(x)),
@@ -377,7 +379,7 @@ TEST(SimdScalarMathTest, atan2SingleAccuracy)
 
 TEST(SimdScalarMathTest, pmeForceCorrectionSingleAccuracy)
 {
-    double z2 = 0.51256;
+    double z2 = c0;
 
     // Calculate reference value for z2!=0 in single precision
     float z   = std::sqrt(static_cast<float>(z2));
@@ -391,7 +393,7 @@ TEST(SimdScalarMathTest, pmeForceCorrectionSingleAccuracy)
 
 TEST(SimdScalarMathTest, pmePotentialCorrectionSingleAccuracy)
 {
-    double z2 = 0.51256;
+    double z2 = c0;
 
     // Calculate reference value for z2!=0 in single precision
     float z   = std::sqrt(static_cast<float>(z2));
index daf1e87a3e1dfaad47deace25451992dcd5e0413..76e64c78a80825e9d25defd15a5519384171392f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
 #include "gromacs/simd/simd.h"
 #include "gromacs/utility/basedefinitions.h"
 
+#include "testutils/testasserts.h"
+
+#include "data.h"
+
 namespace gmx
 {
 namespace test
@@ -55,7 +59,7 @@ namespace
 
 TEST(SimdScalarUtilTest, gatherLoadTranspose)
 {
-    real         data[8] = {1, 2, 3, 4, 5, 6, 7, 8};
+    real         data[8] = {c0, c1, c2, c3, c4, c5, c6, c7};
     std::int32_t offset  = 1;
     real         v0, v1, v2, v3;
 
@@ -74,7 +78,7 @@ TEST(SimdScalarUtilTest, gatherLoadTranspose)
 
 TEST(SimdScalarUtilTest, gatherLoadUTranspose)
 {
-    real         data[6] = {1, 2, 3, 4, 5, 6};
+    real         data[6] = {c0, c1, c2, c3, c4, c5};
     std::int32_t offset  = 1;
     real         v0, v1, v2;
 
@@ -95,33 +99,33 @@ TEST(SimdScalarUtilTest, transposeScatterStoreU)
 
     transposeScatterStoreU<3>(data, &offset, v0, v1, v2);
 
-    EXPECT_EQ(real(0.0), data[0]);
-    EXPECT_EQ(real(0.0), data[1]);
-    EXPECT_EQ(real(0.0), data[2]);
+    EXPECT_EQ(czero, data[0]);
+    EXPECT_EQ(czero, data[1]);
+    EXPECT_EQ(czero, data[2]);
     EXPECT_EQ(v0, data[3]);
     EXPECT_EQ(v1, data[4]);
     EXPECT_EQ(v2, data[5]);
-    EXPECT_EQ(real(0.0), data[6]);
-    EXPECT_EQ(real(0.0), data[7]);
-    EXPECT_EQ(real(0.0), data[8]);
+    EXPECT_EQ(czero, data[6]);
+    EXPECT_EQ(czero, data[7]);
+    EXPECT_EQ(czero, data[8]);
 }
 
 TEST(SimdScalarUtilTest, transposeScatterIncrU)
 {
     real         data[9] = {10, 20, 30, 40, 50, 60, 70, 80, 90};
     std::int32_t offset  = 1;
-    real         v0      = 1;
-    real         v1      = 2;
-    real         v2      = 3;
+    real         v0      = c1;
+    real         v1      = c2;
+    real         v2      = c3;
 
     transposeScatterIncrU<3>(data, &offset, v0, v1, v2);
 
     EXPECT_EQ(real(10), data[0]);
     EXPECT_EQ(real(20), data[1]);
     EXPECT_EQ(real(30), data[2]);
-    EXPECT_EQ(real(41), data[3]);
-    EXPECT_EQ(real(52), data[4]);
-    EXPECT_EQ(real(63), data[5]);
+    EXPECT_EQ(real(40+c1), data[3]);
+    EXPECT_EQ(real(50+c2), data[4]);
+    EXPECT_EQ(real(60+c3), data[5]);
     EXPECT_EQ(real(70), data[6]);
     EXPECT_EQ(real(80), data[7]);
     EXPECT_EQ(real(90), data[8]);
@@ -131,18 +135,18 @@ TEST(SimdScalarUtilTest, transposeScatterDecrU)
 {
     real         data[9] = {10, 20, 30, 40, 50, 60, 70, 80, 90};
     std::int32_t offset  = 1;
-    real         v0      = 1;
-    real         v1      = 2;
-    real         v2      = 3;
+    real         v0      = c1;
+    real         v1      = c2;
+    real         v2      = c3;
 
     transposeScatterDecrU<3>(data, &offset, v0, v1, v2);
 
     EXPECT_EQ(real(10), data[0]);
     EXPECT_EQ(real(20), data[1]);
     EXPECT_EQ(real(30), data[2]);
-    EXPECT_EQ(real(39), data[3]);
-    EXPECT_EQ(real(48), data[4]);
-    EXPECT_EQ(real(57), data[5]);
+    EXPECT_EQ(real(40-c1), data[3]);
+    EXPECT_EQ(real(50-c2), data[4]);
+    EXPECT_EQ(real(60-c3), data[5]);
     EXPECT_EQ(real(70), data[6]);
     EXPECT_EQ(real(80), data[7]);
     EXPECT_EQ(real(90), data[8]);
@@ -151,7 +155,7 @@ TEST(SimdScalarUtilTest, transposeScatterDecrU)
 
 TEST(SimdScalarTest, expandScalarsToTriplets)
 {
-    real scalar = 1.234;
+    real scalar = c1;
     real t0, t1, t2;
 
     expandScalarsToTriplets(scalar, &t0, &t1, &t2);
@@ -163,7 +167,7 @@ TEST(SimdScalarTest, expandScalarsToTriplets)
 
 TEST(SimdScalarUtilTest, gatherLoadBySimdIntTranspose)
 {
-    real         data[8] = {1, 2, 3, 4, 5, 6, 7, 8};
+    real         data[8] = {c0, c1, c2, c3, c4, c5, c6, c7};
     std::int32_t offset  = 1;
     real         v0, v1, v2, v3;
 
@@ -182,7 +186,7 @@ TEST(SimdScalarUtilTest, gatherLoadBySimdIntTranspose)
 
 TEST(SimdScalarUtilTest, gatherLoadUBySimdIntTranspose)
 {
-    real         data[8] = {1, 2, 3, 4, 5, 6, 7, 8};
+    real         data[8] = {c0, c1, c2, c3, c4, c5, c6, c7};
     std::int32_t offset  = 1;
     real         v0, v1;
 
@@ -195,22 +199,22 @@ TEST(SimdScalarUtilTest, gatherLoadUBySimdIntTranspose)
 TEST(SimdScalarUtilTest, reduceIncr4ReturnSum)
 {
     real data[6] = {0, 0, 0, 0, 0, 0};
-    real v0      = 1;
-    real v1      = 2;
-    real v2      = 3;
-    real v3      = 4;
+    real v0      = c1;
+    real v1      = c2;
+    real v2      = c3;
+    real v3      = c4;
     real sum;
 
     sum = reduceIncr4ReturnSum(data+1, v0, v1, v2, v3);
 
-    EXPECT_EQ(real(0.0), data[0]);
+    EXPECT_EQ(czero, data[0]);
     EXPECT_EQ(v0, data[1]);
     EXPECT_EQ(v1, data[2]);
     EXPECT_EQ(v2, data[3]);
     EXPECT_EQ(v3, data[4]);
-    EXPECT_EQ(real(0.0), data[5]);
+    EXPECT_EQ(czero, data[5]);
 
-    EXPECT_EQ(real(v0+v1+v2+v3), sum);
+    EXPECT_REAL_EQ_TOL(real(v0+v1+v2+v3), sum, defaultRealTolerance());
 }
 
 /*! \} */
index dd56b0d4255a61e064b34bba98986bb894f91f24..6aa0fa04ff311658760d41b9d77ebf203ca1ebfc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -64,29 +64,48 @@ namespace test
  * them in a single place makes sure they are consistent.
  */
 #if GMX_SIMD_HAVE_REAL
-const SimdReal rSimd_1_2_3    = setSimdRealFrom3R(1, 2, 3);
-const SimdReal rSimd_4_5_6    = setSimdRealFrom3R(4, 5, 6);
-const SimdReal rSimd_7_8_9    = setSimdRealFrom3R(7, 8, 9);
-const SimdReal rSimd_5_7_9    = setSimdRealFrom3R(5, 7, 9);
-const SimdReal rSimd_m1_m2_m3 = setSimdRealFrom3R(-1, -2, -3);
-const SimdReal rSimd_3_1_4    = setSimdRealFrom3R(3, 1, 4);
-const SimdReal rSimd_m3_m1_m4 = setSimdRealFrom3R(-3, -1, -4);
-const SimdReal rSimd_2p25     = setSimdRealFrom1R(2.25);
-const SimdReal rSimd_3p25     = setSimdRealFrom1R(3.25);
-const SimdReal rSimd_3p75     = setSimdRealFrom1R(3.75);
+const SimdReal rSimd_c0c1c2 = setSimdRealFrom3R( c0, c1, c2);
+const SimdReal rSimd_c3c4c5 = setSimdRealFrom3R( c3, c4, c5);
+const SimdReal rSimd_c6c7c8 = setSimdRealFrom3R( c6, c7, c8);
+const SimdReal rSimd_c3c0c4 = setSimdRealFrom3R( c3, c0, c4);
+const SimdReal rSimd_c4c6c8 = setSimdRealFrom3R( c4, c6, c8);
+const SimdReal rSimd_c7c2c3 = setSimdRealFrom3R( c7, c2, c3);
+const SimdReal rSimd_m0m1m2 = setSimdRealFrom3R(-c0, -c1, -c2);
+const SimdReal rSimd_m3m0m4 = setSimdRealFrom3R(-c3, -c0, -c4);
+
+const SimdReal rSimd_2p25     = setSimdRealFrom1R( 2.25);
+const SimdReal rSimd_3p25     = setSimdRealFrom1R( 3.25);
+const SimdReal rSimd_3p75     = setSimdRealFrom1R( 3.75);
 const SimdReal rSimd_m2p25    = setSimdRealFrom1R(-2.25);
 const SimdReal rSimd_m3p25    = setSimdRealFrom1R(-3.25);
 const SimdReal rSimd_m3p75    = setSimdRealFrom1R(-3.75);
 const SimdReal rSimd_Exp      = setSimdRealFrom3R( 1.4055235171027452623914516e+18,
                                                    5.3057102734253445623914516e-13,
                                                    -2.1057102745623934534514516e+16);
-#    if GMX_SIMD_HAVE_DOUBLE && GMX_DOUBLE
+#if GMX_SIMD_HAVE_DOUBLE && GMX_DOUBLE
 // Make sure we also test exponents outside single precision when we use double
 const SimdReal rSimd_ExpDouble = setSimdRealFrom3R( 6.287393598732017379054414e+176,
                                                     8.794495252903116023030553e-140,
                                                     -3.637060701570496477655022e+202);
-#    endif
-#endif  // GMX_SIMD_HAVE_REAL
+#endif  // GMX_SIMD_HAVE_DOUBLE && GMX_DOUBLE
+
+#if GMX_SIMD_HAVE_LOGICAL
+// The numbers below all have exponent (2^0), which will not change with AND/OR operations.
+// We also leave the last part of the mantissa as zeros, to avoid rounding issues in the compiler
+#if GMX_DOUBLE
+const SimdReal rSimd_logicalA         = setSimdRealFrom1R(1.3333333332557231188); // mantissa 01010101010101010101010101010101
+const SimdReal rSimd_logicalB         = setSimdRealFrom1R(1.7999999998137354851); // mantissa 11001100110011001100110011001100
+const SimdReal rSimd_logicalResultAnd = setSimdRealFrom1R(1.266666666604578495);  // mantissa 01000100010001000100010001000100
+const SimdReal rSimd_logicalResultOr  = setSimdRealFrom1R(1.8666666664648801088); // mantissa 11011101110111011101110111011101
+#else                                                                             // GMX_DOUBLE
+const SimdReal rSimd_logicalA         = setSimdRealFrom1R(1.3333282470703125);    // mantissa 0101010101010101
+const SimdReal rSimd_logicalB         = setSimdRealFrom1R(1.79998779296875);      // mantissa 1100110011001100
+const SimdReal rSimd_logicalResultAnd = setSimdRealFrom1R(1.26666259765625);      // mantissa 0100010001000100
+const SimdReal rSimd_logicalResultOr  = setSimdRealFrom1R(1.8666534423828125);    // mantissa 1101110111011101
+#endif                                                                            // GMX_DOUBLE
+#endif                                                                            // GMX_SIMD_HAVE_LOGICAL
+
+#endif                                                                            // GMX_SIMD_HAVE_REAL
 #if GMX_SIMD_HAVE_INT32_ARITHMETICS
 const SimdInt32 iSimd_1_2_3      = setSimdIntFrom3I(1, 2, 3);
 const SimdInt32 iSimd_4_5_6      = setSimdIntFrom3I(4, 5, 6);
index 978a3dfa2da45874e088a57003c7552dc93c0450..f4aac8d657cdd8839d7c00df6aae367fdb4ad6c9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -81,6 +81,7 @@
 #include "gromacs/simd/simd.h"
 
 #include "base.h"
+#include "data.h"
 
 #if GMX_SIMD
 
@@ -108,13 +109,15 @@ namespace test
  * them in a single place makes sure they are consistent.
  */
 #if GMX_SIMD_HAVE_REAL
-extern const SimdReal rSimd_1_2_3;     //!< Generic (different) fp values.
-extern const SimdReal rSimd_4_5_6;     //!< Generic (different) fp values.
-extern const SimdReal rSimd_7_8_9;     //!< Generic (different) fp values.
-extern const SimdReal rSimd_5_7_9;     //!< rSimd_1_2_3 + rSimd_4_5_6.
-extern const SimdReal rSimd_m1_m2_m3;  //!< Generic negative floating-point values.
-extern const SimdReal rSimd_3_1_4;     //!< Used to test min/max.
-extern const SimdReal rSimd_m3_m1_m4;  //!< negative rSimd_3_1_4.
+extern const SimdReal rSimd_c0c1c2;    //!< c0,c1,c2 repeated
+extern const SimdReal rSimd_c3c4c5;    //!< c3,c4,c5 repeated
+extern const SimdReal rSimd_c6c7c8;    //!< c6,c7,c8 repeated
+extern const SimdReal rSimd_c3c0c4;    //!< c3,c0,c4 repeated
+extern const SimdReal rSimd_c4c6c8;    //!< c4,c6,c8 repeated
+extern const SimdReal rSimd_c7c2c3;    //!< c7,c2,c3 repeated
+extern const SimdReal rSimd_m0m1m2;    //!< -c0,-c1,-c2 repeated
+extern const SimdReal rSimd_m3m0m4;    //!< -c3,-c0,-c4 repeated
+
 extern const SimdReal rSimd_2p25;      //!< Value that rounds down.
 extern const SimdReal rSimd_3p25;      //!< Value that rounds down.
 extern const SimdReal rSimd_3p75;      //!< Value that rounds up.
@@ -123,6 +126,14 @@ extern const SimdReal rSimd_m3p25;     //!< Negative value that rounds up.
 extern const SimdReal rSimd_m3p75;     //!< Negative value that rounds down.
 //! Three large floating-point values whose exponents are >32.
 extern const SimdReal rSimd_Exp;
+
+#if GMX_SIMD_HAVE_LOGICAL
+extern const SimdReal rSimd_logicalA;         //!< Bit pattern to test logical ops
+extern const SimdReal rSimd_logicalB;         //!< Bit pattern to test logical ops
+extern const SimdReal rSimd_logicalResultOr;  //!< Result or bitwise 'or' of A and B
+extern const SimdReal rSimd_logicalResultAnd; //!< Result or bitwise 'and' of A and B
+#endif                                        // GMX_SIMD_HAVE_LOGICAL
+
 #    if GMX_SIMD_HAVE_DOUBLE && GMX_DOUBLE
 // Make sure we also test exponents outside single precision when we use double
 extern const SimdReal rSimd_ExpDouble;
index c50f8db6a2f99ad46043578d796b569b3753d3a0..edb66badf06bc5dceca67bfb37352965ee630b5d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -39,6 +39,8 @@
 #include "gromacs/simd/simd.h"
 #include "gromacs/utility/basedefinitions.h"
 
+#include "data.h"
+
 #if GMX_SIMD
 
 namespace gmx
@@ -52,26 +54,34 @@ namespace test
 
 #if GMX_SIMD4_HAVE_REAL
 
-const Simd4Real rSimd4_1_2_3    = setSimd4RealFrom3R(1, 2, 3);
-const Simd4Real rSimd4_4_5_6    = setSimd4RealFrom3R(4, 5, 6);
-const Simd4Real rSimd4_7_8_9    = setSimd4RealFrom3R(7, 8, 9);
-const Simd4Real rSimd4_5_7_9    = setSimd4RealFrom3R(5, 7, 9);
-const Simd4Real rSimd4_m1_m2_m3 = setSimd4RealFrom3R(-1, -2, -3);
-const Simd4Real rSimd4_3_1_4    = setSimd4RealFrom3R(3, 1, 4);
-const Simd4Real rSimd4_m3_m1_m4 = setSimd4RealFrom3R(-3, -1, -4);
+const Simd4Real rSimd4_c0c1c2   = setSimd4RealFrom3R( c0, c1, c2);
+const Simd4Real rSimd4_c3c4c5   = setSimd4RealFrom3R( c3, c4, c5);
+const Simd4Real rSimd4_c6c7c8   = setSimd4RealFrom3R( c6, c7, c8);
+const Simd4Real rSimd4_c3c0c4   = setSimd4RealFrom3R( c3, c0, c4);
+const Simd4Real rSimd4_c4c6c8   = setSimd4RealFrom3R( c4, c6, c8);
+const Simd4Real rSimd4_c7c2c3   = setSimd4RealFrom3R( c7, c2, c3);
+const Simd4Real rSimd4_m0m1m2   = setSimd4RealFrom3R(-c0, -c1, -c2);
+const Simd4Real rSimd4_m3m0m4   = setSimd4RealFrom3R(-c3, -c0, -c4);
 const Simd4Real rSimd4_2p25     = setSimd4RealFrom1R(2.25);
 const Simd4Real rSimd4_3p75     = setSimd4RealFrom1R(3.75);
 const Simd4Real rSimd4_m2p25    = setSimd4RealFrom1R(-2.25);
 const Simd4Real rSimd4_m3p75    = setSimd4RealFrom1R(-3.75);
-const Simd4Real rSimd4_Exp      = setSimd4RealFrom3R( 1.4055235171027452623914516e+18,
-                                                      5.3057102734253445623914516e-13,
-                                                      -2.1057102745623934534514516e+16);
-#    if GMX_SIMD_HAVE_DOUBLE && GMX_DOUBLE
-// Make sure we also test exponents outside single precision when we use double
-const Simd4Real  rSimd_ExpDouble = setSimd4RealFrom3R( 6.287393598732017379054414e+176,
-                                                       8.794495252903116023030553e-140,
-                                                       -3.637060701570496477655022e+202);
-#    endif
+
+#if GMX_SIMD_HAVE_LOGICAL
+// The numbers below all have exponent (2^0), which will not change with AND/OR operations.
+// We also leave the last part of the mantissa as zeros, to avoid rounding issues in the compiler
+#if GMX_DOUBLE
+const Simd4Real rSimd4_logicalA         = setSimd4RealFrom1R(1.3333333332557231188); // mantissa 01010101010101010101010101010101
+const Simd4Real rSimd4_logicalB         = setSimd4RealFrom1R(1.7999999998137354851); // mantissa 11001100110011001100110011001100
+const Simd4Real rSimd4_logicalResultAnd = setSimd4RealFrom1R(1.266666666604578495);  // mantissa 01000100010001000100010001000100
+const Simd4Real rSimd4_logicalResultOr  = setSimd4RealFrom1R(1.8666666664648801088); // mantissa 11011101110111011101110111011101
+#else                                                                                // GMX_DOUBLE
+const Simd4Real rSimd4_logicalA         = setSimd4RealFrom1R(1.3333282470703125);    // mantissa 0101010101010101
+const Simd4Real rSimd4_logicalB         = setSimd4RealFrom1R(1.79998779296875);      // mantissa 1100110011001100
+const Simd4Real rSimd4_logicalResultAnd = setSimd4RealFrom1R(1.26666259765625);      // mantissa 0100010001000100
+const Simd4Real rSimd4_logicalResultOr  = setSimd4RealFrom1R(1.8666534423828125);    // mantissa 1101110111011101
+#endif                                                                               // GMX_DOUBLE
+#endif                                                                               // GMX_SIMD_HAVE_LOGICAL
 
 ::std::vector<real>
 simd4Real2Vector(const Simd4Real simd4)
index 4432227cf75368ae766f648bb5339ff8c5905795..4d4eecde531a5b824ff9d4edb2a7a1cb89b6f5c3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -54,6 +54,7 @@
 #include "gromacs/simd/simd.h"
 
 #include "base.h"
+#include "data.h"
 
 #if GMX_SIMD
 
@@ -67,29 +68,34 @@ namespace test
 /*! \{ */
 
 #if GMX_SIMD4_HAVE_REAL
-extern const Simd4Real rSimd4_1_2_3;     //!< Generic (different) fp values.
-extern const Simd4Real rSimd4_4_5_6;     //!< Generic (different) fp values.
-extern const Simd4Real rSimd4_7_8_9;     //!< Generic (different) fp values.
-extern const Simd4Real rSimd4_5_7_9;     //!< rSimd_1_2_3 + rSimd_4_5_6.
-extern const Simd4Real rSimd4_m1_m2_m3;  //!< Generic negative fp values.
-extern const Simd4Real rSimd4_3_1_4;     //!< Used to test min/max.
-extern const Simd4Real rSimd4_m3_m1_m4;  //!< negative rSimd_3_1_4.
+extern const Simd4Real rSimd4_c0c1c2;    //!< c0,c1,c2 repeated
+extern const Simd4Real rSimd4_c3c4c5;    //!< c3,c4,c5 repeated
+extern const Simd4Real rSimd4_c6c7c8;    //!< c6,c7,c8 repeated
+extern const Simd4Real rSimd4_c3c0c4;    //!< c3,c0,c4 repeated
+extern const Simd4Real rSimd4_c4c6c8;    //!< c4,c6,c8 repeated
+extern const Simd4Real rSimd4_c7c2c3;    //!< c7,c2,c3 repeated
+extern const Simd4Real rSimd4_m0m1m2;    //!< -c0,-c1,-c2 repeated
+extern const Simd4Real rSimd4_m3m0m4;    //!< -c3,-c0,-c4 repeated
 extern const Simd4Real rSimd4_2p25;      //!< Value that rounds down.
 extern const Simd4Real rSimd4_3p75;      //!< Value that rounds up.
 extern const Simd4Real rSimd4_m2p25;     //!< Negative value that rounds up.
 extern const Simd4Real rSimd4_m3p75;     //!< Negative value that rounds down.
 //! Three large floating-point values whose exponents are >32.
 extern const Simd4Real rSimd4_Exp;
-#    if GMX_SIMD_HAVE_DOUBLE && GMX_DOUBLE
-// Make sure we also test exponents outside single precision when we use double
-extern const Simd4Real rSimd4_ExpDouble;
-#    endif
-extern const Simd4Real rSimd4_Bits1; //!< Pattern F0 repeated to fill single/double.
-extern const Simd4Real rSimd4_Bits2; //!< Pattern CC repeated to fill single/double.
-extern const Simd4Real rSimd4_Bits3; //!< Pattern C0 repeated to fill single/double.
-extern const Simd4Real rSimd4_Bits4; //!< Pattern 0C repeated to fill single/double.
-extern const Simd4Real rSimd4_Bits5; //!< Pattern FC repeated to fill single/double.
-extern const Simd4Real rSimd4_Bits6; //!< Pattern 3C repeated to fill single/double.
+
+#if GMX_SIMD_HAVE_LOGICAL
+extern const Simd4Real rSimd4_logicalA;         //!< Bit pattern to test logical ops
+extern const Simd4Real rSimd4_logicalB;         //!< Bit pattern to test logical ops
+extern const Simd4Real rSimd4_logicalResultOr;  //!< Result or bitwise 'or' of A and B
+extern const Simd4Real rSimd4_logicalResultAnd; //!< Result or bitwise 'and' of A and B
+#endif                                          // GMX_SIMD_HAVE_LOGICAL
+
+extern const Simd4Real rSimd4_Bits1;            //!< Pattern F0 repeated to fill single/double.
+extern const Simd4Real rSimd4_Bits2;            //!< Pattern CC repeated to fill single/double.
+extern const Simd4Real rSimd4_Bits3;            //!< Pattern C0 repeated to fill single/double.
+extern const Simd4Real rSimd4_Bits4;            //!< Pattern 0C repeated to fill single/double.
+extern const Simd4Real rSimd4_Bits5;            //!< Pattern FC repeated to fill single/double.
+extern const Simd4Real rSimd4_Bits6;            //!< Pattern 3C repeated to fill single/double.
 
 /*! \internal
  * \brief
index 3705aab566b99c524fd2a83f2fdf1fe2fbbdc171..b2300ec8be733abe5c03a77103b17332224c47ad 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -40,6 +40,9 @@
 #include "gromacs/simd/simd.h"
 #include "gromacs/utility/basedefinitions.h"
 
+#include "testutils/testasserts.h"
+
+#include "data.h"
 #include "simd4.h"
 
 #if GMX_SIMD
@@ -67,75 +70,79 @@ TEST_F(Simd4FloatingpointTest, setZero)
 
 TEST_F(Simd4FloatingpointTest, set)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom1R(1.0), Simd4Real(1.0));
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom1R(c1), Simd4Real(c1));
 }
 
 TEST_F(Simd4FloatingpointTest, add)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_5_7_9, rSimd4_1_2_3 + rSimd4_4_5_6); // 1+4=5, 2+5=7, 3+6=9
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(c0 + c3, c1 + c4, c2 + c5 ),
+                             rSimd4_c0c1c2 + rSimd4_c3c4c5);
+
 }
 
 TEST_F(Simd4FloatingpointTest, sub)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_4_5_6, rSimd4_5_7_9 - rSimd4_1_2_3); // 5-1=4, 7-2=5, 9-3=6
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(c0 - c3, c1 - c4, c2 - c5 ),
+                             rSimd4_c0c1c2 - rSimd4_c3c4c5);
 }
 
 TEST_F(Simd4FloatingpointTest, mul)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(4, 10, 18), rSimd4_1_2_3 * rSimd4_4_5_6);
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(c0 * c3, c1 * c4, c2 * c5 ),
+                             rSimd4_c0c1c2 * rSimd4_c3c4c5);
 }
 
 TEST_F(Simd4FloatingpointTest, fma)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(11, 18, 27), fma(rSimd4_1_2_3, rSimd4_4_5_6, rSimd4_7_8_9)); // 1*4+7, etc.
+    // The last bit of FMA operations depends on hardware, so we don't require exact match
+    GMX_EXPECT_SIMD4_REAL_NEAR(setSimd4RealFrom3R(c0 * c3 + c6, c1 * c4 + c7, c2 * c5 + c8),
+                               fma(rSimd4_c0c1c2, rSimd4_c3c4c5, rSimd4_c6c7c8));
 }
 
 TEST_F(Simd4FloatingpointTest, fms)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(-3, 2, 9), fms(rSimd4_1_2_3, rSimd4_4_5_6, rSimd4_7_8_9)); // 1*4-7, etc.
+    // The last bit of FMA operations depends on hardware, so we don't require exact match
+    GMX_EXPECT_SIMD4_REAL_NEAR(setSimd4RealFrom3R(c0 * c3 - c6, c1 * c4 - c7, c2 * c5 - c8),
+                               fms(rSimd4_c0c1c2, rSimd4_c3c4c5, rSimd4_c6c7c8));
 }
 
 TEST_F(Simd4FloatingpointTest, fnma)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(3, -2, -9), fnma(rSimd4_1_2_3, rSimd4_4_5_6, rSimd4_7_8_9)); // -1*4+7, etc.
+    // The last bit of FMA operations depends on hardware, so we don't require exact match
+    GMX_EXPECT_SIMD4_REAL_NEAR(setSimd4RealFrom3R(c6 - c0 * c3, c7 - c1 * c4, c8 - c2 * c5),
+                               fnma(rSimd4_c0c1c2, rSimd4_c3c4c5, rSimd4_c6c7c8));
 }
 
 TEST_F(Simd4FloatingpointTest, fnms)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(-11, -18, -27), fnms(rSimd4_1_2_3, rSimd4_4_5_6, rSimd4_7_8_9)); // -1*4-7, etc.
+    // The last bit of FMA operations depends on hardware, so we don't require exact match
+    GMX_EXPECT_SIMD4_REAL_NEAR(setSimd4RealFrom3R(-c0 * c3 - c6, -c1 * c4 - c7, -c2 * c5 - c8),
+                               fnms(rSimd4_c0c1c2, rSimd4_c3c4c5, rSimd4_c6c7c8));
 }
 
 TEST_F(Simd4FloatingpointTest, abs)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_1_2_3, abs(rSimd4_1_2_3));    // fabs(x)=x
-    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_1_2_3, abs(rSimd4_m1_m2_m3)); // fabs(-x)=x
+    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_c0c1c2, abs(rSimd4_c0c1c2)); // fabs(x)=x
+    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_c0c1c2, abs(rSimd4_m0m1m2)); // fabs(-x)=x
 }
 
 TEST_F(Simd4FloatingpointTest, neg)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_m1_m2_m3, -rSimd4_1_2_3);   // fneg(x)=-x
-    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_1_2_3,   -rSimd4_m1_m2_m3); // fneg(-x)=x
+    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_m0m1m2, -(rSimd4_c0c1c2)); // fneg(x)=-x
+    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_c0c1c2, -(rSimd4_m0m1m2)); // fneg(-x)=x
 }
 
 #if GMX_SIMD_HAVE_LOGICAL
-/* 1.3333282470703125 has mantissa 0101010101010101 (followed by zeros)
- * 1.79998779296875   has mantissa 1100110011001100 (followed by zeros)
- * 1.26666259765625   has mantissa 0100010001000100 (followed by zeros)
- * 1.8666534423828125 has mantissa 1101110111011101 (followed by zeros)
- *
- * Since all of them have the same exponent (2^0), the exponent will
- * not change with AND or OR operations.
- */
 TEST_F(Simd4FloatingpointTest, and)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom1R(1.26666259765625),
-                             Simd4Real(1.3333282470703125) & Simd4Real(1.79998779296875));
+    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_logicalResultAnd,
+                             (rSimd4_logicalA & rSimd4_logicalB));
 }
 
 TEST_F(Simd4FloatingpointTest, or)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom1R(1.8666534423828125),
-                             Simd4Real(1.3333282470703125) | Simd4Real(1.79998779296875));
+    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_logicalResultOr,
+                             (rSimd4_logicalA | rSimd4_logicalB));
 }
 
 TEST_F(Simd4FloatingpointTest, xor)
@@ -144,8 +151,8 @@ TEST_F(Simd4FloatingpointTest, xor)
      * in only the sign bit being set. We then use this bit change the sign of
      * different numbers.
      */
-    Simd4Real signbit = Simd4Real(1.5) ^ Simd4Real(-1.5);
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(-1, 2, -3), signbit ^ setSimd4RealFrom3R(1, -2, 3));
+    Simd4Real signbit = Simd4Real(c1) ^ Simd4Real(-c1);
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(-c2, c3, -c4), signbit ^ setSimd4RealFrom3R(c2, -c3, c4));
 }
 
 TEST_F(Simd4FloatingpointTest, andNot)
@@ -153,26 +160,26 @@ TEST_F(Simd4FloatingpointTest, andNot)
     /* Use xor (which we already tested, so fix that first if both tests fail)
      * to extract the sign bit, and then use andnot to take absolute values.
      */
-    Simd4Real signbit = Simd4Real(1.5) ^ Simd4Real(-1.5);
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(1, 2, 3), andNot(signbit, setSimd4RealFrom3R(-1, 2, -3)));
+    Simd4Real signbit = Simd4Real(c1) ^ Simd4Real(-c1);
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(c2, c3, c4), andNot(signbit, setSimd4RealFrom3R(-c2, c3, -c4)));
 }
 
 #endif
 
 TEST_F(Simd4FloatingpointTest, max)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(3, 2, 4), max(rSimd4_1_2_3, rSimd4_3_1_4));
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(3, 2, 4), max(rSimd4_3_1_4, rSimd4_1_2_3));
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(-1, -1, -3), max(rSimd4_m1_m2_m3, rSimd4_m3_m1_m4));
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(-1, -1, -3), max(rSimd4_m3_m1_m4, rSimd4_m1_m2_m3));
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R( c3,  c1,  c4), max(rSimd4_c0c1c2, rSimd4_c3c0c4));
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R( c3,  c1,  c4), max(rSimd4_c3c0c4, rSimd4_c0c1c2));
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(-c0, -c0, -c2), max(rSimd4_m0m1m2, rSimd4_m3m0m4));
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(-c0, -c0, -c2), max(rSimd4_m3m0m4, rSimd4_m0m1m2));
 }
 
 TEST_F(Simd4FloatingpointTest, min)
 {
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(1, 1, 3), min(rSimd4_1_2_3, rSimd4_3_1_4));
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(1, 1, 3), min(rSimd4_3_1_4, rSimd4_1_2_3));
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(-3, -2, -4), min(rSimd4_m1_m2_m3, rSimd4_m3_m1_m4));
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(-3, -2, -4), min(rSimd4_m3_m1_m4, rSimd4_m1_m2_m3));
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R( c0,  c0,  c2), min(rSimd4_c0c1c2, rSimd4_c3c0c4));
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R( c0,  c0,  c2), min(rSimd4_c3c0c4, rSimd4_c0c1c2));
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(-c3, -c1, -c4), min(rSimd4_m0m1m2, rSimd4_m3m0m4));
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(-c3, -c1, -c4), min(rSimd4_m3m0m4, rSimd4_m0m1m2));
 }
 
 TEST_F(Simd4FloatingpointTest, round)
@@ -214,46 +221,46 @@ TEST_F(Simd4FloatingpointTest, gmxSimd4RsqrtR)
 
 TEST_F(Simd4FloatingpointTest, cmpEqAndSelectByMask)
 {
-    Simd4Bool eq   = (rSimd4_5_7_9 == rSimd4_7_8_9);
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(0, 0, 3), selectByMask(rSimd4_1_2_3, eq));
+    Simd4Bool eq   = rSimd4_c4c6c8 == rSimd4_c6c7c8;
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(0, 0, c2), selectByMask(rSimd4_c0c1c2, eq));
 }
 
 TEST_F(Simd4FloatingpointTest, selectByNotMask)
 {
-    Simd4Bool eq   = (rSimd4_5_7_9 == rSimd4_7_8_9);
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(1, 2, 0), selectByNotMask(rSimd4_1_2_3, eq));
+    Simd4Bool eq   = rSimd4_c4c6c8 == rSimd4_c6c7c8;
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(c0, c1, 0), selectByNotMask(rSimd4_c0c1c2, eq));
 }
 
 TEST_F(Simd4FloatingpointTest, cmpNe)
 {
-    Simd4Bool eq   = (rSimd4_5_7_9 != rSimd4_7_8_9);
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(1, 2, 0), selectByMask(rSimd4_1_2_3, eq));
+    Simd4Bool eq   = rSimd4_c4c6c8 != rSimd4_c6c7c8;
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(c0, c1, 0), selectByMask(rSimd4_c0c1c2, eq));
 }
 
 TEST_F(Simd4FloatingpointTest, cmpLe)
 {
-    Simd4Bool le   = (rSimd4_5_7_9 <= rSimd4_7_8_9);
-    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_1_2_3, selectByMask(rSimd4_1_2_3, le));
+    Simd4Bool le   = rSimd4_c4c6c8 <= rSimd4_c6c7c8;
+    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_c0c1c2, selectByMask(rSimd4_c0c1c2, le));
 }
 
 TEST_F(Simd4FloatingpointTest, cmpLt)
 {
-    Simd4Bool lt   = (rSimd4_5_7_9 < rSimd4_7_8_9);
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(1, 2, 0), selectByMask(rSimd4_1_2_3, lt));
+    Simd4Bool lt   = rSimd4_c4c6c8 < rSimd4_c6c7c8;
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(c0, c1, 0), selectByMask(rSimd4_c0c1c2, lt));
 }
 
 TEST_F(Simd4FloatingpointTest, andB)
 {
-    Simd4Bool eq   = (rSimd4_5_7_9 == rSimd4_7_8_9);
-    Simd4Bool le   = (rSimd4_5_7_9 <= rSimd4_7_8_9);
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(0, 0, 3), selectByMask(rSimd4_1_2_3, eq && le));
+    Simd4Bool eq   = rSimd4_c4c6c8 == rSimd4_c6c7c8;
+    Simd4Bool le   = rSimd4_c4c6c8 <= rSimd4_c6c7c8;
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(0, 0, c2), selectByMask(rSimd4_c0c1c2, (eq && le)));
 }
 
 TEST_F(Simd4FloatingpointTest, orB)
 {
-    Simd4Bool eq   = (rSimd4_5_7_9 == rSimd4_7_8_9);
-    Simd4Bool lt   = (rSimd4_5_7_9 < rSimd4_7_8_9);
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(1, 2, 3), selectByMask(rSimd4_1_2_3, eq || lt));
+    Simd4Bool eq   = rSimd4_c4c6c8 == rSimd4_c6c7c8;
+    Simd4Bool lt   = rSimd4_c4c6c8  < rSimd4_c6c7c8;
+    GMX_EXPECT_SIMD4_REAL_EQ(rSimd4_c0c1c2, selectByMask(rSimd4_c0c1c2, (eq || lt)));
 }
 
 TEST_F(Simd4FloatingpointTest, anyTrue)
@@ -264,24 +271,24 @@ TEST_F(Simd4FloatingpointTest, anyTrue)
      * We cannot check for truth values for "any" element beyond the first,
      * since that part of the data will not be used if simd width is 1.
      */
-    eq = (rSimd4_5_7_9 == setSimd4RealFrom3R(5, 0, 0));
+    eq = (rSimd4_c4c6c8 == setSimd4RealFrom3R(c4, 0, 0));
     EXPECT_TRUE(anyTrue(eq));
 
-    eq = (rSimd4_1_2_3 == rSimd4_4_5_6);
+    eq = (rSimd4_c0c1c2 == rSimd4_c3c4c5);
     EXPECT_FALSE(anyTrue(eq));
 }
 
 TEST_F(Simd4FloatingpointTest, blend)
 {
-    Simd4Bool lt   = (rSimd4_5_7_9 < rSimd4_7_8_9);
-    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(4, 5, 3), blend(rSimd4_1_2_3, rSimd4_4_5_6, lt));
+    Simd4Bool lt   = rSimd4_c4c6c8 < rSimd4_c6c7c8;
+    GMX_EXPECT_SIMD4_REAL_EQ(setSimd4RealFrom3R(c3, c4, c2), blend(rSimd4_c0c1c2, rSimd4_c3c4c5, lt));
 }
 
 TEST_F(Simd4FloatingpointTest, reduce)
 {
     // The horizontal sum of the SIMD variable depends on the width, so
     // simply store it an extra time and calculate what the sum should be
-    std::vector<real> v   = simd4Real2Vector(rSimd4_1_2_3);
+    std::vector<real> v   = simd4Real2Vector(rSimd4_c3c4c5);
     real              sum = 0.0;
 
     for (int i = 0; i < GMX_SIMD4_WIDTH; i++)
@@ -289,19 +296,15 @@ TEST_F(Simd4FloatingpointTest, reduce)
         sum += v[i];
     }
 
-    EXPECT_EQ(sum, reduce(rSimd4_1_2_3));
+    EXPECT_REAL_EQ_TOL(sum, reduce(rSimd4_c3c4c5), defaultRealTolerance() );
 }
 
 
 TEST_F(Simd4FloatingpointTest, dotProduct)
 {
-    Simd4Real v1 = setSimd4RealFrom3R(1, 4, 5);
-    Simd4Real v2 = setSimd4RealFrom3R(3, 8, 2);
-#    if GMX_DOUBLE
-    EXPECT_DOUBLE_EQ(45.0, dotProduct(v1, v2));
-#    else
-    EXPECT_FLOAT_EQ(45.0, dotProduct(v1, v2));
-#    endif
+    real res = c0*c3 + c1*c4 + c2*c5;
+
+    EXPECT_REAL_EQ_TOL(res, dotProduct(rSimd4_c0c1c2, rSimd4_c3c4c5), defaultRealTolerance());
 }
 
 TEST_F(Simd4FloatingpointTest, transpose)
@@ -317,10 +320,11 @@ TEST_F(Simd4FloatingpointTest, transpose)
     // Assign data with tens as row, single-digit as column
     for (i = 0; i < 4; i++)
     {
-        p0[i] = 0*10 + i*1;
-        p1[i] = 1*10 + i*1;
-        p2[i] = 2*10 + i*1;
-        p3[i] = 3*10 + i*1;
+        // Scale by 1+100*eps to use low bits tii
+        p0[i] = (0*10 + i*1) * (1.0 + 100*GMX_REAL_EPS);
+        p1[i] = (1*10 + i*1) * (1.0 + 100*GMX_REAL_EPS);
+        p2[i] = (2*10 + i*1) * (1.0 + 100*GMX_REAL_EPS);
+        p3[i] = (3*10 + i*1) * (1.0 + 100*GMX_REAL_EPS);
     }
 
     v0 = load4(p0);
@@ -337,10 +341,10 @@ TEST_F(Simd4FloatingpointTest, transpose)
 
     for (i = 0; i < 4; i++)
     {
-        EXPECT_EQ(i*10+0, p0[i]);
-        EXPECT_EQ(i*10+1, p1[i]);
-        EXPECT_EQ(i*10+2, p2[i]);
-        EXPECT_EQ(i*10+3, p3[i]);
+        EXPECT_REAL_EQ_TOL( (i*10+0) * (1.0 + 100*GMX_REAL_EPS), p0[i], defaultRealTolerance());
+        EXPECT_REAL_EQ_TOL( (i*10+1) * (1.0 + 100*GMX_REAL_EPS), p1[i], defaultRealTolerance());
+        EXPECT_REAL_EQ_TOL( (i*10+2) * (1.0 + 100*GMX_REAL_EPS), p2[i], defaultRealTolerance());
+        EXPECT_REAL_EQ_TOL( (i*10+3) * (1.0 + 100*GMX_REAL_EPS), p3[i], defaultRealTolerance());
     }
 }
 
index f32d4ff14b38052d40c1eb5e3e7caeb533608269..97ae2d2d1ffadb382528c99a8bc0ee893483e44f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -39,6 +39,7 @@
 #include "gromacs/simd/simd.h"
 #include "gromacs/simd/vector_operations.h"
 
+#include "data.h"
 #include "simd4.h"
 
 #if GMX_SIMD
@@ -61,10 +62,12 @@ typedef Simd4Test Simd4VectorOperationsTest;
 
 TEST_F(Simd4VectorOperationsTest, norm2)
 {
-    Simd4Real simdX  = setSimd4RealFrom3R(1, 2, 3);
-    Simd4Real simdY  = setSimd4RealFrom3R(3, 0, 5);
-    Simd4Real simdZ  = setSimd4RealFrom3R(4, 1, 8);
-    Simd4Real simdR2 = setSimd4RealFrom3R(26, 5, 98);
+    Simd4Real simdX  = rSimd4_c0c1c2;
+    Simd4Real simdY  = rSimd4_c3c4c5;
+    Simd4Real simdZ  = rSimd4_c6c7c8;
+    Simd4Real simdR2 = setSimd4RealFrom3R(c0*c0 + c3*c3 + c6*c6,
+                                          c1*c1 + c4*c4 + c7*c7,
+                                          c2*c2 + c5*c5 + c8*c8);
 
     setUlpTol(2);
     GMX_EXPECT_SIMD4_REAL_NEAR(simdR2, norm2(simdX, simdY, simdZ));
index 4e411343781175417ac2bc87bba7868d2681758a..ce994b6e3dd45f7d4f147343a987e609f8966ce4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -42,6 +42,7 @@
 
 #include "testutils/testasserts.h"
 
+#include "data.h"
 #include "simd.h"
 
 #if GMX_SIMD
@@ -70,106 +71,103 @@ TEST_F(SimdFloatingpointTest, setZero)
 
 TEST_F(SimdFloatingpointTest, set)
 {
-    real  r  = 2.0;
-    real *p  = &r;
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(1.0), SimdReal(1.0));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(r), SimdReal(*p));
+    const real *p  = &c0;
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(c1), SimdReal(c1));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(c0), SimdReal(*p));
 }
 
 TEST_F(SimdFloatingpointTest, add)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(rSimd_5_7_9,
-                            (rSimd_1_2_3 + rSimd_4_5_6)); // 1+4=5, 2+5=7, 3+6=9
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(c0 + c3, c1 + c4, c2 + c5 ),
+                              rSimd_c0c1c2 + rSimd_c3c4c5);
 }
 
 TEST_F(SimdFloatingpointTest, maskAdd)
 {
-    SimdBool m = setSimdRealFrom3R(1, 0, 1) != setZero();
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(5, 2, 9),
-                            maskAdd(rSimd_1_2_3, rSimd_4_5_6, m));
+    SimdBool m = setSimdRealFrom3R(c6, 0, c7) != setZero();
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(c0 + c3, c1 + 0.0, c2 + c5 ),
+                              maskAdd(rSimd_c0c1c2, rSimd_c3c4c5, m));
 }
 
 TEST_F(SimdFloatingpointTest, sub)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(rSimd_4_5_6,
-                            (rSimd_5_7_9 - rSimd_1_2_3)); // 5-1=4, 7-2=5, 9-3=6
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(c0 - c3, c1 - c4, c2 - c5 ),
+                              rSimd_c0c1c2 - rSimd_c3c4c5);
 }
 
 TEST_F(SimdFloatingpointTest, mul)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(4, 10, 18),
-                            (rSimd_1_2_3 * rSimd_4_5_6));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(c0 * c3, c1 * c4, c2 * c5 ),
+                              rSimd_c0c1c2 * rSimd_c3c4c5);
 }
 
 TEST_F(SimdFloatingpointTest, maskzMul)
 {
-    SimdBool m = setSimdRealFrom3R(1, 0, 1) != setZero();
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(4, 0, 18),
-                            maskzMul(rSimd_1_2_3, rSimd_4_5_6, m));
+    SimdBool m = setSimdRealFrom3R(c1, 0, c1) != setZero();
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(c0 * c3, 0.0, c2 * c5 ),
+                              maskzMul(rSimd_c0c1c2, rSimd_c3c4c5, m));
 }
 
 TEST_F(SimdFloatingpointTest, fma)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(11, 18, 27),
-                            fma(rSimd_1_2_3, rSimd_4_5_6, rSimd_7_8_9)); // 1*4+7, etc.
+    // The last bit of FMA operations depends on hardware, so we don't require exact match
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(c0 * c3 + c6, c1 * c4 + c7, c2 * c5 + c8),
+                              fma(rSimd_c0c1c2, rSimd_c3c4c5, rSimd_c6c7c8));
 }
 
+
 TEST_F(SimdFloatingpointTest, maskzFma)
 {
-    SimdBool m = setSimdRealFrom3R(1, 0, 1) != setZero();
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(11, 0, 27),
-                            maskzFma(rSimd_1_2_3, rSimd_4_5_6, rSimd_7_8_9, m)); // 1*4+7, etc.
+    SimdBool m = setSimdRealFrom3R(c2, 0, c3) != setZero();
+    // The last bit of FMA operations depends on hardware, so we don't require exact match
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(c0 * c3 + c6, 0.0, c2 * c5 + c8),
+                              maskzFma(rSimd_c0c1c2, rSimd_c3c4c5, rSimd_c6c7c8, m));
 }
 
 TEST_F(SimdFloatingpointTest, fms)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-3, 2, 9),
-                            fms(rSimd_1_2_3, rSimd_4_5_6, rSimd_7_8_9)); // 1*4-7, etc.
+    // The last bit of FMA operations depends on hardware, so we don't require exact match
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(c0 * c3 - c6, c1 * c4 - c7, c2 * c5 - c8),
+                              fms(rSimd_c0c1c2, rSimd_c3c4c5, rSimd_c6c7c8));
 }
 
 TEST_F(SimdFloatingpointTest, fnma)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(3, -2, -9),
-                            fnma(rSimd_1_2_3, rSimd_4_5_6, rSimd_7_8_9)); // -1*4+7, etc.
+    // The last bit of FMA operations depends on hardware, so we don't require exact match
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(c6 - c0 * c3, c7 - c1 * c4, c8 - c2 * c5),
+                              fnma(rSimd_c0c1c2, rSimd_c3c4c5, rSimd_c6c7c8));
 }
 
 TEST_F(SimdFloatingpointTest, fnms)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-11, -18, -27),
-                            fnms(rSimd_1_2_3, rSimd_4_5_6, rSimd_7_8_9)); // -1*4-7, etc.
+    // The last bit of FMA operations depends on hardware, so we don't require exact match
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(-c0 * c3 - c6, -c1 * c4 - c7, -c2 * c5 - c8),
+                              fnms(rSimd_c0c1c2, rSimd_c3c4c5, rSimd_c6c7c8));
 }
 
 TEST_F(SimdFloatingpointTest, abs)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(rSimd_1_2_3, abs(rSimd_1_2_3));    // fabs(x)=x
-    GMX_EXPECT_SIMD_REAL_EQ(rSimd_1_2_3, abs(rSimd_m1_m2_m3)); // fabs(-x)=x
+    GMX_EXPECT_SIMD_REAL_EQ(rSimd_c0c1c2, abs(rSimd_c0c1c2)); // fabs(x)=x
+    GMX_EXPECT_SIMD_REAL_EQ(rSimd_c0c1c2, abs(rSimd_m0m1m2)); // fabs(-x)=x
 }
 
 TEST_F(SimdFloatingpointTest, neg)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(rSimd_m1_m2_m3, -(rSimd_1_2_3));    // fneg(x)=-x
-    GMX_EXPECT_SIMD_REAL_EQ(rSimd_1_2_3,    -(rSimd_m1_m2_m3)); // fneg(-x)=x
+    GMX_EXPECT_SIMD_REAL_EQ(rSimd_m0m1m2, -(rSimd_c0c1c2)); // fneg(x)=-x
+    GMX_EXPECT_SIMD_REAL_EQ(rSimd_c0c1c2, -(rSimd_m0m1m2)); // fneg(-x)=x
 }
 
 #if GMX_SIMD_HAVE_LOGICAL
-/* 1.3333282470703125 has mantissa 0101010101010101 (followed by zeros)
- * 1.79998779296875   has mantissa 1100110011001100 (followed by zeros)
- * 1.26666259765625   has mantissa 0100010001000100 (followed by zeros)
- * 1.8666534423828125 has mantissa 1101110111011101 (followed by zeros)
- *
- * Since all of them have the same exponent (2^0), the exponent will
- * not change with AND or OR operations.
- */
 TEST_F(SimdFloatingpointTest, and)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(1.26666259765625),
-                            (SimdReal(1.3333282470703125) & SimdReal(1.79998779296875)));
+    GMX_EXPECT_SIMD_REAL_EQ(rSimd_logicalResultAnd,
+                            (rSimd_logicalA & rSimd_logicalB));
 }
 
 TEST_F(SimdFloatingpointTest, or)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(1.8666534423828125),
-                            (SimdReal(1.3333282470703125) | SimdReal(1.79998779296875)));
+    GMX_EXPECT_SIMD_REAL_EQ(rSimd_logicalResultOr,
+                            (rSimd_logicalA | rSimd_logicalB));
 }
 
 TEST_F(SimdFloatingpointTest, xor)
@@ -178,8 +176,8 @@ TEST_F(SimdFloatingpointTest, xor)
      * in only the sign bit being set. We then use this bit change the sign of
      * different numbers.
      */
-    SimdReal signbit = SimdReal(1.5) ^ SimdReal(-1.5);
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-1, 2, -3), (signbit ^ setSimdRealFrom3R(1, -2, 3)));
+    SimdReal signbit = SimdReal(c1) ^ SimdReal(-c1);
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-c2, c3, -c4), (signbit ^ setSimdRealFrom3R(c2, -c3, c4)));
 }
 
 TEST_F(SimdFloatingpointTest, andNot)
@@ -187,34 +185,34 @@ TEST_F(SimdFloatingpointTest, andNot)
     /* Use xor (which we already tested, so fix that first if both tests fail)
      * to extract the sign bit, and then use andnot to take absolute values.
      */
-    SimdReal signbit = SimdReal(1.5) ^ SimdReal(-1.5);
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(1, 2, 3), andNot(signbit, setSimdRealFrom3R(-1, 2, -3)));
+    SimdReal signbit = SimdReal(c1) ^ SimdReal(-c1);
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(c2, c3, c4), andNot(signbit, setSimdRealFrom3R(-c2, c3, -c4)));
 }
 
 #endif
 
 TEST_F(SimdFloatingpointTest, max)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(3, 2, 4), max(rSimd_1_2_3, rSimd_3_1_4));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(3, 2, 4), max(rSimd_3_1_4, rSimd_1_2_3));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-1, -1, -3), max(rSimd_m1_m2_m3, rSimd_m3_m1_m4));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-1, -1, -3), max(rSimd_m3_m1_m4, rSimd_m1_m2_m3));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R( c3,  c1,  c4), max(rSimd_c0c1c2, rSimd_c3c0c4));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R( c3,  c1,  c4), max(rSimd_c3c0c4, rSimd_c0c1c2));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-c0, -c0, -c2), max(rSimd_m0m1m2, rSimd_m3m0m4));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-c0, -c0, -c2), max(rSimd_m3m0m4, rSimd_m0m1m2));
 }
 
 TEST_F(SimdFloatingpointTest, min)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(1, 1, 3), min(rSimd_1_2_3, rSimd_3_1_4));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(1, 1, 3), min(rSimd_3_1_4, rSimd_1_2_3));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-3, -2, -4), min(rSimd_m1_m2_m3, rSimd_m3_m1_m4));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-3, -2, -4), min(rSimd_m3_m1_m4, rSimd_m1_m2_m3));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R( c0,  c0,  c2), min(rSimd_c0c1c2, rSimd_c3c0c4));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R( c0,  c0,  c2), min(rSimd_c3c0c4, rSimd_c0c1c2));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-c3, -c1, -c4), min(rSimd_m0m1m2, rSimd_m3m0m4));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-c3, -c1, -c4), min(rSimd_m3m0m4, rSimd_m0m1m2));
 }
 
 TEST_F(SimdFloatingpointTest, round)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(2), round(SimdReal(2.25)));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(4), round(SimdReal(3.75)));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-2), round(SimdReal(-2.25)));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-4), round(SimdReal(-3.75)));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(2), round(rSimd_2p25));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(4), round(rSimd_3p75));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-2), round(rSimd_m2p25));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom1R(-4), round(rSimd_m3p75));
 }
 
 TEST_F(SimdFloatingpointTest, trunc)
@@ -353,58 +351,58 @@ TEST_F(SimdFloatingpointTest, maskzRcp)
 
 TEST_F(SimdFloatingpointTest, cmpEqAndSelectByMask)
 {
-    SimdBool eq   = rSimd_5_7_9 == rSimd_7_8_9;
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(0, 0, 3), selectByMask(rSimd_1_2_3, eq));
+    SimdBool eq   = rSimd_c4c6c8 == rSimd_c6c7c8;
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(0, 0, c2), selectByMask(rSimd_c0c1c2, eq));
 }
 
 TEST_F(SimdFloatingpointTest, selectByNotMask)
 {
-    SimdBool eq   = rSimd_5_7_9 == rSimd_7_8_9;
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(1, 2, 0), selectByNotMask(rSimd_1_2_3, eq));
+    SimdBool eq   = rSimd_c4c6c8 == rSimd_c6c7c8;
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(c0, c1, 0), selectByNotMask(rSimd_c0c1c2, eq));
 }
 
 TEST_F(SimdFloatingpointTest, cmpNe)
 {
-    SimdBool eq   = rSimd_5_7_9 != rSimd_7_8_9;
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(1, 2, 0), selectByMask(rSimd_1_2_3, eq));
+    SimdBool eq   = rSimd_c4c6c8 != rSimd_c6c7c8;
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(c0, c1, 0), selectByMask(rSimd_c0c1c2, eq));
 }
 
 TEST_F(SimdFloatingpointTest, cmpLe)
 {
-    SimdBool le   = rSimd_5_7_9 <= rSimd_7_8_9;
-    GMX_EXPECT_SIMD_REAL_EQ(rSimd_1_2_3, selectByMask(rSimd_1_2_3, le));
+    SimdBool le   = rSimd_c4c6c8 <= rSimd_c6c7c8;
+    GMX_EXPECT_SIMD_REAL_EQ(rSimd_c0c1c2, selectByMask(rSimd_c0c1c2, le));
 }
 
 TEST_F(SimdFloatingpointTest, cmpLt)
 {
-    SimdBool lt   = rSimd_5_7_9 < rSimd_7_8_9;
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(1, 2, 0), selectByMask(rSimd_1_2_3, lt));
+    SimdBool lt   = rSimd_c4c6c8 < rSimd_c6c7c8;
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(c0, c1, 0), selectByMask(rSimd_c0c1c2, lt));
 }
 
 #if GMX_SIMD_HAVE_INT32_LOGICAL || GMX_SIMD_HAVE_LOGICAL
 TEST_F(SimdFloatingpointTest, testBits)
 {
-    SimdBool eq   = testBits(setSimdRealFrom3R(1, 0, 2));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(1, 0, 3), selectByMask(rSimd_1_2_3, eq));
+    SimdBool eq   = testBits(setSimdRealFrom3R(c1, 0, c1));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(c0, 0, c2), selectByMask(rSimd_c0c1c2, eq));
 
     // Test if we detect only the sign bit being set
     eq            = testBits(setSimdRealFrom1R(GMX_REAL_NEGZERO));
-    GMX_EXPECT_SIMD_REAL_EQ(rSimd_1_2_3, selectByMask(rSimd_1_2_3, eq));
+    GMX_EXPECT_SIMD_REAL_EQ(rSimd_c0c1c2, selectByMask(rSimd_c0c1c2, eq));
 }
 #endif
 
 TEST_F(SimdFloatingpointTest, andB)
 {
-    SimdBool eq   = rSimd_5_7_9 == rSimd_7_8_9;
-    SimdBool le   = rSimd_5_7_9 <= rSimd_7_8_9;
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(0, 0, 3), selectByMask(rSimd_1_2_3, (eq && le)));
+    SimdBool eq   = rSimd_c4c6c8 == rSimd_c6c7c8;
+    SimdBool le   = rSimd_c4c6c8 <= rSimd_c6c7c8;
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(0, 0, c2), selectByMask(rSimd_c0c1c2, (eq && le)));
 }
 
 TEST_F(SimdFloatingpointTest, orB)
 {
-    SimdBool eq   = rSimd_5_7_9 == rSimd_7_8_9;
-    SimdBool lt   = rSimd_5_7_9 < rSimd_7_8_9;
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(1, 2, 3), selectByMask(rSimd_1_2_3, (eq || lt)));
+    SimdBool eq   = rSimd_c4c6c8 == rSimd_c6c7c8;
+    SimdBool lt   = rSimd_c4c6c8  < rSimd_c6c7c8;
+    GMX_EXPECT_SIMD_REAL_EQ(rSimd_c0c1c2, selectByMask(rSimd_c0c1c2, (eq || lt)));
 }
 
 TEST_F(SimdFloatingpointTest, anyTrueB)
@@ -415,24 +413,24 @@ TEST_F(SimdFloatingpointTest, anyTrueB)
      * We cannot check for truth values for "any" element beyond the first,
      * since that part of the data will not be used if simd width is 1.
      */
-    eq = rSimd_5_7_9 == setSimdRealFrom3R(5, 0, 0);
+    eq = rSimd_c4c6c8 == setSimdRealFrom3R(c4, 0, 0);
     EXPECT_TRUE(anyTrue(eq));
 
-    eq = rSimd_1_2_3 == rSimd_4_5_6;
+    eq = rSimd_c0c1c2 == rSimd_c3c4c5;
     EXPECT_FALSE(anyTrue(eq));
 }
 
 TEST_F(SimdFloatingpointTest, blend)
 {
-    SimdBool lt   = rSimd_5_7_9 < rSimd_7_8_9;
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(4, 5, 3), blend(rSimd_1_2_3, rSimd_4_5_6, lt));
+    SimdBool lt   = rSimd_c4c6c8 < rSimd_c6c7c8;
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(c3, c4, c2), blend(rSimd_c0c1c2, rSimd_c3c4c5, lt));
 }
 
 TEST_F(SimdFloatingpointTest, reduce)
 {
     // The horizontal sum of the SIMD variable depends on the width, so
     // simply store it an extra time and calculate what the sum should be
-    std::vector<real> v   = simdReal2Vector(rSimd_4_5_6);
+    std::vector<real> v   = simdReal2Vector(rSimd_c3c4c5);
     real              sum = 0.0;
 
     for (int i = 0; i < GMX_SIMD_REAL_WIDTH; i++)
@@ -440,7 +438,7 @@ TEST_F(SimdFloatingpointTest, reduce)
         sum += v[i];
     }
 
-    EXPECT_EQ(sum, reduce(rSimd_4_5_6));
+    EXPECT_REAL_EQ_TOL(sum, reduce(rSimd_c3c4c5), defaultRealTolerance() );
 }
 
 #endif      // GMX_SIMD_HAVE_REAL
@@ -458,7 +456,9 @@ TEST_F(SimdFloatingpointTest, cvtFloat2Double)
 
     for (i = 0; i < GMX_SIMD_FLOAT_WIDTH; i++)
     {
-        f[i] = i;
+        // Scale by 1+100*eps to use low bits too.
+        // Due to the conversions we want to avoid being too sensitive to fluctuations in last bit
+        f[i] = i * (1.0 + 100*GMX_FLOAT_EPS);
     }
 
     vf = load(f);
@@ -491,7 +491,9 @@ TEST_F(SimdFloatingpointTest, cvtDouble2Float)
     // This fills elements for pd1 too when double width is 2*single width
     for (i = 0; i < GMX_SIMD_FLOAT_WIDTH; i++)
     {
-        d[i] = i;
+        // Scale by 1+eps to use low bits too.
+        // Due to the conversions we want to avoid being too sensitive to fluctuations in last bit
+        d[i] = i * (1.0 + 100*GMX_FLOAT_EPS);
     }
 
     vd0 = load(d);
index 6eef2e2a95fd7b5b69fada291d053f7bb5433cd9..8d288f77c69be35d16996814f26aed1aa1906faf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2015, by the GROMACS development team, led by
+ * Copyright (c) 2015,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -85,10 +85,12 @@ class SimdFloatingpointUtilTest : public SimdTest
             {
                 // Use every third point to avoid a continguous access pattern
                 offset_[i] = 3 * i;
-                val0_[i]   = i;
-                val1_[i]   = i + 0.1;
-                val2_[i]   = i + 0.2;
-                val3_[i]   = i + 0.3;
+                // Multiply numbers by 1+100*GMX_REAL_EPS ensures some low bits are
+                // set too, so the tests make sure we read all bits correctly.
+                val0_[i]   = (i      ) * (1.0 + 100*GMX_REAL_EPS);
+                val1_[i]   = (i + 0.1) * (1.0 + 100*GMX_REAL_EPS);
+                val2_[i]   = (i + 0.2) * (1.0 + 100*GMX_REAL_EPS);
+                val3_[i]   = (i + 0.3) * (1.0 + 100*GMX_REAL_EPS);
             }
         }
 
@@ -265,7 +267,8 @@ TEST_F(SimdFloatingpointUtilTest, transposeScatterStoreU3)
         // Set test and reference memory to background value
         for (std::size_t j = 0; j < s_workMemSize_; j++)
         {
-            mem0_[j] = refmem[j] = 1000.0 + j;
+            // Multiply by 1+100*eps to make sure low bits are also used
+            mem0_[j] = refmem[j] = (1000.0 + j) * (1.0 + 100*GMX_REAL_EPS);
         }
 
         for (std::size_t j = 0; j < GMX_SIMD_REAL_WIDTH; j++)
@@ -316,7 +319,8 @@ TEST_F(SimdFloatingpointUtilTest, transposeScatterIncrU3)
         // Set test and reference memory to background value
         for (std::size_t j = 0; j < s_workMemSize_; j++)
         {
-            mem0_[j] = refmem[j] = 1000.0 + j;
+            // Multiply by 1+100*eps to make sure low bits are also used
+            mem0_[j] = refmem[j] = (1000.0 + j) * (1.0 + 100*GMX_REAL_EPS);
         }
 
         for (std::size_t j = 0; j < GMX_SIMD_REAL_WIDTH; j++)
@@ -366,7 +370,8 @@ TEST_F(SimdFloatingpointUtilTest, transposeScatterIncrU3Overlapping)
     // Set test and reference memory to background value
     for (std::size_t j = 0; j < s_workMemSize_; j++)
     {
-        mem0_[j] = refmem[j] = 1000.0 + j;
+        // Multiply by 1+100*eps to make sure low bits are also used
+        mem0_[j] = refmem[j] = (1000.0 + j) * (1.0 + 100*GMX_REAL_EPS);
     }
 
     for (std::size_t j = 0; j < GMX_SIMD_REAL_WIDTH; j++)
@@ -405,7 +410,8 @@ TEST_F(SimdFloatingpointUtilTest, transposeScatterDecrU3)
         // Set test and reference memory to background value
         for (std::size_t j = 0; j < s_workMemSize_; j++)
         {
-            mem0_[j] = refmem[j] = 1000.0 + j;
+            // Multiply by 1+100*eps to make sure low bits are also used
+            mem0_[j] = refmem[j] = (1000.0 + j) * (1.0 + 100*GMX_REAL_EPS);
         }
 
         for (std::size_t j = 0; j < GMX_SIMD_REAL_WIDTH; j++)
@@ -455,7 +461,8 @@ TEST_F(SimdFloatingpointUtilTest, transposeScatterDecrU3Overlapping)
     // Set test and reference memory to background value
     for (std::size_t j = 0; j < s_workMemSize_; j++)
     {
-        mem0_[j] = refmem[j] = 1000.0 + j;
+        // Multiply by 1+100*eps to make sure low bits are also used
+        mem0_[j] = refmem[j] = (1000.0 + j) * (1.0 + 100*GMX_REAL_EPS);
     }
 
     for (std::size_t j = 0; j < GMX_SIMD_REAL_WIDTH; j++)
@@ -668,17 +675,17 @@ TEST_F(SimdFloatingpointUtilTest, reduceIncr4Sum)
     }
 
     // Just put some numbers in memory so we check the addition is correct
-    mem0_[0] = 5.0;
-    mem0_[1] = 15.0;
-    mem0_[2] = 25.0;
-    mem0_[3] = 35.0;
+    mem0_[0] = c0;
+    mem0_[1] = c1;
+    mem0_[2] = c2;
+    mem0_[3] = c3;
 
     tstsum = reduceIncr4ReturnSum(mem0_, v0, v1, v2, v3);
 
-    EXPECT_REAL_EQ_TOL( 5.0 + sum0, mem0_[0], tolerance);
-    EXPECT_REAL_EQ_TOL(15.0 + sum1, mem0_[1], tolerance);
-    EXPECT_REAL_EQ_TOL(25.0 + sum2, mem0_[2], tolerance);
-    EXPECT_REAL_EQ_TOL(35.0 + sum3, mem0_[3], tolerance);
+    EXPECT_REAL_EQ_TOL(c0 + sum0, mem0_[0], tolerance);
+    EXPECT_REAL_EQ_TOL(c1 + sum1, mem0_[1], tolerance);
+    EXPECT_REAL_EQ_TOL(c2 + sum2, mem0_[2], tolerance);
+    EXPECT_REAL_EQ_TOL(c3 + sum3, mem0_[3], tolerance);
 
     EXPECT_REAL_EQ_TOL(sum0 + sum1 + sum2 + sum3, tstsum, tolerance);
 }
@@ -893,17 +900,17 @@ TEST_F(SimdFloatingpointUtilTest, reduceIncr4SumHsimd)
     }
 
     // Just put some numbers in memory so we check the addition is correct
-    mem0_[0] = 5.0;
-    mem0_[1] = 15.0;
-    mem0_[2] = 25.0;
-    mem0_[3] = 35.0;
+    mem0_[0] = c0;
+    mem0_[1] = c1;
+    mem0_[2] = c2;
+    mem0_[3] = c3;
 
     tstsum = reduceIncr4ReturnSumHsimd(mem0_, v0, v1);
 
-    EXPECT_REAL_EQ_TOL( 5.0 + sum0, mem0_[0], tolerance);
-    EXPECT_REAL_EQ_TOL(15.0 + sum1, mem0_[1], tolerance);
-    EXPECT_REAL_EQ_TOL(25.0 + sum2, mem0_[2], tolerance);
-    EXPECT_REAL_EQ_TOL(35.0 + sum3, mem0_[3], tolerance);
+    EXPECT_REAL_EQ_TOL(c0 + sum0, mem0_[0], tolerance);
+    EXPECT_REAL_EQ_TOL(c1 + sum1, mem0_[1], tolerance);
+    EXPECT_REAL_EQ_TOL(c2 + sum2, mem0_[2], tolerance);
+    EXPECT_REAL_EQ_TOL(c3 + sum3, mem0_[3], tolerance);
 
     EXPECT_REAL_EQ_TOL(sum0 + sum1 + sum2 + sum3, tstsum, tolerance);
 }
index 9ab6e87774c633738b9d4c5bef2128496c417ff1..7dd555bbbd15daee5f37010d9f710dd174daf618 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015,2016, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2016,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -305,7 +305,7 @@ TEST_F(SimdIntegerTest, blend)
 #if GMX_SIMD_HAVE_REAL && GMX_SIMD_HAVE_INT32_ARITHMETICS
 TEST_F(SimdIntegerTest, cvtB2IB)
 {
-    SimdBool  eq   = (rSimd_5_7_9 == setSimdRealFrom3R(5, 0, 0));  // eq should be T,F,F
+    SimdBool  eq   = (rSimd_c3c4c5 == rSimd_c3c0c4);  // eq should be T,F,F
     SimdIBool eqi  = cvtB2IB(eq);
     GMX_EXPECT_SIMD_INT_EQ(setSimdIntFrom3I(1, 0, 0), selectByMask(iSimd_1_2_3, eqi));
 
@@ -315,7 +315,7 @@ TEST_F(SimdIntegerTest, cvtIB2B)
 {
     SimdIBool eqi  = (iSimd_5_7_9 == setSimdIntFrom3I(5, 0, 0));  // eq should be T,F,F
     SimdBool  eq   = cvtIB2B(eqi);
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(1.0, 0, 0), selectByMask(rSimd_1_2_3, eq));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(c0, 0, 0), selectByMask(rSimd_c0c1c2, eq));
 }
 #endif      // GMX_SIMD_HAVE_REAL && GMX_SIMD_HAVE_INT32_ARITHMETICS
 
index 532ab3ec887aa5a934664809939f5f4f8d1d6834..2f1f19ff67a889605d56f2bab3ccc137dbb8fab9 100644 (file)
@@ -68,6 +68,7 @@ class SimdMathTest : public SimdTest
         ::testing::AssertionResult
                             compareSimdMathFunction(const char * refFuncExpr, const char *simdFuncExpr,
                                                     real refFunc(real x),     SimdReal gmx_simdcall simdFunc(SimdReal x));
+
 };
 
 /*! \brief Test approximate equality of SIMD vs reference version of a function.
@@ -198,10 +199,10 @@ namespace
 
 TEST_F(SimdMathTest, copysign)
 {
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-4, 5, 6), copysign(setSimdRealFrom3R(4, 5, 6), setSimdRealFrom3R(-5, 2, 0)));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-4, 5, 6), copysign(setSimdRealFrom3R(-4, -5, -6), setSimdRealFrom3R(-5, 2, 0)));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(4, -5, 6), copysign(setSimdRealFrom3R(4, 5, 6), setSimdRealFrom3R(5, -2, 0)));
-    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(4, -5, 6), copysign(setSimdRealFrom3R(-4, -5, -6), setSimdRealFrom3R(5, -2, 0)));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-c0,  c1, c2), copysign(setSimdRealFrom3R( c0,  c1,  c2), setSimdRealFrom3R(-c3,  c4, 0)));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R(-c0,  c1, c2), copysign(setSimdRealFrom3R(-c0, -c1, -c2), setSimdRealFrom3R(-c3,  c4, 0)));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R( c0, -c1, c2), copysign(setSimdRealFrom3R( c0,  c1,  c2), setSimdRealFrom3R( c3, -c4, 0)));
+    GMX_EXPECT_SIMD_REAL_EQ(setSimdRealFrom3R( c0, -c1, c2), copysign(setSimdRealFrom3R(-c0, -c1, -c2), setSimdRealFrom3R( c3, -c4, 0)));
 }
 
 /*! \brief Function wrapper to evaluate reference 1/sqrt(x) */
@@ -219,9 +220,9 @@ TEST_F(SimdMathTest, invsqrt)
 
 TEST_F(SimdMathTest, maskzInvsqrt)
 {
-    SimdReal x   = setSimdRealFrom3R(1.0, 0.0, 3.0);
+    SimdReal x   = setSimdRealFrom3R(c1, 0.0, c2);
     SimdBool m   = (setZero() < x);
-    SimdReal ref = setSimdRealFrom3R(1.0/std::sqrt(1.0), 0.0, 1.0/std::sqrt(3.0));
+    SimdReal ref = setSimdRealFrom3R(1.0/std::sqrt(c1), 0.0, 1.0/std::sqrt(c2));
     GMX_EXPECT_SIMD_REAL_NEAR(ref, maskzInvsqrt(x, m));
 }
 
@@ -257,7 +258,7 @@ TEST_F(SimdMathTest, invsqrtPair)
 TEST_F(SimdMathTest, sqrt)
 {
     // Just make sure sqrt(0)=0 works and isn't evaluated as 0*1/sqrt(0)=NaN
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(0, 2, 3), sqrt(setSimdRealFrom3R(0, 4, 9)));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(0, std::sqrt(c1), std::sqrt(c2)), sqrt(setSimdRealFrom3R(0, c1, c2)));
 }
 
 /*! \brief Function wrapper to evaluate reference 1/x */
@@ -277,9 +278,9 @@ TEST_F(SimdMathTest, inv)
 
 TEST_F(SimdMathTest, maskzInv)
 {
-    SimdReal x   = setSimdRealFrom3R(2.0, 0.0, 3.0);
+    SimdReal x   = setSimdRealFrom3R(c1, 0.0, c2);
     SimdBool m   = (setZero() < x);
-    SimdReal ref = setSimdRealFrom3R(0.5, 0.0, 1.0/3.0);
+    SimdReal ref = setSimdRealFrom3R(1.0/c1, 0.0, 1.0/c2);
     GMX_EXPECT_SIMD_REAL_NEAR(ref, maskzInv(x, m));
 }
 
@@ -429,16 +430,25 @@ TEST_F(SimdMathTest, atan)
 TEST_F(SimdMathTest, atan2)
 {
     // test each quadrant
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(1.0, 1.0)), atan2(rSimd_1_2_3, rSimd_1_2_3));
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(-1.0, 1.0)), atan2(rSimd_m1_m2_m3, rSimd_1_2_3));
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(-1.0, -1.0)), atan2(rSimd_m1_m2_m3, rSimd_m1_m2_m3));
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(1.0, -1.0)), atan2(rSimd_1_2_3, rSimd_m1_m2_m3));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(c0, c3), std::atan2(c1, c4), std::atan2(c2, c5)),
+                              atan2(rSimd_c0c1c2, rSimd_c3c4c5));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(-c0, c3), std::atan2(-c1, c4), std::atan2(-c2, c5)),
+                              atan2(rSimd_m0m1m2, rSimd_c3c4c5));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(-c0, -c3), std::atan2(-c1, -c0), std::atan2(-c2, -c4)),
+                              atan2(rSimd_m0m1m2, rSimd_m3m0m4));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(c0, -c3), std::atan2(c1, -c0), std::atan2(c2, -c4)),
+                              atan2(rSimd_c0c1c2, rSimd_m3m0m4));
+
     // cases important for calculating angles
     // values on coordinate axes
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(0.0, 1.0)), atan2(setZero(), rSimd_1_2_3));
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(1.0, 0.0)), atan2(rSimd_1_2_3, setZero()));
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(0.0, -1.0)), atan2(setZero(), rSimd_m1_m2_m3));
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(-1.0, 0.0)), atan2(rSimd_m1_m2_m3, setZero()));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(0, c0), std::atan2(0, c1), std::atan2(0, c2)),
+                              atan2(setZero(), rSimd_c0c1c2));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(c0, 0), std::atan2(c1, 0), std::atan2(c2, 0)),
+                              atan2(rSimd_c0c1c2, setZero()));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(0, -c0), std::atan2(0, -c1), std::atan2(0, -c2)),
+                              atan2(setZero(), rSimd_m0m1m2));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(-c0, 0), std::atan2(-c1, 0), std::atan2(-c2, 0)),
+                              atan2(rSimd_m0m1m2, setZero()));
     // degenerate value (origin) should return 0.0. At least IBM xlc 13.1.5 gets the reference
     // value wrong (-nan) at -O3 optimization, so we compare to the correct value (0.0) instead.
     GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(0.0), atan2(setSimdRealFrom3R(0.0, 0.0, 0.0), setZero()));
@@ -541,7 +551,7 @@ TEST_F(SimdMathTest, sqrtSingleAccuracy)
     setUlpTol(ulpTol_ * (1LL << (std::numeric_limits<real>::digits-std::numeric_limits<float>::digits)));
 
     // Just make sure sqrt(0)=0 works and isn't evaluated as 0*1/sqrt(0)=NaN
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(0, 2, 3), sqrtSingleAccuracy(setSimdRealFrom3R(0, 4, 9)));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(0, std::sqrt(c0), std::sqrt(c1)), sqrtSingleAccuracy(setSimdRealFrom3R(0, c0, c1)));
 }
 
 TEST_F(SimdMathTest, invSingleAccuracy)
@@ -682,16 +692,25 @@ TEST_F(SimdMathTest, atan2SingleAccuracy)
     setUlpTol(ulpTol_ * (1LL << (std::numeric_limits<real>::digits-std::numeric_limits<float>::digits)));
 
     // test each quadrant
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(1.0, 1.0)), atan2SingleAccuracy(rSimd_1_2_3, rSimd_1_2_3));
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(-1.0, 1.0)), atan2SingleAccuracy(rSimd_m1_m2_m3, rSimd_1_2_3));
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(-1.0, -1.0)), atan2SingleAccuracy(rSimd_m1_m2_m3, rSimd_m1_m2_m3));
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(1.0, -1.0)), atan2SingleAccuracy(rSimd_1_2_3, rSimd_m1_m2_m3));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(c0, c3), std::atan2(c1, c4), std::atan2(c2, c5)),
+                              atan2SingleAccuracy(rSimd_c0c1c2, rSimd_c3c4c5));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(-c0, c3), std::atan2(-c1, c4), std::atan2(-c2, c5)),
+                              atan2SingleAccuracy(rSimd_m0m1m2, rSimd_c3c4c5));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(-c0, -c3), std::atan2(-c1, -c0), std::atan2(-c2, -c4)),
+                              atan2SingleAccuracy(rSimd_m0m1m2, rSimd_m3m0m4));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(c0, -c3), std::atan2(c1, -c0), std::atan2(c2, -c4)),
+                              atan2SingleAccuracy(rSimd_c0c1c2, rSimd_m3m0m4));
     // cases important for calculating angles
     // values on coordinate axes
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(0.0, 1.0)), atan2SingleAccuracy(setZero(), rSimd_1_2_3));
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(1.0, 0.0)), atan2SingleAccuracy(rSimd_1_2_3, setZero()));
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(0.0, -1.0)), atan2SingleAccuracy(setZero(), rSimd_m1_m2_m3));
-    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(std::atan2(-1.0, 0.0)), atan2SingleAccuracy(rSimd_m1_m2_m3, setZero()));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(0, c0), std::atan2(0, c1), std::atan2(0, c2)),
+                              atan2SingleAccuracy(setZero(), rSimd_c0c1c2));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(c0, 0), std::atan2(c1, 0), std::atan2(c2, 0)),
+                              atan2SingleAccuracy(rSimd_c0c1c2, setZero()));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(0, -c0), std::atan2(0, -c1), std::atan2(0, -c2)),
+                              atan2SingleAccuracy(setZero(), rSimd_m0m1m2));
+    GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom3R(std::atan2(-c0, 0), std::atan2(-c1, 0), std::atan2(-c2, 0)),
+                              atan2SingleAccuracy(rSimd_m0m1m2, setZero()));
+
     // degenerate value (origin) should return 0.0. At least IBM xlc 13.1.5 gets the reference
     // value wrong (-nan) at -O3 optimization, so we compare to the correct value (0.0) instead.
     GMX_EXPECT_SIMD_REAL_NEAR(setSimdRealFrom1R(0.0), atan2SingleAccuracy(setSimdRealFrom3R(0.0, 0.0, 0.0), setZero()));
index fa1570ffa4a6faa0f2320f3a04c8fe291b36ada6..0795606104d18ba125772c3fc9e3cc3fd5ac5795 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2014,2015, by the GROMACS development team, led by
+ * Copyright (c) 2014,2015,2017, by the GROMACS development team, led by
  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
  * and including many others, as listed in the AUTHORS file in the
  * top-level source directory and at http://www.gromacs.org.
@@ -39,6 +39,7 @@
 #include "gromacs/simd/simd.h"
 #include "gromacs/simd/vector_operations.h"
 
+#include "data.h"
 #include "simd.h"
 
 #if GMX_SIMD
@@ -61,13 +62,15 @@ typedef SimdTest SimdVectorOperationsTest;
 
 TEST_F(SimdVectorOperationsTest, iprod)
 {
-    SimdReal aX       = setSimdRealFrom3R(1, 2, 3);
-    SimdReal aY       = setSimdRealFrom3R(3, 0, 5);
-    SimdReal aZ       = setSimdRealFrom3R(4, 1, 8);
-    SimdReal bX       = setSimdRealFrom3R(8, 3, 6);
-    SimdReal bY       = setSimdRealFrom3R(2, 3, 1);
-    SimdReal bZ       = setSimdRealFrom3R(5, 7, 9);
-    SimdReal iprodRef = setSimdRealFrom3R(34, 13, 95);
+    SimdReal aX       = rSimd_c0c1c2;
+    SimdReal aY       = rSimd_c3c4c5;
+    SimdReal aZ       = rSimd_c6c7c8;
+    SimdReal bX       = rSimd_c3c0c4;
+    SimdReal bY       = rSimd_c4c6c8;
+    SimdReal bZ       = rSimd_c7c2c3;
+    SimdReal iprodRef = setSimdRealFrom3R(c0*c3 + c3*c4 + c6*c7,
+                                          c1*c0 + c4*c6 + c7*c2,
+                                          c2*c4 + c5*c8 + c8*c3);
 
     setUlpTol(2);
     GMX_EXPECT_SIMD_REAL_NEAR(iprodRef, iprod(aX, aY, aZ, bX, bY, bZ));
@@ -75,10 +78,12 @@ TEST_F(SimdVectorOperationsTest, iprod)
 
 TEST_F(SimdVectorOperationsTest, norm2)
 {
-    SimdReal simdX    = setSimdRealFrom3R(1, 2, 3);
-    SimdReal simdY    = setSimdRealFrom3R(3, 0, 5);
-    SimdReal simdZ    = setSimdRealFrom3R(4, 1, 8);
-    SimdReal norm2Ref = setSimdRealFrom3R(26, 5, 98);
+    SimdReal simdX    = rSimd_c0c1c2;
+    SimdReal simdY    = rSimd_c3c4c5;
+    SimdReal simdZ    = rSimd_c6c7c8;
+    SimdReal norm2Ref = setSimdRealFrom3R(c0*c0 + c3*c3 + c6*c6,
+                                          c1*c1 + c4*c4 + c7*c7,
+                                          c2*c2 + c5*c5 + c8*c8);
 
     setUlpTol(2);
     GMX_EXPECT_SIMD_REAL_NEAR(norm2Ref, norm2(simdX, simdY, simdZ));
@@ -86,15 +91,15 @@ TEST_F(SimdVectorOperationsTest, norm2)
 
 TEST_F(SimdVectorOperationsTest, cprod)
 {
-    SimdReal aX    = setSimdRealFrom3R(1, 2, 3);
-    SimdReal aY    = setSimdRealFrom3R(3, 0, 5);
-    SimdReal aZ    = setSimdRealFrom3R(4, 1, 8);
-    SimdReal bX    = setSimdRealFrom3R(8, 3, 6);
-    SimdReal bY    = setSimdRealFrom3R(2, 3, 1);
-    SimdReal bZ    = setSimdRealFrom3R(5, 7, 9);
-    SimdReal refcX = setSimdRealFrom3R(7, -3, 37);
-    SimdReal refcY = setSimdRealFrom3R(27, -11, 21);
-    SimdReal refcZ = setSimdRealFrom3R(-22, 6, -27);
+    SimdReal aX    = rSimd_c0c1c2;
+    SimdReal aY    = rSimd_c3c4c5;
+    SimdReal aZ    = rSimd_c6c7c8;
+    SimdReal bX    = rSimd_c3c0c4;
+    SimdReal bY    = rSimd_c4c6c8;
+    SimdReal bZ    = rSimd_c7c2c3;
+    SimdReal refcX = setSimdRealFrom3R( c3*c7-c6*c4, c4*c2-c7*c6, c5*c3-c8*c8 );
+    SimdReal refcY = setSimdRealFrom3R( c6*c3-c0*c7, c7*c0-c1*c2, c8*c4-c2*c3 );
+    SimdReal refcZ = setSimdRealFrom3R( c0*c4-c3*c3, c1*c6-c4*c0, c2*c8-c5*c4 );
     SimdReal cX, cY, cZ;
 
     cprod(aX, aY, aZ, bX, bY, bZ, &cX, &cY, &cZ);