XL Fortran for AIX 8.1

User's Guide


Detecting and Trapping Floating-Point Exceptions

As stated earlier, the IEEE standard for floating-point arithmetic defines a number of exception (or error) conditions that might require special care to avoid or recover from. The following sections are intended to help you make your programs work safely in the presence of such exception conditions while sacrificing the minimum amount of performance.

The floating-point hardware always detects a number of floating-point exception conditions (which the IEEE standard rigorously defines): overflow, underflow, zerodivide, invalid, and inexact.

By default, the only action that occurs is that a status flag is set. The program continues without a problem (although the results from that point on may not be what you expect). If you want to know when an exception occurs, you can arrange for one or more of these exception conditions to generate a signal.

The signal causes a branch to a handler routine. The handler receives information about the type of signal and the state of the program when the signal occurred. It can produce a core dump, display a listing showing where the exception occurred, modify the results of the calculation, or carry out some other processing that you specify.

Both the XL Fortran compiler and the operating system provide facilities for working with floating-point exception conditions. The compiler facilities indicate the presence of exceptions by generating SIGTRAP signals. The operating-system facilities generate SIGFPE signals. Do not mix these different facilities within a single program.

Compiler Features for Trapping Floating-Point Exceptions

To turn on XL Fortran exception trapping, compile the program with the -qflttrap option and some combination of suboptions that includes enable. This option uses trap operations to detect floating-point exceptions and generates SIGTRAP signals when exceptions occur.

-qflttrap also has suboptions that correspond to the names of the exception conditions. For example, if you are only concerned with handling overflow and underflow exceptions, you could specify something similar to the following:

  xlf95 -qflttrap=overflow:underflow:enable compute_pi.f
You only need enable when you are compiling the main program. However, it is very important and does not cause any problems if you specify it for other files, so always include it when you use -qflttrap.

An advantage of this approach is that performance impact is relatively low. To further reduce performance impact, you can include the imprecise suboption of the -qflttrap option. This suboption delays any trapping until the program reaches the start or end of a subprogram.

The disadvantages of this approach include the following:

Notes:

  1. If your program depends on floating-point exceptions occurring for particular operations, also specify -qfloat suboptions that include nofold and nohssngl. Otherwise, the compiler might replace an exception-producing calculation with a constant NaN or infinity value, or it might eliminate an overflow in a single-precision operation.

  2. The suboptions of the -qflttrap option replace an earlier technique that required you to modify your code with calls to the fpsets and fpgets procedures. You no longer require these calls for exception handling if you use the appropriate -qflttrap settings.

    Attention: If your code contains fpsets calls that enable checking for floating-point exceptions and you do not use the -qflttrap option when compiling the whole program, the program will produce unexpected results if exceptions occur, as explained in Table 18.

Operating System Features for Trapping Floating-Point Exceptions

A direct way to turn on exception trapping is to call the operating system routine fp_trap. It uses the system hardware to detect floating-point exceptions and generates SIGFPE signals when exceptions occur. Fortran definitions for the values needed to call it are in the files /usr/include/fp_fort_c.f, fp_fort_t.f, or the xlf_fp_util module.

There are other related operating system routines that you can locate by reading the description of fp_trap.

The advantages of this approach include:

The disadvantages of this approach include:

Installing an Exception Handler

When a program that uses the XL Fortran or AIX exception-detection facilities encounters an exception condition, it generates a signal. This causes a branch to whatever handler is specified by the program. The information in this section, except the explanation of the -qsigtrap option, applies both to SIGTRAP and SIGFPE signals.

By default, the program stops after producing a core file, which you can use with a debugger to locate the problem. If you want to install a SIGTRAP signal handler, use the -qsigtrap option. It allows you to specify an XL Fortran handler that produces a traceback or to specify a handler you have written:

xlf95 -qflttrap=ov:und:en pi.f                             # Dump core on an exception
xlf95 -qflttrap=ov:und:en -qsigtrap pi.f                   # Uses the xl__trce handler
xlf95 -qflttrap=ov:und:en -qsigtrap=return_22_over_7 pi.f  # Uses any other handler

You can also install an alternative exception handler, either one supplied by XL Fortran or one you have written yourself, by calling the SIGNAL subroutine (defined in /usr/include/fexcp.h):

  INCLUDE 'fexcp.h'
  CALL SIGNAL(SIGTRAP,handler_name)
  CALL SIGNAL(SIGFPE,handler_name)

The XL Fortran exception handlers and related routines are:

xl__ieee
Produces a traceback and an explanation of the signal and continues execution by supplying the default IEEE result for the failed computation. This handler allows the program to produce the same results as if exception detection was not turned on.

xl__trce
Produces a traceback and stops the program.

xl__trcedump
Produces a traceback and a core file and stops the program.

xl__sigdump
Provides a traceback that starts from the point at which it is called and provides information about the signal. You can only call it from inside a user-written signal handler, and it requires the same parameters as other AIX signal handlers. It does not stop the program. To successfully continue, the signal handler must perform some cleanup after calling this subprogram.

xl__trbk
Provides a traceback that starts from the point at which it is called. You call it as a subroutine from your code, rather than specifying it with the -qsigtrap option. It requires no parameters. It does not stop the program.

All of these handler names contain double underscores to avoid duplicating names that you declared in your program. All of these routines work for both SIGTRAP and SIGFPE signals.

You can use the -g compiler option to get line numbers in the traceback listings. The file /usr/include/fsignal.h defines a Fortran derived type similar to the sigcontext structure in /usr/include/sys/signal.h. You can write a Fortran signal handler that accesses this derived type.

Related Information:
Sample Programs for Exception Handling lists some sample programs that illustrate how to use these signal handlers or write your own. For more information on SIGNAL, see the "Intrinsic Procedures" chapter in the XL Fortran for AIX Language Reference.

Producing a Core File

To produce a core file, do not install an exception handler, or else specify the xl__trcedump handler.

Controlling the Floating-Point Status and Control Register

Before the -qflttrap suboptions or the -qsigtrap options, most of the processing for floating-point exceptions required you to change your source files to turn on exception trapping or install a signal handler. Although you can still do so, for any new applications, we recommend that you use the options instead.

To control exception handling at run time, compile without the enable suboption of the -qflttrap option:

   xlf95 -qflttrap compute_pi.f     # Check all exceptions, but do not trap.
   xlf95 -qflttrap=ov compute_pi.f  # Check one type, but do not trap.

Then, inside your program, manipulate the fpstats array (defined in the include file /usr/include/fpdc.h) and call the fpsets subroutine to specify which exceptions should generate traps.

See the sample program that uses fpsets and fpgets in Selecting the Rounding Mode.

Another method is to use the set_fpscr_flags() subroutine in the xlf_fp_util module. This subroutine allows you to set the floating-point status and control register flags you specify in the MASK argument. Flags that you do not specify in MASK remain unaffected. MASK must be of type INTEGER(FPSCR_KIND). For example:

 USE XLF_FP_UTIL
 INTEGER(FPSCR_KIND) SAVED_FPSCR
 INTEGER(FP_MODE_KIND) FP_MODE
 
 SAVED_FPSCR = get_fpscr()           ! Saves the current value of
                                     ! the fpscr register.
 
 CALL set_fpscr_flags(TRP_DIV_BY_ZERO) ! Enables trapping of
 ! ...                                 ! divide-by-zero.
 SAVED_FPSCR=set_fpscr(SAVED_FPSCR)    ! Restores fpscr register.

xlf_fp_util Procedures

The xlf_fp_util procedures allow you to query and control the floating-point status and control register (fpscr) of the processor directly. These procedures are more efficient than the fpsets and fpgets subroutines because they are mapped into inlined machine instructions that manipulate the floating-point status and control register directly.

The module, xlf_fp_util, contains the interfaces and data type definitions for these procedures and the definitions for the named constants that are needed by the procedures. This module enables type checking of these procedures at compile time rather than link time. The following files are supplied for the modules xlf_fp_util:

File names File type Locations
xlf_fp_util.mod module symbol file (32-bit)
  • /usr/lpp/xlf/include_32_d10
  • /usr/lpp/xlf/include_32_d7
Note:
The files in these directories are exact copies of one another.
module symbol file (64-bit) /usr/lpp/xlf/include_64

module symbol file (64-bit LDT) /usr/lpp/xlf/include_64ldt

To use the procedures, you must add a USE XLF_FP_UTIL statement to your source file. For more information on USE, refer to the XL Fortran for AIX Language Reference.

When compiling with the -U option, you must code the names of these procedures in all lowercase.

For a list of the xlf_fp_util procedures, see the "Service and Utility Procedures" chapter in the XL Fortran for AIX Language Reference.

fpgets and fpsets Subroutines

The fpsets and fpgets subroutines provide a way to manipulate or query the floating-point status and control register. Instead of calling the operating system routines directly, you pass information back and forth in fpstat, an array of logicals. The following table shows the most commonly used array elements that deal with exceptions:

Table 20. Exception Bits to Use with fpsets and fpgets

Array Element to
Set to Enable
Array Element to
Check if Exception
Occurred
Exception Indicated When .TRUE.
n/a fpstat(fpfx) Floating-point exception summary
n/a fpstat(fpfex) Floating-point enabled exception summary
fpstat(fpve) fpstat(fpvx) Floating-point invalid operation exception summary
fpstat(fpoe) fpstat(fpox) Floating-point overflow exception
fpstat(fpue) fpstat(fpux) Floating-point underflow exception
fpstat(fpze) fpstat(fpzx) Zero-divide exception
fpstat(fpxe) fpstat(fpxx) Inexact exception
fpstat(fpve) fpstat(fpvxsnan) Floating-point invalid operation exception (NaNS)
fpstat(fpve) fpstat(fpvxisi) Floating-point invalid operation exception (INF-INF)
fpstat(fpve) fpstat(fpvxidi) Floating-point invalid operation exception (INF/INF)
fpstat(fpve) fpstat(fpvxzdz) Floating-point invalid operation exception (0/0)
fpstat(fpve) fpstat(fpvximz) Floating-point invalid operation exception (INF*0)
fpstat(fpve) fpstat(fpvxvc) Floating-point invalid operation exception (invalid compare)
n/a fpstat(fpvxsoft) Floating-point invalid operation exception (software request), PowerPC only
n/a fpstat(fpvxsqrt) Floating-point invalid operation exception (invalid square root), PowerPC only
n/a fpstat(fpvxcvi) Floating-point invalid operation exception (invalid integer convert), PowerPC only

To explicitly check for specific exceptions at particular points in a program, use fpgets and then test whether the elements in fpstat have changed. Once an exception has occurred, the corresponding exception bit (second column in the preceding table) is set until it is explicitly reset, except for fpstat(fpfx), fpstat(fpvx), and fpstat(fpfex), which are reset only when the specific exception bits are reset.

An advantage of using the fpgets and fpsets subroutines (as opposed to controlling everything with suboptions of the -qflttrap option) includes control over granularity of exception checking. For example, you might only want to test if an exception occurred anywhere in the program when the program ends.

The disadvantages of this approach include the following:

For example, to trap floating-point overflow exceptions but only in a certain section of the program, you would set fpstat(fpoe) to .TRUE. and call fpsets. After the exception occurs, the corresponding exception bit, fpstat(fpox), is .TRUE. until the program runs:

      call fpgets(fpstat)
      fpstat(fpox) = .FALSE.
      call fpsets(fpstat)   ! resetting fpstat(fpox) to .FALSE.

Sample Programs for Exception Handling

/usr/lpp/xlf/samples/floating_point contains a number of sample programs to illustrate different aspects of exception handling:

flttrap_handler.c  and  flttrap_test.f
A sample exception handler that is written in C and a Fortran program that uses it.

xl__ieee.F  and  xl__ieee.c
Exception handlers that are written in Fortran and C that show how to substitute particular values for operations that produce exceptions. Even when you use support code such as this, the implementation of XL Fortran exception handling does not fully support the exception-handling environment that is suggested by the IEEE floating-point standard.

check_fpscr.f  and  postmortem.f
Show how to work with the fpsets and fpgets procedures and the fpstats array.

fhandler.F
Shows a sample Fortran signal handler and demonstrates the xl__sigdump procedure.

xl__trbk_test.f
Shows how to use the xl__trbk procedure to generate a traceback listing without stopping the program.

The sample programs are strictly for illustrative purposes only.

Causing Exceptions for Particular Variables

To mark a variable as "do not use", you can encode a special value called a signaling NaN (NaNS) in it. This causes an invalid exception condition any time that variable is used in a calculation.

If you use this technique, use the nans suboption of the -qfloat option, so that the program properly detects all cases where a NaNS is used, and one of the methods already described to generate corresponding SIGFPE or SIGTRAP signals.

Notes:

  1. Because a NaNS is never generated as the result of a calculation and must be explicitly introduced to your program as a constant or in input data, you should not need to use this technique unless you deliberately use NaNS values in it.
  2. In previous XL Fortran releases, the -qfloat suboption was called spnans. In the future, use nans instead (although spnans still works, for backward compatibility).

Minimizing the Performance Impact of Floating-Point Exception Trapping

If you need to deal with floating-point exception conditions but are concerned that doing so will make your program too slow, here are some techniques that can help minimize the performance impact:


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]