xref: /petsc/src/sys/utils/mathclose.c (revision b0b385f45f76f1e108f857efe1d02ffe3b58ed6c)
1 #include <petscsys.h>
2 
3 /*@C
4   PetscIsCloseAtTol - Returns whether the two `PetscReal` numbers
5   are close at a given relative and absolute tolerances <https://www.python.org/dev/peps/pep-0485/>.
6 
7   Input Parameters:
8 + a    - first floating point number
9 . b    - second floating point number
10 . rtol - relative tolerance
11 - atol - absolute tolerances
12 
13   Level: beginner
14 
15 .seealso: `PetscIsCloseAtTolScalar()`, `PetscEqualReal()`, `PetscEqualScalar()`
16 @*/
17 PetscBool PetscIsCloseAtTol(PetscReal a, PetscReal b, PetscReal rtol, PetscReal atol)
18 {
19   PetscReal diff;
20   /* NaN is not considered close to any other value, including NaN */
21   if (PetscIsNanReal(a) || PetscIsNanReal(b)) return PETSC_FALSE;
22   /* Fast path for exact equality or two infinities of same sign */
23   if (a == b) return PETSC_TRUE;
24   /* Handle two infinities of opposite sign */
25   if (PetscIsInfReal(a) || PetscIsInfReal(b)) return PETSC_FALSE;
26   /* Cannot error if tolerances are negative */
27   rtol = PetscAbsReal(rtol);
28   atol = PetscAbsReal(atol);
29   /* The regular check for difference within tolerances */
30   diff = PetscAbsReal(b - a);
31   return ((diff <= PetscAbsReal(rtol * b)) || (diff <= PetscAbsReal(rtol * a)) || (diff <= atol)) ? PETSC_TRUE : PETSC_FALSE;
32 }
33