From fa1d62c66cfd845fcfda33783a7881bca7aa8c1d Mon Sep 17 00:00:00 2001 From: Erik Lindahl Date: Fri, 8 Jul 2016 01:05:17 +0200 Subject: [PATCH] Work around compiler issue with random test gcc-4.8.4 running on 32-bit Linux fails a few tests for random distributions. This seems to be caused by the compiler doing something strange (that can lead to differences in the lsb) when we do not use the result as floating-point values, but rather do exact binary comparisions. This is valid C++, and bad behaviour of the compiler (IMHO), but technically it is not required to produce bitwise identical results at high optimization. However, by using floating-point tests with zero ULP tolerance the problem appears to go away. Fixes #1986. Change-Id: I252f37b46605424c02435af0fbf7a4f81b493eb8 --- .../random/tests/exponentialdistribution.cpp | 4 ++-- src/gromacs/random/tests/gammadistribution.cpp | 4 ++-- src/gromacs/random/tests/normaldistribution.cpp | 17 ++++++++++++++--- .../random/tests/tabulatednormaldistribution.cpp | 8 +++++--- .../random/tests/uniformrealdistribution.cpp | 21 +++++++++++++++------ 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/gromacs/random/tests/exponentialdistribution.cpp b/src/gromacs/random/tests/exponentialdistribution.cpp index c429e3ffd8..684242433c 100644 --- a/src/gromacs/random/tests/exponentialdistribution.cpp +++ b/src/gromacs/random/tests/exponentialdistribution.cpp @@ -106,7 +106,7 @@ TEST(ExponentialDistributionTest, Reset) valB = distB(rng); - EXPECT_EQ(valA, valB); + EXPECT_REAL_EQ_TOL(valA, valB, gmx::test::ulpTolerance(0)); } TEST(ExponentialDistributionTest, AltParam) @@ -122,7 +122,7 @@ TEST(ExponentialDistributionTest, AltParam) rngB.restart(); distA.reset(); distB.reset(); - EXPECT_EQ(distA(rngA), distB(rngB, paramA)); + EXPECT_REAL_EQ_TOL(distA(rngA), distB(rngB, paramA), gmx::test::ulpTolerance(0)); } } // namespace anonymous diff --git a/src/gromacs/random/tests/gammadistribution.cpp b/src/gromacs/random/tests/gammadistribution.cpp index b28bc083ec..2d3ce20c76 100644 --- a/src/gromacs/random/tests/gammadistribution.cpp +++ b/src/gromacs/random/tests/gammadistribution.cpp @@ -100,7 +100,7 @@ TEST(GammaDistributionTest, Reset) valB = distB(rng); - EXPECT_EQ(valA, valB); + EXPECT_REAL_EQ_TOL(valA, valB, gmx::test::ulpTolerance(0)); } TEST(GammaDistributionTest, AltParam) @@ -116,7 +116,7 @@ TEST(GammaDistributionTest, AltParam) rngB.restart(); distA.reset(); distB.reset(); - EXPECT_EQ(distA(rngA), distB(rngB, paramA)); + EXPECT_REAL_EQ_TOL(distA(rngA), distB(rngB, paramA), gmx::test::ulpTolerance(0)); } } // namespace anonymous diff --git a/src/gromacs/random/tests/normaldistribution.cpp b/src/gromacs/random/tests/normaldistribution.cpp index cfacf22017..a6d5022ce1 100644 --- a/src/gromacs/random/tests/normaldistribution.cpp +++ b/src/gromacs/random/tests/normaldistribution.cpp @@ -91,7 +91,7 @@ TEST(NormalDistributionTest, Reset) gmx::ThreeFry2x64<8> rng(123456, gmx::RandomDomain::Other); gmx::NormalDistribution distA(2.0, 5.0); gmx::NormalDistribution distB(2.0, 5.0); - gmx::NormalDistribution<>::result_type valA, valB; + gmx::NormalDistribution::result_type valA, valB; valA = distA(rng); @@ -101,7 +101,10 @@ TEST(NormalDistributionTest, Reset) valB = distB(rng); - EXPECT_EQ(valA, valB); + // Use floating-point test with no tolerance rather than + // exact test, since the latter leads to failures with + // 32-bit gcc-4.8.4 + EXPECT_REAL_EQ_TOL(valA, valB, gmx::test::ulpTolerance(0)); } TEST(NormalDistributionTest, AltParam) @@ -111,13 +114,21 @@ TEST(NormalDistributionTest, AltParam) gmx::NormalDistribution distA(2.0, 5.0); gmx::NormalDistribution distB; // default parameters gmx::NormalDistribution::param_type paramA(2.0, 5.0); + gmx::NormalDistribution::result_type valA, valB; EXPECT_NE(distA(rngA), distB(rngB)); rngA.restart(); rngB.restart(); distA.reset(); distB.reset(); - EXPECT_EQ(distA(rngA), distB(rngB, paramA)); + + valA = distA(rngA); + valB = distB(rngB, paramA); + + // Use floating-point test with no tolerance rather than + // exact test, since the latter leads to failures with + // 32-bit gcc-4.8.4 + EXPECT_REAL_EQ_TOL(valA, valB, gmx::test::ulpTolerance(0)); } } // namespace anonymous diff --git a/src/gromacs/random/tests/tabulatednormaldistribution.cpp b/src/gromacs/random/tests/tabulatednormaldistribution.cpp index a4e8fc652d..45fba63403 100644 --- a/src/gromacs/random/tests/tabulatednormaldistribution.cpp +++ b/src/gromacs/random/tests/tabulatednormaldistribution.cpp @@ -132,7 +132,7 @@ TEST(TabulatedNormalDistributionTest, Reset) valB = distB(rng); - EXPECT_EQ(valA, valB); + EXPECT_REAL_EQ_TOL(valA, valB, gmx::test::ulpTolerance(0)); } TEST(TabulatedNormalDistributionTest, AltParam) @@ -148,7 +148,7 @@ TEST(TabulatedNormalDistributionTest, AltParam) rngB.restart(); distA.reset(); distB.reset(); - EXPECT_EQ(distA(rngA), distB(rngB, paramA)); + EXPECT_REAL_EQ_TOL(distA(rngA), distB(rngB, paramA), gmx::test::ulpTolerance(0)); } TEST(TabulatedNormalDistributionTableTest, HasValidProperties) @@ -159,7 +159,9 @@ TEST(TabulatedNormalDistributionTableTest, HasValidProperties) size_t halfSize = table.size() / 2; double sumOfSquares = 0.0; - auto tolerance = gmx::test::ulpTolerance(1); + // accept errors of a few ULP since the exact value of the summation + // below will depend on whether the compiler issues FMA instructions + auto tolerance = gmx::test::ulpTolerance(10); for (size_t i = 0, iFromEnd = table.size()-1; i < halfSize; ++i, --iFromEnd) { EXPECT_REAL_EQ_TOL(table.at(i), -table.at(iFromEnd), tolerance) diff --git a/src/gromacs/random/tests/uniformrealdistribution.cpp b/src/gromacs/random/tests/uniformrealdistribution.cpp index f80f067cdf..6121eb463e 100644 --- a/src/gromacs/random/tests/uniformrealdistribution.cpp +++ b/src/gromacs/random/tests/uniformrealdistribution.cpp @@ -102,10 +102,10 @@ TEST(UniformRealDistributionTest, Logical) TEST(UniformRealDistributionTest, Reset) { - gmx::ThreeFry2x64<8> rng(123456, gmx::RandomDomain::Other); - gmx::UniformRealDistribution distA(2.0, 5.0); - gmx::UniformRealDistribution distB(2.0, 5.0); - gmx::UniformRealDistribution<>::result_type valA, valB; + gmx::ThreeFry2x64<8> rng(123456, gmx::RandomDomain::Other); + gmx::UniformRealDistribution distA(2.0, 5.0); + gmx::UniformRealDistribution distB(2.0, 5.0); + gmx::UniformRealDistribution::result_type valA, valB; valA = distA(rng); @@ -115,7 +115,9 @@ TEST(UniformRealDistributionTest, Reset) valB = distB(rng); - EXPECT_EQ(valA, valB); + // Use floating-point test with no tolerance rather than exact + // test, since the later fails with 32-bit gcc-4.8.4 + EXPECT_REAL_EQ_TOL(valA, valB, gmx::test::ulpTolerance(0)); } TEST(UniformRealDistributionTest, AltParam) @@ -125,13 +127,20 @@ TEST(UniformRealDistributionTest, AltParam) gmx::UniformRealDistribution distA(2.0, 5.0); gmx::UniformRealDistribution distB; // default parameters gmx::UniformRealDistribution::param_type paramA(2.0, 5.0); + gmx::UniformRealDistribution::result_type valA, valB; EXPECT_NE(distA(rngA), distB(rngB)); rngA.restart(); rngB.restart(); distA.reset(); distB.reset(); - EXPECT_EQ(distA(rngA), distB(rngB, paramA)); + + valA = distA(rngA); + valB = distB(rngB, paramA); + + // Use floating-point test with no tolerance rather than exact test, + // since the latter fails with 32-bit gcc-4.8.4 + EXPECT_REAL_EQ_TOL(valA, valB, gmx::test::ulpTolerance(0)); } } // namespace anonymous -- 2.11.4.GIT