isNumericallyEqual(x,y) compares two scalar types using a tolerance (default or explicitly specified) and returns true if they are close enough.
isNumericallyEqual(x,y) compares two scalar types using a tolerance (default or explicitly specified) and returns true if they are close enough.
The default tolerance used is the NTraits<P>::getSignificant() value (about 1e-14 in double precision, 1e-6 in float) for the narrower of the types being compared but you can override that. The tolerance is both a relative and absolute tolerance; for two numbers a and b and tolerance tol we compute the following condition:
scale = max(|a|,|b|,1)
isNumericallyEqual = |a-b| <= scale*tol
For complex or conjugate numbers we insist that both the real and imaginary parts independently satisfy the above condition.
- Mixed precision
- We support mixed argument types here in which case the default tolerance used is the one appropriate to the lower-precision argument. When one argument is an integer, the default tolerance used is that of the floating point argument. Comparisons may be performed at a higher precision than the tolerance to avoid incorrect truncation; for example an int cannot generally be contained in a float so an int/float comparison is done as double/double, but to float tolerance.
- Treatment of NaN
- When both arguments are NaN they are considered equal here, which is different than the behavior of the IEEE-sanctioned "==" comparison for which NaN==NaN returns false. If only one argument is NaN we return false. When comparing complex or conjugate numbers the real and imaginary parts are tested separately, so (NaN,0) and (0,NaN) don't test equal despite the fact that isNaN() would return true for both of them. We don't distinguish among types of NaNs, though, so NaN and -NaN (if there is such a thing) will test numerically equal.