...
Code Block |
---|
#include <math.h> #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) #include <fenv.h> #pragma STDC FENV_ACCESS ON #endif #include <errno.h> /* ... */ #if defined(math_errhandling) \ && (math/* Where you want to call a function and check errors */ { #pragma STDC FENV_ACCESS ON if (math_errhandling & MATH_ERREXCEPT) { feclearexcept(FE_ALL_EXCEPT); #endif } errno = 0; /* Call the function */ #if !defined(math_errhandling) \ || if ((math_errhandling & MATH_ERRNO) if (&& errno != 0) { /* Handle range error */ } #endif #if defined(math_errhandling) \ && } else if ((math_errhandling & MATH_ERREXCEPT) if (fetestexcept(FE_INVALID && fetestexcept(FE_INVALID | FE_DIVBYZERO | | FE_OVERFLOW FE_OVERFLOW | FE_UNDERFLOW) != 0) { /* Handle range error */ } #endif} |
See FLP03-C. Detect and handle floating-point errors for more details on how to detect floating-point errors.
...
A subnormal number is a nonzero number that does not use all of its precision bits [IEEE 754 2006 ]. They can be used to represent values that are closer to 0 than the smallest normal number (one that uses all of its precision bits). However, certain functions may produce range errors specifically when applied with a subnormal number. These functions are: asin()
, asinh()
, atan()
, atanh()
, and erf()
. When evaluated with a subnormal number, these functions can produce an inexact, subnormal value, which is an underflow error. Subclause 7.12.1, paragraph 6, of the C Standard [ISO/IEC 9899:2011] defines the following behavior for floating-point underflow:
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <errno<math.h> #include <math<fenv.h> #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) #include <fenv.h> #pragma STDC FENV_ACCESS ON #endif #include <errno.h> void func(double x) { double result; { errno = 0; #pragma #ifSTDC defined(math_errhandling) \FENV_ACCESS ON &&if (math_errhandling & MATH_ERREXCEPT) { feclearexcept(FE_ALL_EXCEPT); #endif } errno = 0; result = sinh(x); #if !defined(math_errhandling) \ ||if ((math_errhandling & MATH_ERRNO) if&& (errno != 0) { /* Handle range error */ } #endif } else #ifif defined((math_errhandling) \ && (math_errhandling & & MATH_ERREXCEPT) if (fetestexcept(FE_INVALID && fetestexcept(FE_INVALID | FE_DIVBYZERO | | FE_OVERFLOW FE_OVERFLOW | FE_UNDERFLOW) != 0) { /* Handle range error */ } #endif }} /* Use result... */ } |
Noncompliant Code Example (Noncompliant Code Example (pow()
)
This noncompliant code example raises x
to the power of y
:
...
Code Block | ||||
---|---|---|---|---|
| ||||
#include <errno<math.h> #include <math<fenv.h> #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) #include <fenv<errno.h> #pragma STDC FENV_ACCESS ON #endif void func(double x, double y) { #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) feclearexcept(FE_ALL_EXCEPT); #endif errno = 0; { double result; if (((x == 0.0f) && islessequal(y, 0.0)) || isless(x, 0.0)) || isless(x, 0.0)) { /* Handle domain or pole error */ } { #pragma STDC FENV_ACCESS ON if (math_errhandling & MATH_ERREXCEPT) { /* Handle domain or pole error */ } feclearexcept(FE_ALL_EXCEPT); } errno = 0; result = pow(x, y); #if !defined(math_errhandling) \ y); ||if ((math_errhandling & MATH_ERRNO) if&& (errno != 0) { /* Handle range error */ } #endif } else #ifif defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) if (fetestexcept(FE_INVALID && fetestexcept(FE_INVALID | FE_DIVBYZERO | | FE_OVERFLOW FE_OVERFLOW | FE_UNDERFLOW) != 0) { /* Handle range error */ } #endif} /* Use result... */ } |
Noncompliant Code Example (asin()
, Subnormal Number)
...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
#include <math.h>#include <errno.h> #include <math.h> #if defined(math_errhandling) \ && (math_errhandling & MATH_ERREXCEPT) #include <fenv.h> #pragma STDC FENV_ACCESS ON #endif #include <errno.h> void func(float x) { float result; errno = 0;{ result = asin(x); #if defined(math_errhandling) \ #pragma STDC FENV_ACCESS ON &&if (math_errhandling & MATH_ERREXCEPT) { feclearexcept(FE_ALL_EXCEPT); #endif } errno = 0; result #if= !defined(math_errhandling) \asinh(x); ||if ((math_errhandling & MATH_ERRNO) && if (errno != 0) { /* Handle range error */ } #endif #if defined(math_errhandling) \ &&} else if ((math_errhandling & MATH_ERREXCEPT) if (fetestexcept(FE_INVALID && fetestexcept(FE_INVALID | FE_DIVBYZERO | | FE_OVERFLOW FE_OVERFLOW | FE_UNDERFLOW) != 0) { /* Handle range error */ } #endif} /* Use result... */ } |
Risk Assessment
Failure to prevent or detect domain and range errors in math functions may cause unexpected results.
...