2
All interactive numerical programs benefit from prompt delivery of
3
SIGFPE signals. The processor should trap on zero divide, overflow,
4
or invalid operations, and give the process a chance to abort the
5
operation cleanly. Testing for these conditions (which is supported
6
in a portable fashion by the C9X standard) is at best a poor
7
substitute for prompt interrupt, since it must be done in a very large
8
number of places in the code. Testing on an operation by operation
9
basis (as would be necessary before C9X) will obviously ruin
10
performance of any numerically demanding program (you'd need to take
11
logarithms to check for overflow, for example). Allowing huge arrays
12
of numbers to slowly fill wil NaN and Inf wastes computer time, and
13
makes debugging nearly impossible.
15
Every UNIX operating system and machine requires a different procedure
16
for setting up the hardware to trap and deliver this interrupt; the
17
universal default is to ignore all floating point errors. I know how
18
to set up the FPU for the following platforms:
20
FPU_DIGITAL DEC Alpha / Digital UNIX (FPU_ALPHA_LINUX also works?)
21
FPU_AIX IBM RS6000 / AIX
22
FPU_HPUX HP PA-RISC / HPUX
23
FPU_IRIX SGI MIPS / IRIX
24
FPU_SUN4 Sun SPARC / SunOS 4
25
FPU_SOLARIS Sun SPARC / Solaris (SunOS 5)
26
FPU_UNICOS Cray X/YMP, J90 / UNICOS
27
FPU_ALPHA_LINUX DEC Alpha / Linux
28
FPU_GCC_I86 Intel x86 / gcc (Linux)
29
FPU_GCC_POWERPC IBM Power PC (RS6000?) / gcc (Linux)
30
FPU_GCC_SPARC Sun SPARC / gcc (Linux or SunOS)
31
FPU_GCC_M68K Motorola 680x0 / gcc (Linux or NextStep)
32
FPU_GCC_ARM ARM / gcc (Linux)
33
FPU_IGNORE dummy, for those few platforms with proper default
36
If none of these works for your machine, and you can figure out what
37
does, please contact me at munro@icf.llnl.gov. (I've never been able
38
to make Ultrix trap SIGFPE, for example.) You can use the fputest.c
39
program (and Make.fpu) to test your ideas.
44
On SGI/IRIX machines, you must be extremely careful *not* to set the
45
TRAP_FPE environment variable, which will override anything your code
46
does. The best policy there is to undefine TRAP_FPE before running
47
your code (do this by starting with a shell script).
49
If you are using gcc on a SunOS 4 machine, you may not have the
50
required routines for FPU_SUN4 (look in /usr/lib/libm.a; otherwise,
51
they are in /usr/lang/SC*/lib/libsunmath.a, which comes with Sun's
52
compilers). In that case, try FPU_GCC_SPARC.
54
Pentium (and other x86) machines do not always deliver SIGFPE
55
promptly, so the signal may be delivered on a (non-faulting)
56
subsequent floating point instruction. This is aggravating, but
57
apparently not much can be done about it.
60
SIGFPE on Linux (18/May/99)
63
The __setfpucw function used to be available for general use; here is
64
its generic implementation. Sometime in early 1999, GNU libc6
65
switched to making __setfpucw only available internally, forcing the
66
use of assembler macros in application code (see fpuset.c).
68
#include <fpu_control.h>
71
__setfpucw (fpu_control_t set)
75
/* Fetch the current control word. */
78
/* Preserve the reserved bits, and set the rest as the user
79
specified (or the default, if the user gave zero). */
81
cw |= set & ~_FPU_RESERVED;
86
Note that the macros are not always defined -- the alpha has its own
87
__setfpucw which translates i386 bits. In all other cases, when they
88
are defined, the bit macros are all different.
93
Alpha Linux implements the Digital UNIX (now Tru64)
94
ieee_set_fp_control() function, although it puts the fpu.h header in a
95
different place than Digital (now Compaq).
97
The alpha hardware cannot handle denormals, infinity, or other IEEE
98
constructs. In particular, denormals cause the hardware to trap. You
99
can let the Linux kernel (or Tru64 kernel) handle these exceptions and
100
fill in the IEEE-compliant value by compiling every module with the
101
-mieee option to GCC. This is obviously slow if you have lots of
102
underflows (as with many FFTs). Furthermore, -mieee inhibits some
103
types of optimizations which would interfere with the kernel math
104
emulator's ability to compute the IEEE-compliant result.
106
Unfortunately, the Linux libc and libm libraries produce denormals,
107
for example exp(-720), which are not numbers unless you have compiled
108
with -mieee. Hence, by default, the C expressions exp(-700)+0.0 and
109
exp(-800)+0.0 work fine, but exp(-720)+0.0 causes a SIGFPE. The
110
problem is that the alpha hardware does not support denormals, but
111
exp() returns them. The best workaround is to use the Compaq math
112
library if you can get it. The libc also contains routines like scanf
113
which will return denormals (hence the yorick read() function can
114
produce them). These are rare enough that you probably don't care
115
about trying to replace libc.
117
If you don't have access to a correct libm, you can put
119
in the top level Make.cfg file. This will cause a significant
120
performance penalty, but at least exp() won't randomly trigger SIGFPE.
121
If you do have a good libm, put it in the MATHLIB= line in Make.cfg.
126
Apparently handle_sigfpes (see manpage), as loaded from the libfpe
127
library, is the preferred way to get control after SIGFPE. The
128
fpsetmask function can masquerade as a FPU_SOLARIS, but that code
129
fails for some reason in full yorick, despite passing the fputest.c
130
suite. When floating point exceptions are masked, IRIX delivers
131
SIGTRAP (causing a core dump) on integer divide by zero (gag me with a
132
spoon). When floating point exceptions are being delivered, integer
133
divide by zero generates SIGFPE.
135
An additional headache is that libm does not generate SIGFPE on
136
overflow. An alternative library libmx is available, but requires a