scran_test_utils
Test utilities for libscran projects
Loading...
Searching...
No Matches
compare_almost_equal.hpp
Go to the documentation of this file.
1#ifndef SCRAN_TESTS_COMPARE_ALMOST_EQUAL_HPP
2#define SCRAN_TESTS_COMPARE_ALMOST_EQUAL_HPP
3
4#include <gtest/gtest.h>
5#include <cmath>
6
12namespace scran_tests {
13
27inline bool compare_almost_equal(double left, double right, double tol = 1e-8, bool report = true) {
28 if (left != right) {
29 // Use relative tolerance to check that we get a similar float.
30 // EXPECT_DOUBLE_EQ and EXPECT_FLOAT_EQ tend to be a bit too stringent
31 // when numerical imprecision is expected. We define the relative difference
32 // as |difference| / |mean| of the two values, and check that this is
33 // below some acceptable error, in this case 1e-8.
34 //
35 // It's worth nothing that I spent a long time using EXPECT_FLOAT_EQ
36 // when I really should have been using EXPECT_DOUBLE_EQ; this would have
37 // implicitly used a relative threshold at the 8th significant figure,
38 // which is why it never failed from differences in numerical precision.
39 double denom = std::abs(left + right) / 2;
40 double threshold = denom * tol;
41
42 // This is effectively refactored to |difference| < threshold. However,
43 // if threshold falls below the machine epsilon - usually because
44 // |mean| is very small - we're effectively back to an exact equality
45 // test, so we need to ensure that the threshold doesn't get too small.
46 //
47 // This compromises the stringency of the test at very-near-zero values,
48 // but this could also be viewed as a feature, because we DON'T want to
49 // fail the test if one value is zero and another is slightly non-zero
50 // (e.g., when something should, in theory, perfectly cancel out).
51 if (threshold < 1e-15) {
52 threshold = 1e-15;
53 }
54 if (std::abs(left - right) > threshold) {
55 if (report) {
56 EXPECT_TRUE(false) << "mismatch in almost-equal floats (expected " << left << ", got " << right << ")";
57 }
58 return false;
59 }
60 }
61
62 return true;
63}
64
76template<class Vector_>
77void compare_almost_equal(const Vector_& left, const Vector_& right, double tol = 1e-8) {
78 auto n = left.size();
79 ASSERT_EQ(n, right.size());
80 for (decltype(n) i = 0; i < n; ++i) {
81 if (!compare_almost_equal(left[i], right[i], tol, false)) {
82 EXPECT_TRUE(false) << "mismatch in almost-equal floats at element " << i << " (expected " << left[i] << ", got " << right[i] << ")";
83 return;
84 }
85 }
86}
87
88}
89
90#endif
Test utilites for libscran.
Definition compare_almost_equal.hpp:12
bool compare_almost_equal(double left, double right, double tol=1e-8, bool report=true)
Definition compare_almost_equal.hpp:27