Introduction.
Using the fpe module.
Acquiring the fpe module source.
Linking with the fpe module.
Portability issues.
The the fpe module API:
Numbers on digital computers are represented as a series of bits,
and thus intrinsically only deal with integers. A number model
for "real" numbers is generally used to provide a representation of
non-integers. Since only a finite number of bits is used, this
representation does not actually map onto the real number set, but a
finite set of those numbers admitting a terminating representation
(i.e excluding irrational numbers and non-terminating fractions). This
number model is now almost universally based on floating-point (FP)
numbers, using a mantissa and an exponent. The IEEE has
specified a standard FP number model, which is used on most, but not
all, modern computers.
When FP computations produce numbers that cannot be represented in the
number model, an exception is said to have occurred. Exceptions
fall into several classes, of which the most common include:
Computing units maintain a word in memory in order to track the
occurrence of exceptions. Each bit in this word signals the occurrence
of a different class of exceptions, such as those listed above. This
word must be tested to know if an exception has occurred. The result
of this test can be used to control subsequent program behaviour,
Principally, we might wish to interrupt the program if certain classes
of exceptions occur, though other more refined consequences may also
be imagined.
There is a computational burden associated with testing for
exceptions, and also one with continuing the execution of a program
after the computation has gone awry. This module provides a standard
interface to a simple range of behaviour under exceptions. This
include enabling and disabling interrupts for certain classes of
exceptions, and a trap function that merely signals to the user that
an exception has occurred.
The fpe module defines four classes of exceptions:
FP_DIVIDE_BY_ZERO, FP_OPERAND_IS_NAN, FP_OVERFLOW,
FP_UNDERFLOW. These are integers and may be summed to
designate multiple classes.
The calls fpe_enable and fpe_disable may be used
to turn on FP error interrupts for different code
sections. fpe_trap returns .TRUE. if an exception
has occurred. Consider the test program:
This produces (on SGIs) the output:
This example provides a comprehensive test case for the FPE module.
In the first computation of 1./(1.-1.), FPE interrupts
have been disabled.
Before the computation the FP_DIVIDE_BY_ZERO exception is
shown as not having occurred. Subsequently this exception bit has been
set to .TRUE. In the second instance, FPE interrupts have
been enabled, and cause the program to abort.
The public interfaces to the fpe module are described here
in alphabetical order. The fpe module defines four classes of
exceptions: FP_DIVIDE_BY_ZERO, FP_OPERAND_IS_NAN, FP_OVERFLOW,
FP_UNDERFLOW, which are public integer parameters use-associated
from the module. The argument flag to any of the routines
below can be a sum of any of these. An absent flag argument
is equivalent to all of the exceptions, i.e equivalent to
flag=FP_DIVIDE_BY_ZERO+FP_OPERAND_IS_NAN+FP_OVERFLOW+FP_UNDERFLOW.
Causes the program to continue execution even if one of the exceptions
in flag has occurred, until a subsequent call to fpe_enable.
GFDL users can copy the file
/net/vb/public/utils/fpe.F90. External users can
download the source here. The
current public version number is 2.2.
Any module or program unit using the fpe module must
contain the line
The source file for the fpe module is fpe.F90.
Compiling with the cpp flag test_fpe turned on:
will produce a program that will exercise certain portions of the
the fpe module module.
This will shortly be extended to various compilers on the Linux
platform. The module is deemed unnecessary on Crays, on which GFDL
seems to have got by quite satisfactorily for many years without this
degree of user control.
Tim Yeager has written an
excellent introduction to FPE behaviour for GFDL users, including
various run-time and compile-time options for controlling this
behaviour. Slides from his recent talk on the subject, and associated
files, are available in /home/ty/doc/trap.talk.
Introduction
Using the fpe module
program fpetest
use fpe
implicit none
real :: a, b
a = 1.
b = 1.
print *
print *, 'Divide by zero with interrupts disabled...'
call fpe_disable(FP_DIVIDE_BY_ZERO)
print *, 'fpe_trap(FP_DIVIDE_BY_ZERO)=', fpe_trap(FP_DIVIDE_BY_ZERO)
print *, 'divide by zero=', a/(a-b)
print *, 'fpe_trap(FP_DIVIDE_BY_ZERO)=', fpe_trap(FP_DIVIDE_BY_ZERO)
print *
print *, 'Divide by zero with interrupts enabled...'
print *, 'The next line should be an abort message:'
call fpe_enable(FP_DIVIDE_BY_ZERO)
print *, 'divide by zero=', a/(a-b)
end program fpetest
Divide by zero with interrupts disabled...
fpe_trap(FP_DIVIDE_BY_ZERO)= F
divide by zero= Infinity
fpe_trap(FP_DIVIDE_BY_ZERO)= T
Divide by zero with interrupts enabled...
The next line should be an abort message:
Floating Exception
Abort
FPE module call syntax
fpe_disable
subroutine fpe_disable(flag)
integer, intent(in), optional :: flag
Acquiring fpe module source
Compiling and linking to fpe module
use fpe
f90 -Dtest_fpe fpe.F90
Portability issues
The fpe module was written specifically for the SGIs using
the MIPSpro f90 compiler. They use the non-standard
FTN_IEEE_DEFINITIONS module that comes with this compiler and
provides exception handling functionality following the IEEE FP number
model.
Changes
The RCS log for
fpe.F90 contains a comprehensive list of changes. In the
unlikely event that you should wish to check out a retro version,
please get in touch with me, Balaji.