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