Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated the boilerplate code to not presume math_errhandling is a macro

...

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
bgColor#ccccff
langc
#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
bgColor#ccccff
langc
#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
bgColor#ccccff
langcc
#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.

...