-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathisclose.hpp
43 lines (37 loc) · 1.3 KB
/
isclose.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// SPDX-FileCopyrightText: Steven Ward
// SPDX-License-Identifier: OSL-3.0
/// function to determine if two floating-point numbers are close to each other
/**
\file
\author Steven Ward
*/
#pragma once
#include <cmath>
#include <concepts>
/// are two floating-point numbers are close to each other?
/**
This is similar to the Python function \c math.isclose.
\sa https://docs.python.org/3/library/math.html#math.isclose
\sa https://peps.python.org/pep-0485/
\sa https://github.com/python/cpython/blob/main/Modules/mathmodule.c#L2997
\pre \a allowed_rel_diff is positive
\pre \a allowed_abs_diff is non-negative
\param allowed_rel_diff maximum relative difference for being considered "close", relative to the magnitude of the input values
\param allowed_abs_diff maximum absolute difference for being considered "close", regardless of the magnitude of the input values
*/
template <std::floating_point T>
bool
isclose(const T a,
const T b,
const T allowed_rel_diff = 1E-9,
const T allowed_abs_diff = 0)
{
if (a == b)
return true;
if (!std::isfinite(a) || !std::isfinite(b))
return false;
const auto actual_abs_diff = std::abs(a - b);
const auto max_abs = std::max(std::abs(a), std::abs(b));
return actual_abs_diff <= allowed_abs_diff ||
actual_abs_diff <= allowed_rel_diff * max_abs;
}