/*
* 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.
* 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,
#
# 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.
gmx_add_unit_test(SimdUnitTests simd-test
bootstrap_loadstore.cpp
base.cpp
+ data.cpp
simd.cpp
simd_floatingpoint.cpp
simd_floatingpoint_util.cpp
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
/*
* 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/utility/basedefinitions.h"
#include "gromacs/utility/real.h"
+#include "data.h"
+
namespace gmx
{
namespace test
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)
{
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)
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)
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)
/*
* 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 "testutils/testasserts.h"
+#include "data.h"
+
namespace gmx
{
namespace test
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;
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));
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);
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));
}
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));
TEST(SimdScalarMathTest, pmeForceCorrection)
{
- real z2 = 0.51256;
+ real z2 = c0;
// Calculate reference value for z2!=0
real z = std::sqrt(z2);
TEST(SimdScalarMathTest, pmePotentialCorrection)
{
- real z2 = 0.51256;
+ real z2 = c0;
// Calculate reference value for z2!=0
real z = std::sqrt(z2);
TEST(SimdScalarMathTest, invsqrtPairSingleAccuracy)
{
- double x0 = 1.2345;
- double x1 = 9.8765;
+ double x0 = c1;
+ double x1 = c2;
double out0, out1;
TEST(SimdScalarMathTest, invSingleAccuracy)
{
- double x0 = 1.2345;
+ double x0 = c1;
EXPECT_EQ(1.0f/static_cast<float>(x0),
static_cast<float>(invSingleAccuracy(x0)));
TEST(SimdScalarMathTest, maskzInvsqrtSingleAccuracy)
{
- double x0 = 1.2345;
+ double x0 = c1;
EXPECT_EQ(invsqrt(static_cast<float>(x0)),
static_cast<float>(maskzInvsqrtSingleAccuracy(x0, true)));
TEST(SimdScalarMathTest, logSingleAccuracy)
{
- double x0 = 1.2345;
+ double x0 = c1;
EXPECT_EQ(std::log(static_cast<float>(x0)),
static_cast<float>(logSingleAccuracy(x0)));
TEST(SimdScalarMathTest, exp2SingleAccuracy)
{
- double x0 = 1.2345;
+ double x0 = c1;
EXPECT_EQ(std::exp2(static_cast<float>(x0)),
static_cast<float>(exp2SingleAccuracy(x0)));
TEST(SimdScalarMathTest, expSingleAccuracy)
{
- double x0 = 1.2345;
+ double x0 = c1;
EXPECT_EQ(std::exp(static_cast<float>(x0)),
static_cast<float>(expSingleAccuracy(x0)));
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);
TEST(SimdScalarMathTest, sinSingleAccuracy)
{
- double x0 = 0.51256;
+ double x0 = c0;
EXPECT_EQ(std::sin(static_cast<float>(x0)),
static_cast<float>(sinSingleAccuracy(x0)));
TEST(SimdScalarMathTest, cosSingleAccuracy)
{
- double x0 = 0.51256;
+ double x0 = c0;
EXPECT_EQ(std::cos(static_cast<float>(x0)),
static_cast<float>(cosSingleAccuracy(x0)));
TEST(SimdScalarMathTest, tanSingleAccuracy)
{
- double x0 = 0.51256;
+ double x0 = c0;
EXPECT_EQ(std::tan(static_cast<float>(x0)),
static_cast<float>(tanSingleAccuracy(x0)));
TEST(SimdScalarMathTest, asinSingleAccuracy)
{
- double x0 = 0.51256;
+ double x0 = c0;
EXPECT_EQ(std::asin(static_cast<float>(x0)),
static_cast<float>(asinSingleAccuracy(x0)));
TEST(SimdScalarMathTest, acosSingleAccuracy)
{
- double x0 = 0.51256;
+ double x0 = c0;
EXPECT_EQ(std::acos(static_cast<float>(x0)),
static_cast<float>(acosSingleAccuracy(x0)));
TEST(SimdScalarMathTest, atanSingleAccuracy)
{
- double x0 = 0.51256;
+ double x0 = c0;
EXPECT_EQ(std::atan(static_cast<float>(x0)),
static_cast<float>(atanSingleAccuracy(x0)));
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)),
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));
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));
/*
* 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
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;
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;
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]);
{
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]);
TEST(SimdScalarTest, expandScalarsToTriplets)
{
- real scalar = 1.234;
+ real scalar = c1;
real t0, t1, t2;
expandScalarsToTriplets(scalar, &t0, &t1, &t2);
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;
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;
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());
}
/*! \} */
/*
* 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.
* 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);
/*
* 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 "base.h"
+#include "data.h"
#if GMX_SIMD
* 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.
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;
/*
* 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.
#include "gromacs/simd/simd.h"
#include "gromacs/utility/basedefinitions.h"
+#include "data.h"
+
#if GMX_SIMD
namespace gmx
#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)
/*
* 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.
#include "gromacs/simd/simd.h"
#include "base.h"
+#include "data.h"
#if GMX_SIMD
/*! \{ */
#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
/*
* 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"
#include "simd4.h"
#if GMX_SIMD
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)
* 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)
/* 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)
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)
* 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++)
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)
// 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);
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());
}
}
/*
* 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.
#include "gromacs/simd/simd.h"
#include "gromacs/simd/vector_operations.h"
+#include "data.h"
#include "simd4.h"
#if GMX_SIMD
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));
/*
* 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 "testutils/testasserts.h"
+#include "data.h"
#include "simd.h"
#if GMX_SIMD
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)
* 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)
/* 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)
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)
* 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++)
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
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);
// 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);
/*
* 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.
{
// 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);
}
}
// 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++)
// 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++)
// 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++)
// 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++)
// 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++)
}
// 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);
}
}
// 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);
}
/*
* 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.
#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));
{
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
::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.
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) */
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));
}
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 */
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));
}
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()));
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)
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()));
/*
* 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.
#include "gromacs/simd/simd.h"
#include "gromacs/simd/vector_operations.h"
+#include "data.h"
#include "simd.h"
#if GMX_SIMD
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));
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));
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);