Go to main content
Oracle® Developer Studio 12.6: Numerical Computation Guide

Exit Print View

Updated: July 2017
 
 

3.5 C99 Floating-Point Environment Functions

This section describes the <fenv.h> floating-point environment functions in C99. In the Oracle Solaris 10 OS, these functions are available in libm. They provide many of the same capabilities as the ieee_flags function, but they use a more natural C interface, and because they are defined by C99, they are more portable.


Note -  For consistent behavior, do not use both C99 floating-point environment functions and exception handling extensions in libm and the ieee_flags and ieee_handler functions in libsunmath in the same program.

3.5.1 Exception Flag Functions

The fenv.h file defines macros for each of the five IEEE floating-point exception flags: FE_INEXACT, FE_UNDERFLOW, FE_OVERFLOW, FE_DIVBYZERO, and FE_INVALID. In addition, the macro FE_ALL_EXCEPT is defined to be the bitwise “or” of all five flag macros. In the following descriptions, the excepts parameter might be a bitwise “or” of any of the five flag macros or the value FE_ALL_EXCEPT. For the fegetexceptflag and fesetexceptflag functions, the flagp parameter must be a pointer to an object of type fexcept_t. This type is defined in fenv.h.

C99 defines the exception flag functions in the following table:

Table 28  C99 Standard Exception Flag Functions
Function
Action
feclearexcept(excepts)
clear specified flags
fetestexcept(excepts)
return settings of specified flags
feraiseexcept(excepts)
raise specified exceptions
fegetexceptflag(flagp, excepts)
save specified flags in *flagp
fesetexceptflag(flagp, excepts)
restore specified flags from *flagp

The feclearexcept function clears the specified flags. The fetestexcept function returns a bitwise “or” of the macro values corresponding to the subset of flags specified by the excepts argument that are set. For example, if the only flags currently set are inexact, underflow, and division by zero, then the following would set i to FE_DIVBYZERO.

i = fetestexcept(FE_INVALID | FE_DIVBYZERO);

The feraiseexcept function causes a trap if any of the specified exceptions' trap is enabled. Otherwise, it merely sets the corresponding flags. See Exceptions and Exception Handling for more information on exception traps.

The fegetexceptflag and fesetexceptflag functions provide a convenient way to temporarily save the state of certain flags and later restore them. In particular, the fesetexceptflag function does not cause a trap; it merely restores the values of the specified flags.

3.5.2 Rounding Control

The fenv.h file defines macros for each of the four IEEE rounding direction modes: FE_TONEAREST, FE_UPWARD (toward positive infinity), FE_DOWNWARD (toward negative infinity), and FE_TOWARDZERO. C99 defines two functions to control rounding direction modes: fesetround sets the current rounding direction to the direction specified by its argument (which must be one of the four macros above), and fegetround returns the value of the macro corresponding to the current rounding direction.

On x86-based systems, the fenv.h file defines macros for each of three rounding precision modes: FE_FLTPREC (single precision), FE_DBLPREC (double precision), and FE_LDBLPREC (extended double precision). Although they are not part of C99, libm on x86 provides two functions to control the rounding precision mode: fesetprec sets the current rounding precision to the precision specified by its argument which must be one of the three macros above, and fegetprec returns the value of the macro corresponding to the current rounding precision.

3.5.3 Environment Functions

The fenv.h file defines the data type fenv_t, which represents the entire floating-point environment including exception flags, rounding control modes, exception handling modes, and, on SPARC, nonstandard mode. In the descriptions that follow, the envp parameter must be a pointer to an object of type fenv_t.

C99 defines four functions to manipulate the floating-point environment. libm provides an additional function that can be useful in multi-threaded programs. These functions are summarized in the following table:

Table 29  libm Floating-Point Environment Functions
Function
Action
fegetenv(envp)
save environment in *envp
fesetenv(envp)
restore environment from *envp
feholdexcept(envp)
save environment in *envp and establish nonstop mode
feupdateenv(envp)
restore environment from *envp and raise exceptions
fex_merge_flags(envp)
“or” exception flags from *envp

The fegetenv and fesetenv functions respectively save and restore the floating-point environment. The argument to fesetenv can be either a pointer to an environment previously saved by a call to fegetenv or feholdexcept or the constant FE_DFL_ENV defined in fenv.h. The latter represents the default environment with all exception flags clear, rounding to nearest and to extended double precision on x86-based systems, nonstop exception handling mode (i.e., traps disabled), and nonstandard mode disabled.

The feholdexcept function saves the current environment and then clears all exception flags and establishes nonstop exception handling mode for all exceptions. The feupdateenv function restores a saved environment (which might be one saved by a call to fegetenv or feholdexcept or the constant FE_DFL_ENV), then raises those exceptions whose flags were set in the previous environment. If the restored environment has traps enabled for any of those exceptions, a trap occurs; otherwise the flags are set. These two functions can be used in conjunction to make a subroutine call appear to be atomic with regard to exceptions, as the following code sample shows:

#include <fenv.h>
 
void myfunc(...) {
    fenv_t env;
 
    /* save the environment, clear flags, and disable traps */
    feholdexcept(&env);
    /* do a computation that may incur exceptions */
    ...
    /* check for spurious exceptions */
    if (fetestexcept(...)) {
        /* handle them appropriately and clear their flags */
        ...
        feclearexcept(...);
    }
    /* restore the environment and raise relevant exceptions */
    feupdateenv(&env);
}

The fex_merge_flags function performs a logical OR of the exception flags from the saved environment into the current environment without provoking any traps. This function can be used in a multi-threaded program to preserve information in the parent thread about flags that were raised by a computation in a child thread. See Examples for an example showing the use of fex_merge_flags.