Using the Floating Point Exception Handling (-fpe) Option

The Fortran compiler supports several kinds of floating-point exceptions; a summary of their masked (or default) responses is given below:

For example,  in round-to-nearest mode 1E30 * 1E30 overflows the single-precision floating-point range and results in a +Infinity;  -1E30 * 1E30 results in a -Infinity.

The -fpen option allows some control over the results of floating-point exceptions.

-fpe0 restricts floating-point exceptions as follows:

Note
On IA-32 and Intel® EM64T systems, explicitly setting -fpe0 can degrade performance since the generated code stream must be synchronized after each floating-point instruction to allow for abrupt underflow fix-up.

-fpe1 restricts only floating-point underflow:

-fpe3, the default, allows full floating-point exception behavior:

The -fpe option affects the Fortran main program only.  The floating-point exception behavior set by the Fortran main program remains in effect throughout the execution of the entire program unless changed by the programmer. If the main program is not Fortran, the user can use the Fortran intrinsic FOR_SET_FPE to set the floating-point exception behavior.

When compiling different routines in a program separately, you should use the same value of n in -fpen.

An example follows:

       IMPLICIT NONE

       real*4 res_uflow, res_oflow

       real*4 res_dbyz, res_inv

       real*4 small, big, zero, scale

       small = 1.0e-30

       big   = 1.0e30

       zero  = 0.0

       scale = 1.0e-10

!      IEEE underflow condition (Underflow Raised)

       res_uflow = small * scale

       write(6,100)"Underflow: ",small, " *", scale, " = ", res_uflow

!      IEEE overflow condition (Overflow Raised)

       res_oflow = big * big

       write(6,100)"Overflow: ", big, " *", big, " = ", res_oflow

!      IEEE divide-by-zero condition (Divide by Zero Raised)

       res_dbyz = -big / zero

       write(6,100)"Div-by-zero: ", -big, " /", zero, " = ", res_dbyz

!      IEEE invalid condition (Invalid Raised)

       res_inv = zero / zero

       write(6,100)"Invalid: ", zero, " /", zero, " = ", res_inv

 100   format(A14,E8.1,A2,E8.1,A2,E10.1)

       end

Consider the following command line:

ifort fpe.f -fpe0 -g

The following output is produced:

./a.out

   Underflow:  0.1E-29 * 0.1E-09 =   0.0E+00

forrtl: error (72): floating overflow

Image       PC        Routine     Line        Source

a.out       0804A063  Unknown     Unknown  Unknown

a.out       08049E78  Unknown     Unknown  Unknown

Unknown     B746B748  Unknown     Unknown  Unknown

a.out       08049D31  Unknown     Unknown  Unknown

Aborted

The following command line uses -fpe1:

ifort fpe.f -fpe1 -g

The following output is produced:

./a.out

   Underflow:  0.1E-29 * 0.1E-09 =   0.0E+00

    Overflow:  0.1E+31 * 0.1E+31 = Infinity

 Div-by-zero: -0.1E+31 / 0.0E+00 = -Infinity

     Invalid:  0.0E+00 / 0.0E+00 = NaN

The following command line uses -fpe3:

ifort fpe.f -fpe3 -g

The following output is produced:

./a.out

   Underflow:  0.1E-29 * 0.1E-09 =   0.1E-39

    Overflow:  0.1E+31 * 0.1E+31 = Infinity

 Div-by-zero: -0.1E+31 / 0.0E+00 = -Infinity

     Invalid:  0.0E+00 / 0.0E+00 = NaN

Relationship between the -fpe Option and the -ftz Option

The -ftz option affects the results of floating underflow in the following ways:

The -ftz option sets or resets the FTZ and the DAZ hardware flags in the MXCSR register. Setting FTZ on means that denormal results from floating-point calculations will be set to the value zero. If FTZ is off, denormal results remain as is. Setting DAZ on means that denormal values used as input to floating-point instructions will be treated as zero.  If DAZ is off, denormal instruction inputs remain as is.  

Itanium®-based systems have the FTZ, but not the DAZ hardware flag.  Intel® EM64T-based systems have both FTZ and DAZ hardware flags.  FTZ and DAZ are not supported on all IA-32 architectures.  

When -ftz is used in combination with an SSE-enabling option (for example, -xN) on IA-32 systems, the compiler will insert code in the main routine to set FTZ and DAZ.  When -ftz is used without such an option, the compiler will insert code to conditionally set FTZ/DAZ based on a runtime processor check (this processor check fails for non-Intel machines).  Specifying -no-ftz will prevent the compiler from inserting any code that might set FTZ or DAZ.

On IA-32 and Intel® EM64T systems with SSE and SSE2 code, there is no performance degradation and possibly even a performance gain due to the fact that the hardware handles the denormals. The default setting of abrupt underflow affects the SSE hardware, not the instruction stream.

On Itanium®-based processors, gradual underflow to 0 can degrade performance. You can improve performance by using higher optimization levels to get the default abrupt underflow or explicitly setting -ftz.

See Also:

-fpe compiler option
-ftz
compiler option