Skip to content

Commit

Permalink
[Math] Fix test of vectorisable Kahan sum.
Browse files Browse the repository at this point in the history
- Replace all EXPECT_EQ macros by EXPECT_FLOAT_EQ, which allows results
to be different by a few ULPs, because some architectures in the CI are
not able to yield numbers accurate to the last bit.
  • Loading branch information
hageboeck committed Aug 30, 2019
1 parent b86f39d commit 8c56953
Showing 1 changed file with 22 additions and 18 deletions.
40 changes: 22 additions & 18 deletions math/mathcore/test/testKahan.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ TEST(KahanTest, LegacySum)
LegacyKahanSum<double> k;
k.Add(numbers.begin(), numbers.end());
auto result = LegacyKahanSum<double>::Accumulate(numbers.begin(), numbers.end());
EXPECT_EQ(k.Result(), result);
EXPECT_FLOAT_EQ(k.Result(), result);

LegacyKahanSum<double> k2;
LegacyKahanSum<double> k3(1);
k2.Add(1);
k2.Add(numbers.begin(), numbers.end());
k3.Add(numbers.begin(), numbers.end());
EXPECT_EQ(k2.Result(), k3.Result());
EXPECT_FLOAT_EQ(k2.Result(), k3.Result());

}

Expand All @@ -78,7 +78,7 @@ TEST(KahanTest, Compensation)
<< "Compensation fails with standard sum.";

auto result = LegacyKahanSum<double>::Accumulate(numbers.begin(), numbers.end());
EXPECT_EQ(result, 1. + 1.E-15) << "Kahan compensation works";
EXPECT_FLOAT_EQ(result, 1. + 1.E-15) << "Kahan compensation works";
}


Expand All @@ -88,7 +88,7 @@ TEST(KahanTest, VectorisableVsLegacy)
//Should more or less accumulate:
std::uniform_real_distribution<double> realLarge(1.E-13, 1.);
//None of these should be possible to accumulate:
const double a = 1.E-20, b = 1.E-16;
constexpr double a = 1.E-20, b = 1.E-16;
std::uniform_real_distribution<double> realSmall(a, b);

std::vector<double> summableNumbers;
Expand Down Expand Up @@ -116,13 +116,17 @@ TEST(KahanTest, VectorisableVsLegacy)
LegacyKahanSum<double>::Accumulate(summableNumbers.begin(), summableNumbers.end());
const double allLegacy =
LegacyKahanSum<double>::Accumulate(allNumbers.begin(), allNumbers.end());
EXPECT_EQ(summableNormal, summableLegacy) << "Legacy Kahan works on summable numbers.";
EXPECT_NEAR(allLegacy-allNormal, 1.E6 * 0.5 * (a+b), 1.E-13) << "Cancellation errors reasonable";
EXPECT_FLOAT_EQ(summableNormal, summableLegacy)
<< "Test that legacy Kahan works on numbers summable without errors.";
// Expect to miss 1.E6 numbers that are on average equal to mean({a,b})
constexpr double expectedCancellationError = 1.E6 * 0.5*(a+b);
EXPECT_NEAR(allLegacy-allNormal, expectedCancellationError, expectedCancellationError/100.)
<< "Test that legacy Kahan doesn't miss the numbers that std::accumulate misses.";


// Test that vectorisable Kahan yields identical results when used with 1 accumulator
auto Kahan1Acc = ROOT::Math::KahanSum<>::Accumulate(allNumbers.begin(), allNumbers.end());
EXPECT_EQ(allLegacy, Kahan1Acc.Sum()) << "New implementation with 1 accumulator identical.";
EXPECT_FLOAT_EQ(allLegacy, Kahan1Acc.Sum()) << "New implementation with 1 accumulator identical.";


// Test with 4 accumulators
Expand All @@ -135,16 +139,16 @@ TEST(KahanTest, VectorisableVsLegacy)
for (unsigned int i=0; i<allNumbers.size(); ++i) {
kahan4AccAll.AddIndexed(allNumbers[i], i);
}
EXPECT_EQ(summableLegacy, kahan4AccSummable.Sum()) << "Both Kahans identical on summable.";
EXPECT_EQ(allLegacy, kahan4AccAll.Sum()) << "Both Kahans identical on numbers with cancellation.";
EXPECT_FLOAT_EQ(summableLegacy, kahan4AccSummable.Sum()) << "Both Kahans identical on summable.";
EXPECT_FLOAT_EQ(allLegacy, kahan4AccAll.Sum()) << "Both Kahans identical on numbers with cancellation.";


// Test with 2 accumulators
ROOT::Math::KahanSum<double, 2> kahan2AccAll;
for (unsigned int i=0; i<allNumbers.size(); ++i) {
kahan2AccAll.AddIndexed(allNumbers[i], i);
}
EXPECT_EQ(kahan2AccAll.Sum(), kahan4AccAll.Sum()) << "Kahan(2,4) identical.";
EXPECT_FLOAT_EQ(kahan2AccAll.Sum(), kahan4AccAll.Sum()) << "Kahan(2,4) identical.";
EXPECT_NEAR(kahan2AccAll.Carry(), kahan4AccAll.Carry(), 1.E-12) << "Kahan(2,4) identical.";


Expand All @@ -153,30 +157,30 @@ TEST(KahanTest, VectorisableVsLegacy)
for (unsigned int i=0; i<allNumbers.size(); ++i) {
kahan8AccAll.AddIndexed(allNumbers[i], i);
}
EXPECT_EQ(kahan8AccAll.Sum(), kahan4AccAll.Sum()) << "Kahan(8,4) identical.";
EXPECT_FLOAT_EQ(kahan8AccAll.Sum(), kahan4AccAll.Sum()) << "Kahan(8,4) identical.";
EXPECT_NEAR(kahan8AccAll.Carry(), kahan4AccAll.Carry(), 1.E-12) << "Kahan(8,4) identical.";


// Test different filling methods
ROOT::Math::KahanSum<double, 4> allVecKahan2;
allVecKahan2.Add(allNumbers);
EXPECT_EQ(allVecKahan2.Sum(), kahan4AccAll.Sum()) << "Kahan from container.";
EXPECT_EQ(allVecKahan2.Carry(), kahan4AccAll.Carry()) << "Kahan from container.";
EXPECT_FLOAT_EQ(allVecKahan2.Sum(), kahan4AccAll.Sum()) << "Kahan from container.";
EXPECT_FLOAT_EQ(allVecKahan2.Carry(), kahan4AccAll.Carry()) << "Kahan from container.";


ROOT::Math::KahanSum<double, 4> allVecKahan3;
allVecKahan3.Add(allNumbers.begin(), allNumbers.end());
EXPECT_EQ(allVecKahan3.Sum(), kahan4AccAll.Sum()) << "Kahan from iterators.";
EXPECT_EQ(allVecKahan3.Carry(), kahan4AccAll.Carry()) << "Kahan from iterators.";
EXPECT_FLOAT_EQ(allVecKahan3.Sum(), kahan4AccAll.Sum()) << "Kahan from iterators.";
EXPECT_FLOAT_EQ(allVecKahan3.Carry(), kahan4AccAll.Carry()) << "Kahan from iterators.";


auto allVecKahan4 = ROOT::Math::KahanSum<double, 4>::Accumulate(allNumbers.begin(), allNumbers.end());
EXPECT_EQ(allVecKahan4.Sum(), kahan4AccAll.Sum()) << "Kahan from Accumulate().";
EXPECT_EQ(allVecKahan4.Carry(), kahan4AccAll.Carry()) << "Kahan from Accumulate().";
EXPECT_FLOAT_EQ(allVecKahan4.Sum(), kahan4AccAll.Sum()) << "Kahan from Accumulate().";
EXPECT_FLOAT_EQ(allVecKahan4.Carry(), kahan4AccAll.Carry()) << "Kahan from Accumulate().";


// Test adding an offset
auto allVecKahan5 = ROOT::Math::KahanSum<double, 4>::Accumulate(allNumbers.begin(), allNumbers.end(), 10.);
EXPECT_EQ(allVecKahan5.Sum(), kahan4AccAll.Sum() + 10.) << "Initial value works.";
EXPECT_FLOAT_EQ(allVecKahan5.Sum(), kahan4AccAll.Sum() + 10.) << "Initial value works.";
}

0 comments on commit 8c56953

Please sign in to comment.