From d72cb5f8dcbc3433a5a819741818a59cce30205f Mon Sep 17 00:00:00 2001 From: rboston628 Date: Tue, 24 Sep 2024 09:45:36 -0400 Subject: [PATCH] should be three failing unit tests --- Framework/API/src/NumericAxis.cpp | 8 +- Framework/API/src/WorkspaceOpOverloads.cpp | 10 +- .../CalculateCarpenterSampleCorrection.cpp | 8 +- .../Algorithms/src/CompareWorkspaces.cpp | 58 +++----- .../src/FindCenterOfMassPosition2.cpp | 10 +- Framework/Algorithms/src/FitPeak.cpp | 11 +- .../Algorithms/src/He3TubeEfficiency.cpp | 9 +- .../SampleLogsBehaviour.cpp | 3 +- Framework/Algorithms/src/Stitch1D.cpp | 5 +- Framework/Algorithms/src/UnwrapMonitor.cpp | 5 +- .../Algorithms/test/CompareWorkspacesTest.h | 54 +++++++ Framework/Crystal/src/FindSXPeaksHelper.cpp | 7 +- .../Crystal/src/IntegratePeakTimeSlices.cpp | 21 ++- Framework/Crystal/src/PredictPeaks.cpp | 13 +- .../src/PDLoadCharacterizations.cpp | 12 +- Framework/DataHandling/src/SaveGSS.cpp | 5 +- .../inc/MantidDataObjects/TableColumn.h | 33 ++--- .../MantidKernel/FloatingPointComparison.h | 7 +- .../Kernel/src/FloatingPointComparison.cpp | 137 +++++++++++++++--- Framework/Kernel/src/V3D.cpp | 20 +-- .../Kernel/test/FloatingPointComparisonTest.h | 51 ++++++- .../src/ComponentCreationHelper.cpp | 7 +- .../CMake/CppCheck_Suppressions.txt.in | 54 +++---- 23 files changed, 361 insertions(+), 187 deletions(-) diff --git a/Framework/API/src/NumericAxis.cpp b/Framework/API/src/NumericAxis.cpp index 22f0989bbd98..4b5e2babc57b 100644 --- a/Framework/API/src/NumericAxis.cpp +++ b/Framework/API/src/NumericAxis.cpp @@ -9,6 +9,7 @@ //---------------------------------------------------------------------- #include "MantidAPI/NumericAxis.h" #include "MantidKernel/Exception.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/VectorHelper.h" #include @@ -22,12 +23,17 @@ Mantid::Kernel::Logger g_log("NumericAxis"); class EqualWithinTolerance { public: explicit EqualWithinTolerance(double tolerance) : m_tolerance(tolerance){}; + /** + * This handles NaNs and infs differently than the FloatingPointComparison operations. + * If this is not necessary, then this entire class may be replaced with + * Mantid::Kernel::withinAbsoluteDifference + */ bool operator()(double a, double b) { if (std::isnan(a) && std::isnan(b)) return true; if (std::isinf(a) && std::isinf(b)) return true; - return std::abs(a - b) <= m_tolerance; + return Mantid::Kernel::withinAbsoluteDifference(a, b, m_tolerance); } private: diff --git a/Framework/API/src/WorkspaceOpOverloads.cpp b/Framework/API/src/WorkspaceOpOverloads.cpp index 47cea3d4b05d..3d5f6df67642 100644 --- a/Framework/API/src/WorkspaceOpOverloads.cpp +++ b/Framework/API/src/WorkspaceOpOverloads.cpp @@ -13,6 +13,7 @@ #include "MantidAPI/MatrixWorkspace.h" #include "MantidAPI/WorkspaceFactory.h" #include "MantidAPI/WorkspaceGroup.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/Property.h" #include @@ -376,10 +377,10 @@ bool WorkspaceHelpers::matchingBins(const MatrixWorkspace &ws1, const MatrixWork const double secondWS = std::accumulate(ws2.x(0).begin(), ws2.x(0).end(), 0.); if (std::abs(firstWS) < 1.0E-7 && std::abs(secondWS) < 1.0E-7) { for (size_t i = 0; i < ws1.x(0).size(); i++) { - if (std::abs(ws1.x(0)[i] - ws2.x(0)[i]) > 1.0E-7) + if (!Kernel::withinAbsoluteDifference(ws1.x(0)[i], ws2.x(0)[i], 1.0E-7)) return false; } - } else if (std::abs(firstWS - secondWS) / std::max(std::abs(firstWS), std::abs(secondWS)) > 1.0E-7) + } else if (!Kernel::withinRelativeDifference(firstWS, secondWS, 1.0E-7)) return false; // If we were only asked to check the first spectrum, return now @@ -409,11 +410,10 @@ bool WorkspaceHelpers::matchingBins(const MatrixWorkspace &ws1, const MatrixWork const double secondWSLoop = std::accumulate(ws2.x(i).begin(), ws2.x(i).end(), 0.); if (std::abs(firstWSLoop) < 1.0E-7 && std::abs(secondWSLoop) < 1.0E-7) { for (size_t j = 0; j < ws1.x(i).size(); j++) { - if (std::abs(ws1.x(i)[j] - ws2.x(i)[j]) > 1.0E-7) + if (!Kernel::withinAbsoluteDifference(ws1.x(i)[j], ws2.x(i)[j], 1.0E-7)) return false; } - } else if (std::abs(firstWSLoop - secondWSLoop) / std::max(std::abs(firstWSLoop), std::abs(secondWSLoop)) > - 1.0E-7) + } else if (!Kernel::withinRelativeDifference(firstWSLoop, secondWSLoop, 1.0E-7)) return false; } diff --git a/Framework/Algorithms/src/CalculateCarpenterSampleCorrection.cpp b/Framework/Algorithms/src/CalculateCarpenterSampleCorrection.cpp index bda9b39a19f9..281535b354ec 100644 --- a/Framework/Algorithms/src/CalculateCarpenterSampleCorrection.cpp +++ b/Framework/Algorithms/src/CalculateCarpenterSampleCorrection.cpp @@ -15,6 +15,7 @@ #include "MantidDataObjects/WorkspaceCreation.h" #include "MantidGeometry/Instrument.h" #include "MantidKernel/CompositeValidator.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/Material.h" #include @@ -128,12 +129,11 @@ void CalculateCarpenterSampleCorrection::exec() { const Material &sampleMaterial = inputWksp->sample().getMaterial(); if (sampleMaterial.totalScatterXSection() != 0.0) { g_log.information() << "Using material \"" << sampleMaterial.name() << "\" from workspace\n"; - if (std::abs(coeff1 - 2.8) < std::numeric_limits::epsilon()) + if (Kernel::equals(coeff1, 2.8)) coeff1 = sampleMaterial.absorbXSection(LAMBDA_REF) / LAMBDA_REF; - if ((std::abs(coeff2 - 0.0721) < std::numeric_limits::epsilon()) && - (!isEmpty(sampleMaterial.numberDensity()))) + if (Kernel::equals(coeff2, 0.0721) && !isEmpty(sampleMaterial.numberDensity())) coeff2 = sampleMaterial.numberDensity(); - if (std::abs(coeff3 - 5.1) < std::numeric_limits::epsilon()) + if (Kernel::equals(coeff3, 5.1)) coeff3 = sampleMaterial.totalScatterXSection(); } else // Save input in Sample with wrong atomic number and name { diff --git a/Framework/Algorithms/src/CompareWorkspaces.cpp b/Framework/Algorithms/src/CompareWorkspaces.cpp index 9119d8064bdc..4e3a200a0bd1 100644 --- a/Framework/Algorithms/src/CompareWorkspaces.cpp +++ b/Framework/Algorithms/src/CompareWorkspaces.cpp @@ -22,6 +22,7 @@ #include "MantidGeometry/Crystal/IPeak.h" #include "MantidGeometry/Instrument/ComponentInfo.h" #include "MantidGeometry/Instrument/DetectorInfo.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/Unit.h" namespace Mantid::Algorithms { @@ -71,23 +72,18 @@ int compareEventLists(Kernel::Logger &logger, const EventList &el1, const EventL const auto &e1 = events1[i]; const auto &e2 = events2[i]; - bool diffpulse = false; - bool difftof = false; - bool diffweight = false; - if (std::abs(e1.pulseTime().totalNanoseconds() - e2.pulseTime().totalNanoseconds()) > tolPulse) { - diffpulse = true; - ++numdiffpulse; - } - if (std::abs(e1.tof() - e2.tof()) > tolTof) { - difftof = true; - ++numdifftof; - } + bool diffpulse = + !withinAbsoluteDifference(e1.pulseTime().totalNanoseconds(), e2.pulseTime().totalNanoseconds(), tolPulse); + bool difftof = !withinAbsoluteDifference(e1.tof(), e2.tof(), tolTof); + bool diffweight = !withinAbsoluteDifference(e1.weight(), e2.weight(), tolWeight); if (diffpulse && difftof) - ++numdiffboth; - if (std::abs(e1.weight() - e2.weight()) > tolWeight) { - diffweight = true; - ++numdiffweight; - } + numdiffboth++; + if (diffpulse) + numdiffpulse++; + if (difftof) + numdifftof++; + if (diffweight) + numdiffweight++; bool same = (!diffpulse) && (!difftof) && (!diffweight); if (!same) { @@ -663,6 +659,8 @@ bool CompareWorkspaces::checkData(const API::MatrixWorkspace_const_sptr &ws1, if (checkError && !err) err = !m_compare(E1[j], E2[j]); if (err) { + printf("MISMATCH ws (%d, %d) : %le %le | %le %le | %le %le \n", i, j, X1[j], X2[j], Y1[j], Y2[j], E1[j], + E2[j]); if (logDebug) { g_log.debug() << "Data mismatch at cell (hist#,bin#): (" << i << "," << j << ")\n"; g_log.debug() << " Dataset #1 (X,Y,E) = (" << X1[j] << "," << Y1[j] << "," << E1[j] << ")\n"; @@ -1049,6 +1047,7 @@ void CompareWorkspaces::doPeaksComparison(PeaksWorkspace_sptr tws1, PeaksWorkspa } const bool isRelErr = getProperty("ToleranceRelErr"); + const bool checkAllData = getProperty("CheckAllData"); for (int i = 0; i < tws1->getNumberPeaks(); i++) { const Peak &peak1 = tws1->getPeak(i); const Peak &peak2 = tws2->getPeak(i); @@ -1121,13 +1120,15 @@ void CompareWorkspaces::doPeaksComparison(PeaksWorkspace_sptr tws1, PeaksWorkspa !m_compare(v1[2], v2[2]); // } if (mismatch) { + printf("MISTMACH col %s - (%d, %d) values %le %le\n", name.c_str(), i, j, s1, s2); g_log.notice(name); g_log.notice() << "data mismatch in column name = " << name << "\n" << "cell (row#, col#): (" << i << "," << j << ")\n" << "value1 = " << s1 << "\n" << "value2 = " << s2 << "\n"; recordMismatch("Data mismatch"); - return; + if (!checkAllData) + return; } } } @@ -1163,6 +1164,7 @@ void CompareWorkspaces::doLeanElasticPeaksComparison(const LeanElasticPeaksWorks const double tolerance = getProperty("Tolerance"); const bool isRelErr = getProperty("ToleranceRelErr"); + const bool checkAllData = getProperty("CheckAllData"); for (int peakIndex = 0; peakIndex < ipws1->getNumberPeaks(); peakIndex++) { for (size_t j = 0; j < ipws1->columnCount(); j++) { std::shared_ptr col = ipws1->getColumn(j); @@ -1236,13 +1238,15 @@ void CompareWorkspaces::doLeanElasticPeaksComparison(const LeanElasticPeaksWorks mismatch = true; } if (mismatch) { + printf("MISTMACH (%d, %d) values %le %le\n", peakIndex, j, s1, s2); g_log.notice(name); g_log.notice() << "data mismatch in column name = " << name << "\n" << "cell (row#, col#): (" << peakIndex << "," << j << ")\n" << "value1 = " << s1 << "\n" << "value2 = " << s2 << "\n"; recordMismatch("Data mismatch"); - return; + if (!checkAllData) + return; } } } @@ -1360,8 +1364,7 @@ this error is within the limits requested. @returns true if absolute difference is within the tolerance; false otherwise */ bool CompareWorkspaces::withinAbsoluteTolerance(double const x1, double const x2, double const atol) { - // NOTE !(|x1-x2| > atol) is not the same as |x1-x2| <= atol - return !(std::abs(x1 - x2) > atol); + return Kernel::withinAbsoluteDifference(x1, x2, atol); } //------------------------------------------------------------------------------------------------ @@ -1376,19 +1379,6 @@ this error is within the limits requested. @returns true if error or false if the relative value is within the limits requested */ bool CompareWorkspaces::withinRelativeTolerance(double const x1, double const x2, double const rtol) { - // calculate difference - double const num = std::abs(x1 - x2); - // return early if the values are equal - if (num == 0.0) - return true; - // create the average magnitude for comparison - double const den = 0.5 * (std::abs(x1) + std::abs(x2)); - // return early, possibly avoids a multiplication - // NOTE if den<1, then divsion will only make num larger - // NOTE if den<1 but num<=rtol, we cannot conclude anything - if (den <= 1.0 && num > rtol) - return false; - // NOTE !(num > rtol*den) is not the same as (num <= rtol*den) - return !(num > (rtol * den)); + return Kernel::withinRelativeDifference(x1, x2, rtol); } } // namespace Mantid::Algorithms diff --git a/Framework/Algorithms/src/FindCenterOfMassPosition2.cpp b/Framework/Algorithms/src/FindCenterOfMassPosition2.cpp index 522212a9f439..7cadf8c502e9 100644 --- a/Framework/Algorithms/src/FindCenterOfMassPosition2.cpp +++ b/Framework/Algorithms/src/FindCenterOfMassPosition2.cpp @@ -18,6 +18,7 @@ #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/BoundedValidator.h" #include "MantidKernel/CompositeValidator.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/PhysicalConstants.h" namespace Mantid::Algorithms { @@ -29,10 +30,11 @@ using namespace API; using namespace Geometry; using namespace DataObjects; -namespace { // anonymous namespace +// namespace { // anonymous namespace /// Equal within machine tolerance -bool almost_equals(const double a, const double b) { return fabs(a - b) < std::numeric_limits::min(); } -} // anonymous namespace +// bool almost_equals(double const a, double const b) { return Kernel::equals(a, b); } +// bool almost_equals(const double a, const double b) { return fabs(a - b) < std::numeric_limits::min(); } +// } // anonymous namespace void FindCenterOfMassPosition2::init() { const auto wsValidator = std::make_shared(); @@ -113,7 +115,7 @@ void FindCenterOfMassPosition2::findCenterOfMass(const API::MatrixWorkspace_sptr // Check to see if we have the same result // as the previous iteration - if (almost_equals(distanceFromPrevious, distanceFromPreviousPrevious)) { + if (Kernel::equals(distanceFromPrevious, distanceFromPreviousPrevious)) { totalLocalMinima++; } else { totalLocalMinima = 0; diff --git a/Framework/Algorithms/src/FitPeak.cpp b/Framework/Algorithms/src/FitPeak.cpp index aa32a557c542..5b1e5c82d5c3 100644 --- a/Framework/Algorithms/src/FitPeak.cpp +++ b/Framework/Algorithms/src/FitPeak.cpp @@ -237,7 +237,7 @@ void FitOneSinglePeak::setupGuessedFWHM(double usrwidth, int minfwhm, int maxfwh void FitOneSinglePeak::setFitPeakCriteria(bool usepeakpostol, double peakpostol) { m_usePeakPositionTolerance = usepeakpostol; if (usepeakpostol) { - m_peakPositionTolerance = fabs(peakpostol); + m_peakPositionTolerance = std::abs(peakpostol); if (peakpostol < 1.0E-13) g_log.warning("Peak position tolerance is very tight. "); } @@ -931,7 +931,7 @@ void FitOneSinglePeak::processNStoreFitResult(double rwp, bool storebkgd) { double f_centre = m_peakFunc->centre(); if (m_usePeakPositionTolerance) { // Peak position criteria is on position tolerance - if (fabs(f_centre - m_userPeakCentre) > m_peakPositionTolerance) { + if (std::abs(f_centre - m_userPeakCentre) > m_peakPositionTolerance) { rwp = DBL_MAX; failreason = "Peak centre out of tolerance. "; fitsuccess = false; @@ -1407,8 +1407,11 @@ void FitPeak::setupOutput(const std::map &m_fitErrorPeakFun // TODO - Need to retrieve useful information from FitOneSinglePeak object // (think of how) const auto &vecX = m_dataWS->x(m_wsIndex); - const size_t i_minFitX = getIndex(vecX, m_minFitX); - const size_t i_maxFitX = getIndex(vecX, m_maxFitX); + // NOTE these scoped variables were shadowed, and were not actually being used in the calculations below. + // It is unclear if this represents and error, or was due to misunderstanding of member variables. + // Existing tests expect the current behavior, which does not use these. + // const size_t i_minFitX = getIndex(vecX, m_minFitX); + // const size_t i_maxFitX = getIndex(vecX, m_maxFitX); // Data workspace const size_t nspec = 3; diff --git a/Framework/Algorithms/src/He3TubeEfficiency.cpp b/Framework/Algorithms/src/He3TubeEfficiency.cpp index 48c1ebbeff78..d485891a61df 100644 --- a/Framework/Algorithms/src/He3TubeEfficiency.cpp +++ b/Framework/Algorithms/src/He3TubeEfficiency.cpp @@ -20,6 +20,7 @@ #include "MantidKernel/ArrayBoundedValidator.h" #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/CompositeValidator.h" +#include "MantidKernel/FloatingPointComparison.h" #include #include @@ -216,7 +217,7 @@ double He3TubeEfficiency::calculateExponential(std::size_t spectraIndex, const G double sinTheta = std::sqrt(1.0 - cosTheta * cosTheta); const double straight_path = detDiameter - twiceTubeThickness; - if (std::fabs(straight_path - 0.0) < TOL) { + if (Kernel::withinAbsoluteDifference(straight_path, 0.0, TOL)) { throw std::out_of_range("Twice tube thickness cannot be greater than " "or equal to the tube diameter"); } @@ -245,7 +246,7 @@ void He3TubeEfficiency::getDetectorGeometry(const Geometry::IDetector &det, doub if (it == m_shapeCache.end()) { double xDist = distToSurface(Kernel::V3D(DIST_TO_UNIVERSE_EDGE, 0, 0), shape_sptr.get()); double zDist = distToSurface(Kernel::V3D(0, 0, DIST_TO_UNIVERSE_EDGE), shape_sptr.get()); - if (std::abs(zDist - xDist) < 1e-8) { + if (Kernel::withinAbsoluteDifference(zDist, xDist, 1e-8)) { detRadius = zDist / 2.0; detAxis = Kernel::V3D(0, 1, 0); // assume radii in z and x and the axis is in the y @@ -253,7 +254,7 @@ void He3TubeEfficiency::getDetectorGeometry(const Geometry::IDetector &det, doub return; } double yDist = distToSurface(Kernel::V3D(0, DIST_TO_UNIVERSE_EDGE, 0), shape_sptr.get()); - if (std::abs(yDist - zDist) < 1e-8) { + if (Kernel::withinAbsoluteDifference(yDist, zDist, 1e-8)) { detRadius = yDist / 2.0; detAxis = Kernel::V3D(1, 0, 0); // assume that y and z are radii of the cylinder's circular cross-section @@ -262,7 +263,7 @@ void He3TubeEfficiency::getDetectorGeometry(const Geometry::IDetector &det, doub return; } - if (std::abs(xDist - yDist) < 1e-8) { + if (Kernel::withinAbsoluteDifference(xDist, yDist, 1e-8)) { detRadius = xDist / 2.0; detAxis = Kernel::V3D(0, 0, 1); PARALLEL_CRITICAL(deteff_shapecachec) { m_shapeCache.insert({shape_sptr.get(), {detRadius, detAxis}}); } diff --git a/Framework/Algorithms/src/RunCombinationHelpers/SampleLogsBehaviour.cpp b/Framework/Algorithms/src/RunCombinationHelpers/SampleLogsBehaviour.cpp index 95b03bc7c097..b11b3a2e742d 100644 --- a/Framework/Algorithms/src/RunCombinationHelpers/SampleLogsBehaviour.cpp +++ b/Framework/Algorithms/src/RunCombinationHelpers/SampleLogsBehaviour.cpp @@ -10,6 +10,7 @@ #include "MantidAPI/Run.h" #include "MantidAlgorithms/RunCombinationHelpers/SampleLogsBehaviour.h" #include "MantidGeometry/Instrument.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/Property.h" #include "MantidKernel/StringTokenizer.h" #include "MantidKernel/Strings.h" @@ -531,7 +532,7 @@ void SampleLogsBehaviour::checkErrorProperty(const MatrixWorkspace &addeeWS, Pro bool SampleLogsBehaviour::isWithinTolerance(const SampleLogBehaviour &behaviour, const double addeeWSNumericValue, const double outWSNumericValue) { if (behaviour.isNumeric && behaviour.tolerance > 0.0) { - return std::abs(addeeWSNumericValue - outWSNumericValue) < behaviour.tolerance; + return Kernel::withinAbsoluteDifference(addeeWSNumericValue, outWSNumericValue, behaviour.tolerance); } return false; diff --git a/Framework/Algorithms/src/Stitch1D.cpp b/Framework/Algorithms/src/Stitch1D.cpp index 0fa8f61ab032..c23abacb4604 100644 --- a/Framework/Algorithms/src/Stitch1D.cpp +++ b/Framework/Algorithms/src/Stitch1D.cpp @@ -16,6 +16,7 @@ #include "MantidHistogramData/HistogramY.h" #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/BoundedValidator.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/MultiThreaded.h" #include "MantidKernel/PropertyWithValue.h" #include "MantidKernel/RebinParamsValidator.h" @@ -491,10 +492,10 @@ void Stitch1D::exec() { const double xMin = params.front(); const double xMax = params.back(); - if (std::abs(xMin - startOverlap) < 1E-6) + if (Kernel::withinAbsoluteDifference(xMin, startOverlap, 1E-6)) startOverlap = xMin; - if (std::abs(xMax - endOverlap) < 1E-6) + if (Kernel::withinAbsoluteDifference(xMax, endOverlap, 1E-6)) endOverlap = xMax; if (startOverlap < xMin) { diff --git a/Framework/Algorithms/src/UnwrapMonitor.cpp b/Framework/Algorithms/src/UnwrapMonitor.cpp index 754d34d7a27d..55b65c13d475 100644 --- a/Framework/Algorithms/src/UnwrapMonitor.cpp +++ b/Framework/Algorithms/src/UnwrapMonitor.cpp @@ -16,6 +16,7 @@ #include "MantidGeometry/Instrument.h" #include "MantidKernel/BoundedValidator.h" #include "MantidKernel/CompositeValidator.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/PhysicalConstants.h" #include "MantidKernel/UnitFactory.h" @@ -204,7 +205,7 @@ const std::vector UnwrapMonitor::unwrapX(std::vector &newX, const i const double wavelength = m_conversionConstant / velocity; newX.emplace_back(wavelength); // Remove the duplicate boundary bin - if (tof == m_Tmax && std::abs(wavelength - tempX_L.front()) < 1.0e-5) + if (tof == m_Tmax && Kernel::withinAbsoluteDifference(wavelength, tempX_L.front(), 1.0e-5)) newX.pop_back(); // Record the bins that fall in this range for copying over the data & // errors @@ -223,7 +224,7 @@ const std::vector UnwrapMonitor::unwrapX(std::vector &newX, const i // Record the point at which the unwrapped sections are joined, first time // through only - Property *join = getProperty("JoinWavelength"); + Property const *join = getProperty("JoinWavelength"); if (join->isDefault()) { g_log.information() << "Joining wavelength: " << tempX_L.front() << " Angstrom\n"; setProperty("JoinWavelength", tempX_L.front()); diff --git a/Framework/Algorithms/test/CompareWorkspacesTest.h b/Framework/Algorithms/test/CompareWorkspacesTest.h index d97b3b71fa8b..44fc3da12869 100644 --- a/Framework/Algorithms/test/CompareWorkspacesTest.h +++ b/Framework/Algorithms/test/CompareWorkspacesTest.h @@ -1193,6 +1193,60 @@ class CompareWorkspacesTest : public CxxTest::TestSuite { TS_ASSERT_EQUALS(alg.getPropertyValue("Result"), PROPERTY_VALUE_TRUE); } + void test_equal_tableworkspaces_match() { + std::string const col_type("double"), col_name("aColumn"); + std::vector col_values{1.0, 2.0, 3.0}; + // create the table workspaces + Mantid::API::ITableWorkspace_sptr table1 = WorkspaceFactory::Instance().createTable(); + table1->addColumn(col_type, col_name); + for (double val : col_values) { + TableRow newrow = table1->appendRow(); + newrow << val; + } + Mantid::API::ITableWorkspace_sptr table2 = WorkspaceFactory::Instance().createTable(); + table2->addColumn(col_type, col_name); + for (double val : col_values) { + TableRow newrow = table2->appendRow(); + newrow << val; + } + + Mantid::Algorithms::CompareWorkspaces alg; + alg.initialize(); + TS_ASSERT_THROWS_NOTHING(alg.setProperty("Workspace1", table1)); + TS_ASSERT_THROWS_NOTHING(alg.setProperty("Workspace2", table2)); + TS_ASSERT(alg.execute()); + TS_ASSERT_EQUALS(alg.getPropertyValue("Result"), PROPERTY_VALUE_TRUE); + } + + void test_tableworkspace_NaNs_fails() { + std::string const col_type("double"), col_name("aColumn"); + std::vector col_values1{1.0, 2.0, 3.0}; + std::vector col_values2{1.0, 2.0, std::numeric_limits::quiet_NaN()}; + // create the table workspaces + Mantid::API::ITableWorkspace_sptr table1 = WorkspaceFactory::Instance().createTable(); + table1->addColumn(col_type, col_name); + for (double val : col_values1) { + TableRow newrow = table1->appendRow(); + newrow << val; + } + Mantid::API::ITableWorkspace_sptr table2 = WorkspaceFactory::Instance().createTable(); + table2->addColumn(col_type, col_name); + for (double val : col_values2) { + TableRow newrow = table2->appendRow(); + newrow << val; + } + + Mantid::Algorithms::CompareWorkspaces alg; + alg.initialize(); + TS_ASSERT_THROWS_NOTHING(alg.setProperty("Workspace1", table1)); + TS_ASSERT_THROWS_NOTHING(alg.setProperty("Workspace2", table2)); + TS_ASSERT(alg.execute()); + TS_ASSERT_EQUALS(alg.getPropertyValue("Result"), PROPERTY_VALUE_FALSE); + + ITableWorkspace_sptr table = AnalysisDataService::Instance().retrieveWS("compare_msgs"); + TS_ASSERT_EQUALS(table->cell(0, 0), "Table data mismatch"); + } + void test_tableworkspace_different_column_names_fails() { auto table1 = setupTableWorkspace(); table1->getColumn(5)->setName("SomethingElse"); diff --git a/Framework/Crystal/src/FindSXPeaksHelper.cpp b/Framework/Crystal/src/FindSXPeaksHelper.cpp index 559e7a850f22..268cba7eb6a2 100644 --- a/Framework/Crystal/src/FindSXPeaksHelper.cpp +++ b/Framework/Crystal/src/FindSXPeaksHelper.cpp @@ -8,6 +8,7 @@ #include "MantidAPI/Progress.h" #include "MantidGeometry/Instrument/DetectorGroup.h" #include "MantidKernel/ConfigService.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/Logger.h" #include "MantidKernel/PhysicalConstants.h" #include "MantidKernel/Unit.h" @@ -118,11 +119,11 @@ Object comparision @param tolerance : tolerance */ bool SXPeak::compare(const SXPeak &rhs, double tolerance) const { - if (std::abs(m_tof / m_nPixels - rhs.m_tof / rhs.m_nPixels) > tolerance * m_tof / m_nPixels) + if (!Kernel::withinRelativeDifference(m_tof / m_nPixels, rhs.m_tof / rhs.m_nPixels, tolerance)) return false; - if (std::abs(m_phi / m_nPixels - rhs.m_phi / rhs.m_nPixels) > tolerance * m_phi / m_nPixels) + if (!Kernel::withinRelativeDifference(m_phi / m_nPixels, rhs.m_phi / rhs.m_nPixels, tolerance)) return false; - if (std::abs(m_twoTheta / m_nPixels - rhs.m_twoTheta / rhs.m_nPixels) > tolerance * m_twoTheta / m_nPixels) + if (!Kernel::withinRelativeDifference(m_twoTheta / m_nPixels, rhs.m_twoTheta / rhs.m_nPixels, tolerance)) return false; return true; } diff --git a/Framework/Crystal/src/IntegratePeakTimeSlices.cpp b/Framework/Crystal/src/IntegratePeakTimeSlices.cpp index 4d4e543fa399..ca5010037286 100644 --- a/Framework/Crystal/src/IntegratePeakTimeSlices.cpp +++ b/Framework/Crystal/src/IntegratePeakTimeSlices.cpp @@ -749,14 +749,10 @@ int IntegratePeakTimeSlices::CalculateTimeChannelSpan(Geometry::IPeak const &pea int chanCenter = findTimeChannel(X, time); Centerchan = chanCenter; - int chanLeft = findTimeChannel(X, time - dtime); - int chanRight = findTimeChannel(X, time + dtime); - int dchan = abs(chanCenter - chanLeft); + int chanLeft = std::abs(chanCenter - findTimeChannel(X, time - dtime)); + int chanRight = std::abs(chanCenter - findTimeChannel(X, time + dtime)); - if (abs(chanRight - chanCenter) > dchan) - dchan = abs(chanRight - chanCenter); - - dchan = max(3, dchan); + int dchan = std::max({3, chanLeft, chanRight}); return dchan + 5; // heuristic should be a lot more } @@ -2448,10 +2444,13 @@ double DataModeHandler::CalcISAWIntensityVariance(const double *params, const do *EdgePeak */ double DataModeHandler::CalcSampleIntensityMultiplier(const double *params) const { - auto MinRow = static_cast(StatBase[IStartRow]); - int MaxRow = MinRow + static_cast(StatBase[INRows]) - 1; - auto MinCol = static_cast(StatBase[IStartCol]); - int MaxCol = MinCol + static_cast(StatBase[INCol]) - 1; + // NOTE: these shadowed variables are not being used in NstdX, NstdY calculations below. + // Unclear if this is a mistake, or a poor understanding of declaring member variables. + // Existing unit tests expect the current behavior, with these variables unused + // auto MinRow = static_cast(StatBase[IStartRow]); + // int MaxRow = MinRow + static_cast(StatBase[INRows]) - 1; + // auto MinCol = static_cast(StatBase[IStartCol]); + // int MaxCol = MinCol + static_cast(StatBase[INCol]) - 1; double r = 1; if (params[IVXX] <= 0 || params[IVYY] <= 0) diff --git a/Framework/Crystal/src/PredictPeaks.cpp b/Framework/Crystal/src/PredictPeaks.cpp index 6ae473ec5013..3ff9922c4013 100644 --- a/Framework/Crystal/src/PredictPeaks.cpp +++ b/Framework/Crystal/src/PredictPeaks.cpp @@ -25,6 +25,7 @@ #include "MantidGeometry/Objects/InstrumentRayTracer.h" #include "MantidKernel/BoundedValidator.h" #include "MantidKernel/EnabledWhenProperty.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/ListValidator.h" #include @@ -201,7 +202,7 @@ void PredictPeaks::exec() { // Get all goniometer matrices DblMatrix lastGoniometerMatrix = Matrix(3, 3, false); for (int i = 0; i < static_cast(peaksWS->getNumberPeaks()); ++i) { - IPeak &p = peaksWS->getPeak(i); + IPeak const &p = peaksWS->getPeak(i); DblMatrix currentGoniometerMatrix = p.getGoniometerMatrix(); if (!(currentGoniometerMatrix == lastGoniometerMatrix)) { gonioVec.emplace_back(currentGoniometerMatrix); @@ -289,7 +290,7 @@ void PredictPeaks::exec() { m_detectorCacheSearch = std::make_unique(m_inst, m_pw->detectorInfo()); if (!usingInstrument) { - for (auto &possibleHKL : possibleHKLs) { + for (auto const &possibleHKL : possibleHKLs) { calculateQAndAddToOutputLeanElastic(possibleHKL, ub); } } else if (getProperty("CalculateGoniometerForCW")) { @@ -329,7 +330,7 @@ void PredictPeaks::exec() { if (!std::isfinite(angle) || angle < angleMin || angle > angleMax) continue; - if (std::abs(wavelength - lambda) < 0.01) { + if (Kernel::withinAbsoluteDifference(wavelength, lambda, 0.01)) { g_log.information() << "Found goniometer rotation to be in YZY convention [" << angles[0] << ", " << angles[1] << ". " << angles[2] << "] degrees for Q sample = " << q_sample << "\n"; calculateQAndAddToOutput(possibleHKL, orientedUB, goniometer.getR()); @@ -341,7 +342,7 @@ void PredictPeaks::exec() { logNumberOfPeaksFound(allowedPeakCount); } else { - for (auto &goniometerMatrix : gonioVec) { + for (auto const &goniometerMatrix : gonioVec) { // Final transformation matrix (HKL to Q in lab frame) DblMatrix orientedUB = goniometerMatrix * ub; @@ -357,7 +358,7 @@ void PredictPeaks::exec() { "no extended detector space has been defined\n"; } - for (auto &possibleHKL : possibleHKLs) { + for (auto const &possibleHKL : possibleHKLs) { if (lambdaFilter.isAllowed(possibleHKL)) { calculateQAndAddToOutput(possibleHKL, orientedUB, goniometerMatrix); ++allowedPeakCount; @@ -503,7 +504,7 @@ void PredictPeaks::fillPossibleHKLsUsingPeaksWorkspace(const IPeaksWorkspace_spt double peaks_q_convention_factor = qConventionFactor(peaksWorkspace->getConvention()); for (int i = 0; i < static_cast(peaksWorkspace->getNumberPeaks()); ++i) { - IPeak &p = peaksWorkspace->getPeak(i); + IPeak const &p = peaksWorkspace->getPeak(i); // Get HKL from that peak V3D hkl = p.getHKL() * peaks_q_convention_factor; diff --git a/Framework/DataHandling/src/PDLoadCharacterizations.cpp b/Framework/DataHandling/src/PDLoadCharacterizations.cpp index 6a2fb1a53e51..81fc1199ae11 100644 --- a/Framework/DataHandling/src/PDLoadCharacterizations.cpp +++ b/Framework/DataHandling/src/PDLoadCharacterizations.cpp @@ -11,6 +11,7 @@ #include "MantidAPI/TableRow.h" #include "MantidAPI/WorkspaceFactory.h" #include "MantidKernel/ArrayProperty.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/Property.h" #include "MantidKernel/StringTokenizer.h" #include "MantidKernel/Strings.h" @@ -419,16 +420,7 @@ void PDLoadCharacterizations::readVersion0(const std::string &filename, API::ITa } namespace { -bool closeEnough(const double left, const double right) { - // the same value - const double diff = fabs(left - right); - if (diff == 0.) - return true; - - // same within 5% - const double relativeDiff = diff * 2 / (left + right); - return relativeDiff < .05; -} +bool closeEnough(const double left, const double right) { return Kernel::withinRelativeDifference(left, right, 0.05); } int findRow(API::ITableWorkspace_sptr &wksp, const std::vector &values) { // don't have a good way to mark error location in these casts diff --git a/Framework/DataHandling/src/SaveGSS.cpp b/Framework/DataHandling/src/SaveGSS.cpp index a33c3fb94cc7..36cc3abc14ad 100644 --- a/Framework/DataHandling/src/SaveGSS.cpp +++ b/Framework/DataHandling/src/SaveGSS.cpp @@ -16,6 +16,7 @@ #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/CompositeValidator.h" #include "MantidKernel/Exception.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/ListValidator.h" #include "MantidKernel/PhysicalConstants.h" #include "MantidKernel/TimeSeriesProperty.h" @@ -67,9 +68,7 @@ double fixErrorValue(const double value) { } bool isEqual(const double left, const double right) { - if (left == right) - return true; - return (2. * std::fabs(left - right) <= std::fabs(m_TOLERANCE * (right + left))); + return Kernel::withinRelativeDifference(left, right, m_TOLERANCE); } bool isConstantDelta(const HistogramData::BinEdges &xAxis) { diff --git a/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h b/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h index 752601e0b5e6..4b9ebafbea0f 100644 --- a/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h +++ b/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h @@ -14,6 +14,7 @@ #include #include "MantidAPI/Column.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/V3D.h" namespace Mantid { @@ -221,7 +222,7 @@ template class TableColumn : public API::Column { // helper function template for equality bool compareVectors(const std::vector &newVector, double tolerance) const { for (size_t i = 0; i < m_data.size(); i++) { - if (fabs((double)m_data[i] - (double)newVector[i]) > tolerance) { + if (!Kernel::withinAbsoluteDifference(m_data[i], newVector[i], tolerance)) { return false; } } @@ -231,17 +232,14 @@ template class TableColumn : public API::Column { // helper function template for equality with relative error bool compareVectorsRelError(const std::vector &newVector, double tolerance) const { for (size_t i = 0; i < m_data.size(); i++) { - double num = fabs((double)m_data[i] - (double)newVector[i]); - double den = (fabs((double)m_data[i]) + fabs((double)newVector[i])) / 2; - if (den < tolerance && num > tolerance) { - return false; - } else if (num / den > tolerance) { + if (!Kernel::withinRelativeDifference(m_data[i], newVector[i], tolerance)) { return false; } } return true; } }; + /// Template specialisation for long64 template <> inline bool TableColumn::compareVectors(const std::vector &newVector, double tolerance) const { @@ -297,11 +295,9 @@ inline bool TableColumn::compareVectors(const std::vector inline bool TableColumn::compareVectors(const std::vector &newVector, double tolerance) const { + // must specify for it to use pass-by-references for (size_t i = 0; i < m_data.size(); i++) { - double dif_x = fabs(m_data[i].X() - newVector[i].X()); - double dif_y = fabs(m_data[i].Y() - newVector[i].Y()); - double dif_z = fabs(m_data[i].Z() - newVector[i].Z()); - if (dif_x > tolerance || dif_y > tolerance || dif_z > tolerance) { + if (!Kernel::withinAbsoluteDifference(m_data[i], newVector[i], tolerance)) { return false; } } @@ -360,21 +356,10 @@ inline bool TableColumn::compareVectorsRelError(const std::vector< template <> inline bool TableColumn::compareVectorsRelError(const std::vector &newVector, double tolerance) const { + // must specify for it to use pass-by-references for (size_t i = 0; i < m_data.size(); i++) { - double dif_x = fabs(m_data[i].X() - newVector[i].X()); - double dif_y = fabs(m_data[i].Y() - newVector[i].Y()); - double dif_z = fabs(m_data[i].Z() - newVector[i].Z()); - double den_x = 0.5 * (fabs(m_data[i].X()) + fabs(newVector[i].X())); - double den_y = 0.5 * (fabs(m_data[i].X()) + fabs(newVector[i].X())); - double den_z = 0.5 * (fabs(m_data[i].X()) + fabs(newVector[i].X())); - if (den_x > tolerance || den_y > tolerance || den_z > tolerance) { - if (dif_x / den_x > tolerance || dif_y / den_y > tolerance || dif_z / den_z > tolerance) { - return false; - } - } else { - if (dif_x > tolerance || dif_y > tolerance || dif_z > tolerance) { - return false; - } + if (!Kernel::withinRelativeDifference(m_data[i], newVector[i], tolerance)) { + return false; } } return true; diff --git a/Framework/Kernel/inc/MantidKernel/FloatingPointComparison.h b/Framework/Kernel/inc/MantidKernel/FloatingPointComparison.h index eb4ee09791fc..b4e562dda304 100644 --- a/Framework/Kernel/inc/MantidKernel/FloatingPointComparison.h +++ b/Framework/Kernel/inc/MantidKernel/FloatingPointComparison.h @@ -10,6 +10,7 @@ // Includes //----------------------------------------------------------------------------- #include "MantidKernel/DllConfig.h" +#include "MantidKernel/V3D.h" namespace Mantid { namespace Kernel { @@ -24,8 +25,10 @@ template MANTID_KERNEL_DLL T absoluteDifference(T const x, T const /// Calculate relative difference between x, y template MANTID_KERNEL_DLL T relativeDifference(T const x, T const y); /// Test whether x, y are within absolute tolerance tol -template MANTID_KERNEL_DLL bool withinAbsoluteDifference(T const x, T const y, T const tolerance); +template +MANTID_KERNEL_DLL bool withinAbsoluteDifference(T const x, T const y, S const tolerance); /// Test whether x, y are within relative tolerance tol -template MANTID_KERNEL_DLL bool withinRelativeDifference(T const x, T const y, T const tolerance); +template +MANTID_KERNEL_DLL bool withinRelativeDifference(T const x, T const y, S const tolerance); } // namespace Kernel } // namespace Mantid diff --git a/Framework/Kernel/src/FloatingPointComparison.cpp b/Framework/Kernel/src/FloatingPointComparison.cpp index f2c15a5492e1..9e1d4714f923 100644 --- a/Framework/Kernel/src/FloatingPointComparison.cpp +++ b/Framework/Kernel/src/FloatingPointComparison.cpp @@ -9,6 +9,7 @@ //----------------------------------------------------------------------------- #include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/System.h" +#include "MantidKernel/V3D.h" #include #include @@ -20,10 +21,26 @@ namespace Mantid::Kernel { * std::numeric_limits::epsilon precision * @param x :: LHS comparator * @param y :: RHS comparator - * @returns True if the numbers are considered equal within the given tolerance, - * false otherwise. False if any value is NaN. + * @returns True if the numbers are considered equal within machine precision. + * Machine precision is a 1 at the least significant bit scaled to the same power as the numbers compared. + * E.g. for 1, it is usually 1x2^{-52} + * E.g. for 1x2^100, it is usually 1x2^{-52} x 1x2^100 = 1x2^{48} + * False if any value is NaN. False if comparing opposite infinities. */ -template bool equals(T const x, T const y) { return std::abs(x - y) <= std::numeric_limits::epsilon(); } +template bool equals(T const x, T const y) { + // handle infinities + if (std::isinf(x) && std::isinf(y)) { + // if x,y both +inf, x-y=NaN; if x,y both -inf, x-y=NaN; else not an NaN + return std::isnan(x - y); + } else { + // produce a scale for comparison + // in general can use either value, but use the second to work better with near differences, + // which call as equals(difference, tolerance), since tolerance will more often be finite + int const exp = y < std::numeric_limits::min() ? std::numeric_limits::min_exponent - 1 : std::ilogb(y); + // compare to within machine epsilon + return std::abs(x - y) <= std::ldexp(std::numeric_limits::epsilon(), exp); + } +} /** * Compare two floating-point numbers as to whether they satisfy x<=y within @@ -68,10 +85,10 @@ template T relativeDifference(T const x, T const y) { T const num = absoluteDifference(x, y); if (num <= std::numeric_limits::epsilon()) { // if |x-y| == 0.0 (within machine tolerance), relative difference is zero - return 0.0; + return static_cast(0); } else { // otherwise we have to calculate the denominator - T const denom = static_cast(0.5 * (std::abs(x) + std::abs(y))); + T const denom = static_cast((std::abs(x) + std::abs(y)) / static_cast(2)); // NOTE if we made it this far, at least one of x or y is nonzero, so denom will be nonzero return num / denom; } @@ -86,8 +103,12 @@ template T relativeDifference(T const x, T const y) { * @returns True if the numbers are considered equal within the given tolerance, * false otherwise. False if either value is NaN. */ -template bool withinAbsoluteDifference(T const x, T const y, T const tolerance) { - return ltEquals(absoluteDifference(x, y), tolerance); +template bool withinAbsoluteDifference(T const x, T const y, S const tolerance) { + // handle the case of infinities + if (std::isinf(x) && std::isinf(y)) + // if both are +inf, return true; if both -inf, return true; else false + return isnan(static_cast(x - y)); + return ltEquals(static_cast(absoluteDifference(x, y)), tolerance); } /** @@ -99,21 +120,21 @@ template bool withinAbsoluteDifference(T const x, T const y, T cons * @returns True if the numbers are considered equal within the given tolerance, * false otherwise. False if either value is NaN. */ -template bool withinRelativeDifference(T const x, T const y, T const tolerance) { - // handle the case of NaNs - if (std::isnan(x) || std::isnan(y)) { - return false; - } - T const num = absoluteDifference(x, y); - if (!(num > std::numeric_limits::epsilon())) { +template bool withinRelativeDifference(T const x, T const y, S const tolerance) { + // handles the case of infinities + if (std::isinf(x) && std::isinf(y)) + // if both are +inf, return true; if both -inf, return true; else false + return isnan(static_cast(x - y)); + S const num = static_cast(absoluteDifference(x, y)); + if (num <= std::numeric_limits::epsilon()) { // if |x-y| == 0.0 (within machine tolerance), this test passes return true; } else { // otherwise we have to calculate the denominator - T const denom = static_cast(0.5 * (std::abs(x) + std::abs(y))); + S const denom = static_cast((std::abs(x) + std::abs(y)) / static_cast(2)); // if denom <= 1, then |x-y| > tol implies |x-y|/denom > tol, can return early // NOTE can only return early if BOTH denom > tol AND |x-y| > tol. - if (denom <= 1. && !ltEquals(num, tolerance)) { + if (denom <= static_cast(1) && !ltEquals(num, tolerance)) { return false; } else { // avoid division for improved performance @@ -130,16 +151,96 @@ template DLLExport bool ltEquals(double const, double const); template DLLExport bool ltEquals(float const, float const); template DLLExport bool gtEquals(double const, double const); template DLLExport bool gtEquals(float const, float const); -// +// difference methods template DLLExport double absoluteDifference(double const, double const); template DLLExport float absoluteDifference(float const, float const); template DLLExport double relativeDifference(double const, double const); template DLLExport float relativeDifference(float const, float const); -// +// within difference methods template DLLExport bool withinAbsoluteDifference(double const, double const, double const); template DLLExport bool withinAbsoluteDifference(float const, float const, float const); template DLLExport bool withinRelativeDifference(double const, double const, double const); template DLLExport bool withinRelativeDifference(float const, float const, float const); +// instantiations where the objects are anything and tolerance is a double +template DLLExport bool withinAbsoluteDifference(float const, float const, double const); +template DLLExport bool withinAbsoluteDifference(int const, int const, double const); +template DLLExport bool withinRelativeDifference(float const, float const, double const); +template DLLExport bool withinRelativeDifference(int const, int const, double const); ///@endcond +/// Template specialization for long int +/// these prevent compiler warnings about using isinf and isnan on longs + +template <> DLLExport bool equals(long const x, long const y) { return x == y; } + +template <> DLLExport bool withinAbsoluteDifference(long const x, long const y, long const tolerance) { + return ltEquals(std::labs(x - y), tolerance); +} + +template <> DLLExport bool withinRelativeDifference(long const x, long const y, long const tolerance) { + long const num = std::labs(x - y); + if (num == 0) { + return true; + } else { + long const denom = (std::labs(x) + std::labs(y)) / 2; + return num <= static_cast(denom * tolerance); + } +} + +/// Template specialization for unsigned int + +template <> +DLLExport bool withinAbsoluteDifference(unsigned int const x, unsigned int const y, + double const tol) { + unsigned int roundedTol = static_cast(llround(tol)); + return std::llabs(x - y) <= roundedTol; +} +template <> +DLLExport bool withinRelativeDifference(unsigned int const x, unsigned int const y, + double const tol) { + unsigned int roundedTol = static_cast(llround(tol)); + return std::llabs(x - y) <= roundedTol; +} + +/// Template specialization for V3D + +template <> +DLLExport bool withinAbsoluteDifference(V3D const &V1, V3D const &V2, double const tolerance) { + //|||V1-V2||^2 < tol^2 --> ||V1-V2|| < tol, since both are non-negative + return ltEquals((V1 - V2).norm2(), tolerance * tolerance); +} + +/** + * Compare 3D vectors (class V3D) for relative difference to + * within the given tolerance. The relative difference is calculated as + * rel diff = ||V1 - V2||/sqrt(||V1||*||V2||) + * consistent in other normalized vector binary operations. + * @param V1 :: first value + * @param V2 :: second value + * @param tolerance :: the tolerance + * @returns True if the vectorsare considered equal within the given tolerance, + * false otherwise. False if any value in either vector is an NaN. + */ +template <> +DLLExport bool withinRelativeDifference(V3D const &V1, V3D const &V2, double const tolerance) { + // NOTE we must avoid sqrt as much as possible + double const tol2 = tolerance * tolerance; + double const diff2 = (V1 - V2).norm2(); + if (diff2 <= std::numeric_limits::epsilon()) { + // if the difference has zero length, the vectors are equal, this test passes + return true; + } else { + // otherwise we must calculate the denominator + double const denom4 = static_cast(V1.norm2() * V2.norm2()); + // if denom <= 1, then |x-y| > tol implies |x-y|/denom > tol, can return early + // NOTE can only return early if BOTH denom <= 1. AND |x-y| > tol. + if (denom4 <= 1. && !ltEquals(diff2, tol2)) { // NOTE ||V1||^2.||V2||^2 <= 1 --> sqrt(||V1||.||V2||) <= 1 + return false; + } else { + // avoid division and sqrt for improved performance + // NOTE ||V1-V2|| < sqrt(||V1||*||V2||) * tol --> ||V1-V2||^4 < ||V1||^2.||V2||^2 * tol^4 + return ltEquals(diff2 * diff2, sqrt(denom4) * tol2 * tol2); + } + } +} } // namespace Mantid::Kernel diff --git a/Framework/Kernel/src/V3D.cpp b/Framework/Kernel/src/V3D.cpp index 64b0387018ef..d471546dc2ba 100644 --- a/Framework/Kernel/src/V3D.cpp +++ b/Framework/Kernel/src/V3D.cpp @@ -241,6 +241,7 @@ bool V3D::nullVector(const double tolerance) const noexcept { } bool V3D::unitVector(const double tolerance) const noexcept { + // NOTE could be made more efficient using norm2() const auto l = norm(); return std::abs(l - 1.) < tolerance; } @@ -500,12 +501,12 @@ V3D V3D::directionAngles(bool inDegrees) const { */ int V3D::maxCoeff() { int MaxOrder = 0; - if (abs(static_cast(m_pt[0])) > MaxOrder) - MaxOrder = abs(static_cast(m_pt[0])); - if (abs(static_cast(m_pt[1])) > MaxOrder) - MaxOrder = abs(static_cast(m_pt[1])); - if (abs(static_cast(m_pt[2])) > MaxOrder) - MaxOrder = abs(static_cast(m_pt[2])); + if (std::abs(static_cast(m_pt[0])) > MaxOrder) + MaxOrder = std::abs(static_cast(m_pt[0])); + if (std::abs(static_cast(m_pt[1])) > MaxOrder) + MaxOrder = std::abs(static_cast(m_pt[1])); + if (std::abs(static_cast(m_pt[2])) > MaxOrder) + MaxOrder = std::abs(static_cast(m_pt[2])); return MaxOrder; } @@ -513,15 +514,16 @@ int V3D::maxCoeff() { Calculates the absolute value. @return The absolute value */ -V3D V3D::absoluteValue() const { return V3D(fabs(m_pt[0]), fabs(m_pt[1]), fabs(m_pt[2])); } +V3D V3D::absoluteValue() const { return V3D(std::abs(m_pt[0]), std::abs(m_pt[1]), std::abs(m_pt[2])); } /** Calculates the error of the HKL to compare with tolerance @return The error */ double V3D::hklError() const { - return fabs(m_pt[0] - std::round(m_pt[0])) + fabs(m_pt[1] - std::round(m_pt[1])) + - fabs(m_pt[2] - std::round(m_pt[2])); + return std::abs(m_pt[0] - std::round(m_pt[0])) + // + std::abs(m_pt[1] - std::round(m_pt[1])) + // + std::abs(m_pt[2] - std::round(m_pt[2])); } } // namespace Mantid::Kernel diff --git a/Framework/Kernel/test/FloatingPointComparisonTest.h b/Framework/Kernel/test/FloatingPointComparisonTest.h index 9fff197fb606..39beaf690c72 100644 --- a/Framework/Kernel/test/FloatingPointComparisonTest.h +++ b/Framework/Kernel/test/FloatingPointComparisonTest.h @@ -16,15 +16,62 @@ class FloatingPointComparisonTest : public CxxTest::TestSuite { void test_Same_Value_Compare_Equal() { TS_ASSERT(Mantid::Kernel::equals(2.5, 2.5)); } void test_Difference_By_Machine_Eps_Compare_Equal() { - TS_ASSERT(Mantid::Kernel::equals(2.5, 2.5 + std::numeric_limits::epsilon())); + double const a = 0x1.4p1; // i.e. 2.5 + // increase by the machine precision + double const diff = std::ldexp(std::numeric_limits::epsilon(), std::ilogb(a)); + TS_ASSERT_DIFFERS(a, a + diff); + TS_ASSERT(Mantid::Kernel::equals(a, a + diff)); } void test_Difference_By_Machine_Eps_Plus_Small_Does_Not_Compare_Equal() { - TS_ASSERT_EQUALS(Mantid::Kernel::equals(2.5, 2.5 + 1.1 * std::numeric_limits::epsilon()), false); + double const a = 0x1.4p1; // i.e. 2.5 + // as above, but increase by twice the machine precision + double const diff = std::ldexp(std::numeric_limits::epsilon(), std::ilogb(a) + 1); + TS_ASSERT_DIFFERS(a, a + diff); + TS_ASSERT(!Mantid::Kernel::equals(a, a + diff)); + } + + void test_Similar_Small_Numbers_Compare_Equal() { + double const a = 0x1p-100; + // increase by the machine precision + double const diff = std::ldexp(std::numeric_limits::epsilon(), std::ilogb(a)); + TS_ASSERT_DIFFERS(a, a + diff); + TS_ASSERT(Mantid::Kernel::equals(a, a + diff)); + } + + void test_Different_Small_Numbers_Do_Not_Compare_Equal() { + // two small but machine-distinguishable numbers + double const a = 0x1.0p-100; // 1.0 * 2^{-100} + double const b = 0x1.8p-100; // 1.5 * 2^{-100} + double const diff = std::abs(a - b); + // the difference is less than machine epsilon (when scaled to 1) + TS_ASSERT_LESS_THAN(diff, std::numeric_limits::epsilon()); + // ne'ertheless, the numbers compare different + TS_ASSERT(!Mantid::Kernel::equals(a, b)) } void test_Same_Large_Numbers_Compare_Equal() { TS_ASSERT(Mantid::Kernel::equals(DBL_MAX, DBL_MAX)); } + void test_Similar_Large_Numbers_Compare_Equal() { + double const a = DBL_MAX / 2; + double const diff = std::ldexp(std::numeric_limits::epsilon(), std::ilogb(a)); + // the difference is a sizeable number and not by itself insignificant + TS_ASSERT_LESS_THAN(0x1.p50, diff); + // the numbers are technicaly different + TS_ASSERT_DIFFERS(a, a + diff); + // but they compare different + TS_ASSERT(Mantid::Kernel::equals(a, a + diff)); + } + + void test_Different_Large_Numbers_Do_Not_Compare_Equal() { + double const a = DBL_MAX / 2; + // as above, but increase by twice the machine precision + double const diff = std::ldexp(std::numeric_limits::epsilon(), std::ilogb(a) + 1); + TS_ASSERT_LESS_THAN(0x1.p50, diff); + TS_ASSERT_DIFFERS(a, a + diff); + TS_ASSERT(Mantid::Kernel::equals(a, a + diff)); + } + void test_Numbers_Outside_Custom_Tolerance_Are_Not_Equal() { const double tol(1e-08); TS_ASSERT_EQUALS(Mantid::Kernel::equals(0.1, 1.0001 * tol), false); diff --git a/Framework/TestHelpers/src/ComponentCreationHelper.cpp b/Framework/TestHelpers/src/ComponentCreationHelper.cpp index 40013cc7552a..1786df0efcd0 100644 --- a/Framework/TestHelpers/src/ComponentCreationHelper.cpp +++ b/Framework/TestHelpers/src/ComponentCreationHelper.cpp @@ -30,6 +30,7 @@ #include "MantidGeometry/Objects/ShapeFactory.h" #include "MantidKernel/ConfigService.h" #include "MantidKernel/DateAndTime.h" +#include "MantidKernel/FloatingPointComparison.h" #include "MantidKernel/Matrix.h" #include "MantidKernel/Quat.h" #include "MantidKernel/UnitFactory.h" @@ -426,11 +427,7 @@ createCylInstrumentWithVerticalOffsetsSpecified(size_t nTubes, std::vector &L2, const std::vector &polar, diff --git a/buildconfig/CMake/CppCheck_Suppressions.txt.in b/buildconfig/CMake/CppCheck_Suppressions.txt.in index e6310c63f998..c1ba44e3a968 100644 --- a/buildconfig/CMake/CppCheck_Suppressions.txt.in +++ b/buildconfig/CMake/CppCheck_Suppressions.txt.in @@ -170,10 +170,10 @@ unreadVariable:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/CalculateCarpenterSa missingOverride:${CMAKE_SOURCE_DIR}/Framework/Algorithms/inc/MantidAlgorithms/SpectrumAlgorithm.h:97 returnByReference:${CMAKE_SOURCE_DIR}/Framework/API/inc/MantidAPI/FunctionDomain1D.h:89 returnByReference:${CMAKE_SOURCE_DIR}/Framework/API/inc/MantidAPI/FunctionValues.h:86 -knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h:67 -knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h:70 -knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h:81 -knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h:84 +knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h:68 +knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h:71 +knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h:82 +knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/DataObjects/inc/MantidDataObjects/TableColumn.h:85 constParameterReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/CalculatePolynomialBackground.cpp:174 missingOverride:${CMAKE_SOURCE_DIR}/Framework/Algorithms/inc/MantidAlgorithms/CalculatePlaczekSelfScattering.h:22 constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/ChangeTimeZero.cpp:154 @@ -202,7 +202,7 @@ constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/CreatePSDBle constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/CreateLogPropertyTable.cpp:126 variableScope:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/CreateGroupingWorkspace.cpp:684 constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/API/inc/MantidAPI/EnabledWhenWorkspaceIsType.h:50 -constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/DetectorEfficiencyCor.cpp:126 +constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/DetectorEfficiencyCor.cpp:127 constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/DetectorEfficiencyCorUser.cpp:176 constParameterReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/DirectILLTubeBackground.cpp:348 constParameterReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/DirectILLTubeBackground.cpp:364 @@ -237,15 +237,13 @@ returnByReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/inc/MantidAlgorithms/ returnByReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/inc/MantidAlgorithms/FitPeak.h:70 constParameterReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/GetEiMonDet3.cpp:218 constParameterReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/GetEiMonDet3.cpp:261 -shadowVariable:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/FitPeak.cpp:1410 -shadowVariable:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/FitPeak.cpp:1411 knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/FilterEvents.cpp:620 constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/FilterEvents.cpp:304 uselessOverride:${CMAKE_SOURCE_DIR}/Framework/Algorithms/inc/MantidAlgorithms/InterpolatingRebin.h:68 uselessOverride:${CMAKE_SOURCE_DIR}/Framework/Algorithms/inc/MantidAlgorithms/InterpolatingRebin.h:71 passedByValue:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/GeneratePeaks.cpp:662 constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/GeneratePeaks.cpp:518 -shadowVariable:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/He3TubeEfficiency.cpp:373 +shadowVariable:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/He3TubeEfficiency.cpp:374 knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/FindPeaks.cpp:892 knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/FindPeaks.cpp:999 unreadVariable:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/InterpolatingRebin.cpp:69 @@ -310,8 +308,8 @@ uselessOverride:${CMAKE_SOURCE_DIR}/Framework/Algorithms/inc/MantidAlgorithms/Re constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/SANSCollimationLengthEstimator.cpp:172 constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/SANSCollimationLengthEstimator.cpp:174 constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/RingProfile.cpp:338 -constParameterPointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/RunCombinationHelpers/SampleLogsBehaviour.cpp:484 -constParameterPointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/RunCombinationHelpers/SampleLogsBehaviour.cpp:510 +constParameterPointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/RunCombinationHelpers/SampleLogsBehaviour.cpp:485 +constParameterPointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/RunCombinationHelpers/SampleLogsBehaviour.cpp:511 constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/ShiftLogTime.cpp:61 constParameterPointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/SofQCommon.cpp:25 containerOutOfBounds:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/SampleCorrections/SparseWorkspace.cpp:32 @@ -351,7 +349,6 @@ constParameterPointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/UnwrapMonitor missingOverride:${CMAKE_SOURCE_DIR}/Framework/API/inc/MantidAPI/BoxControllerSettingsAlgorithm.h:43 constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/API/src/BoxControllerSettingsAlgorithm.cpp:78 uselessOverride:${CMAKE_SOURCE_DIR}/Framework/Algorithms/inc/MantidAlgorithms/SofQWNormalisedPolygon.h:55 -constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/UnwrapMonitor.cpp:226 constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/SofQWNormalisedPolygon.cpp:537 missingOverride:${CMAKE_SOURCE_DIR}/Framework/Algorithms/inc/MantidAlgorithms/XrayAbsorptionCorrection.h:36 returnByReference:${CMAKE_SOURCE_DIR}/Framework/API/inc/MantidAPI/IMDWorkspace.h:92 @@ -367,7 +364,7 @@ unreadVariable:${CMAKE_SOURCE_DIR}/Framework/Algorithms/src/WeightedMeanOfWorksp constVariableReference:${CMAKE_SOURCE_DIR}/Framework/API/src/IMDEventWorkspace.cpp:50 constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/API/src/IMDEventWorkspace.cpp:85 constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/API/src/IMDEventWorkspace.cpp:92 -unreadVariable:${CMAKE_SOURCE_DIR}/Framework/API/src/NumericAxis.cpp:160 +unreadVariable:${CMAKE_SOURCE_DIR}/Framework/API/src/NumericAxis.cpp:166 constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/API/src/ParameterReference.cpp:52 constVariableReference:${CMAKE_SOURCE_DIR}/Framework/API/src/MultiDomainFunction.cpp:135 constVariableReference:${CMAKE_SOURCE_DIR}/Framework/API/src/MultiDomainFunction.cpp:174 @@ -467,12 +464,7 @@ constVariableReference:${CMAKE_SOURCE_DIR}/Framework/CurveFitting/src/Algorithms constVariableReference:${CMAKE_SOURCE_DIR}/Framework/CurveFitting/src/Algorithms/EstimateFitParameters.cpp:408 constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/CurveFitting/src/Algorithms/EstimateFitParameters.cpp:362 constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/CurveFitting/src/Algorithms/EstimateFitParameters.cpp:389 -constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/PredictPeaks.cpp:204 -constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/PredictPeaks.cpp:292 -constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/PredictPeaks.cpp:311 -constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/PredictPeaks.cpp:344 -constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/PredictPeaks.cpp:360 -constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/PredictPeaks.cpp:506 +constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/PredictPeaks.cpp:312 passedByValue:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/SaveIsawPeaks.cpp:508 constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/PeakIntegration.cpp:105 shadowVariable:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/SCDCalibratePanels.cpp:189 @@ -535,20 +527,16 @@ constVariableReference:${CMAKE_SOURCE_DIR}/Framework/CurveFitting/src/Algorithms constVariableReference:${CMAKE_SOURCE_DIR}/Framework/CurveFitting/src/Algorithms/LeBailFit.cpp:1707 constParameterReference:${CMAKE_SOURCE_DIR}/Framework/CurveFitting/src/Algorithms/LeBailFit.cpp:2189 returnByReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/inc/MantidCrystal/IntegratePeakTimeSlices.h:84 -knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:837 +knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:833 variableScope:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:238 -variableScope:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:1006 -shadowVariable:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:2451 -shadowVariable:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:2452 -shadowVariable:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:2453 -shadowVariable:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:2454 +variableScope:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:1002 constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:206 -constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:1468 -constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:1470 -constParameterReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:1834 +constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:1464 +constVariableReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:1466 +constParameterReference:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:1830 variableScope:${CMAKE_SOURCE_DIR}/Framework/CurveFitting/src/Algorithms/RefinePowderInstrumentParameters3.cpp:1300 -constVariable:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:1048 -constVariable:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:2387 +constVariable:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:1044 +constVariable:${CMAKE_SOURCE_DIR}/Framework/Crystal/src/IntegratePeakTimeSlices.cpp:2383 passedByValue:${CMAKE_SOURCE_DIR}/Framework/CurveFitting/src/Algorithms/RefinePowderInstrumentParameters3.cpp:1201 passedByValue:${CMAKE_SOURCE_DIR}/Framework/CurveFitting/src/Algorithms/RefinePowderInstrumentParameters3.cpp:1219 constVariableReference:${CMAKE_SOURCE_DIR}/Framework/CurveFitting/src/Algorithms/RefinePowderInstrumentParameters3.cpp:662 @@ -765,8 +753,8 @@ uninitMemberVarPrivate:${CMAKE_SOURCE_DIR}/Framework/DataHandling/inc/MantidData uselessOverride:${CMAKE_SOURCE_DIR}/Framework/DataHandling/inc/MantidDataHandling/SaveNexusESS.h:26 uselessOverride:${CMAKE_SOURCE_DIR}/Framework/DataHandling/inc/MantidDataHandling/SaveNexusESS.h:27 knownConditionTrueFalse:${CMAKE_SOURCE_DIR}/Framework/DataHandling/src/SaveIsawDetCal.cpp:110 -constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/DataHandling/src/SaveGSS.cpp:433 -constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/DataHandling/src/SaveGSS.cpp:567 +constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/DataHandling/src/SaveGSS.cpp:432 +constVariablePointer:${CMAKE_SOURCE_DIR}/Framework/DataHandling/src/SaveGSS.cpp:566 constVariableReference:${CMAKE_SOURCE_DIR}/Framework/DataHandling/src/SaveNXTomo.cpp:150 shadowVariable:${CMAKE_SOURCE_DIR}/Framework/DataHandling/src/LoadTOFRawNexus.cpp:285 shadowVariable:${CMAKE_SOURCE_DIR}/Framework/DataHandling/src/LoadTOFRawNexus.cpp:357 @@ -1055,8 +1043,8 @@ unusedScopedObject:${CMAKE_SOURCE_DIR}/Framework/PythonInterface/mantid/dataobje unusedScopedObject:${CMAKE_SOURCE_DIR}/Framework/PythonInterface/mantid/dataobjects/src/Exports/SpecialWorkspace2D.cpp:57 unusedScopedObject:${CMAKE_SOURCE_DIR}/Framework/PythonInterface/mantid/dataobjects/src/Exports/WorkspaceSingleValue.cpp:24 unusedScopedObject:${CMAKE_SOURCE_DIR}/Framework/PythonInterface/mantid/dataobjects/src/Exports/RebinnedOutput.cpp:84 -passedByValue:${CMAKE_SOURCE_DIR}/Framework/TestHelpers/src/ComponentCreationHelper.cpp:383 -unreadVariable:${CMAKE_SOURCE_DIR}/Framework/TestHelpers/src/ComponentCreationHelper.cpp:411 +passedByValue:${CMAKE_SOURCE_DIR}/Framework/TestHelpers/src/ComponentCreationHelper.cpp:384 +unreadVariable:${CMAKE_SOURCE_DIR}/Framework/TestHelpers/src/ComponentCreationHelper.cpp:412 unusedScopedObject:${CMAKE_SOURCE_DIR}/Framework/PythonInterface/mantid/dataobjects/src/Exports/OffsetsWorkspace.cpp:23 unusedScopedObject:${CMAKE_SOURCE_DIR}/Framework/PythonInterface/mantid/dataobjects/src/Exports/GroupingWorkspace.cpp:42 unusedScopedObject:${CMAKE_SOURCE_DIR}/Framework/PythonInterface/mantid/dataobjects/src/Exports/Workspace2D.cpp:173