xref: /petsc/src/sys/utils/mathclose.c (revision 28dd6638a6a029604ae1c2f1f758daef03ec4a8d)
1b10005b4SLisandro Dalcin #include <petscsys.h>
2b10005b4SLisandro Dalcin 
3b10005b4SLisandro Dalcin /*@C
4667f096bSBarry Smith     PetscIsCloseAtTol - Returns whether the two `PetscReal` numbers
5811af0c4SBarry Smith        are close at a given relative and absolute tolerances.
6b10005b4SLisandro Dalcin 
7d8d19677SJose E. Roman     Input Parameters:
8b10005b4SLisandro Dalcin +     a - first floating point number
9b10005b4SLisandro Dalcin .     b - second floating point number
10b10005b4SLisandro Dalcin .     rtol - relative tolerance
11a2b725a8SWilliam Gropp -     atol - absolute tolerances
12b10005b4SLisandro Dalcin 
13667f096bSBarry Smith     Level: beginner
14667f096bSBarry Smith 
15811af0c4SBarry Smith     Reference:
16811af0c4SBarry Smith .   * -  https://www.python.org/dev/peps/pep-0485/
17b10005b4SLisandro Dalcin 
18*28dd6638SJacob Faibussowitsch .seealso: `PetscIsCloseAtTolScalar()`, `PetscEqualReal()`, `PetscEqualScalar()`
19b10005b4SLisandro Dalcin @*/
20d71ae5a4SJacob Faibussowitsch PetscBool PetscIsCloseAtTol(PetscReal a, PetscReal b, PetscReal rtol, PetscReal atol)
21d71ae5a4SJacob Faibussowitsch {
22b10005b4SLisandro Dalcin   PetscReal diff;
23b10005b4SLisandro Dalcin   /* NaN is not considered close to any other value, including NaN */
24b10005b4SLisandro Dalcin   if (PetscIsNanReal(a) || PetscIsNanReal(b)) return PETSC_FALSE;
25b10005b4SLisandro Dalcin   /* Fast path for exact equality or two infinities of same sign */
26b10005b4SLisandro Dalcin   if (a == b) return PETSC_TRUE;
27b10005b4SLisandro Dalcin   /* Handle two infinities of opposite sign */
28b10005b4SLisandro Dalcin   if (PetscIsInfReal(a) || PetscIsInfReal(b)) return PETSC_FALSE;
29b10005b4SLisandro Dalcin   /* Cannot error if tolerances are negative */
309371c9d4SSatish Balay   rtol = PetscAbsReal(rtol);
319371c9d4SSatish Balay   atol = PetscAbsReal(atol);
32b10005b4SLisandro Dalcin   /* The regular check for difference within tolerances */
33b10005b4SLisandro Dalcin   diff = PetscAbsReal(b - a);
34b10005b4SLisandro Dalcin   return ((diff <= PetscAbsReal(rtol * b)) || (diff <= PetscAbsReal(rtol * a)) || (diff <= atol)) ? PETSC_TRUE : PETSC_FALSE;
35b10005b4SLisandro Dalcin }
36