Mailing List Archive

FP exception, core dump in Python 1.5.2 (Tim's doing <grin>)
[Tim Peters suggests some code to generate INFs and NANs]

>def _make_inf():
> x = 2.0
> x2 = x * x
> i = 0
> while i < 100 and x != x2:
> x = x2
> x2 = x * x
> i = i + 1
> if x != x2:
> raise ValueError("This machine's floats go on forever!")
> return x

>PINF = _make_inf()
>MINF = -PINF
>NAN = PINF - PINF
>if 1.0 + NAN == 1.0:
> raise ValueError("This machine doesn't have NaNs, "
> "'overflows' to a finite number, "
> "or is 754-conformant but is using "
> "a goofy rounding mode.")
>PZERO = 0.0
>MZERO = -PZERO

[Mark tries it, and...]

On my platform, (DEC Alpha, Digital Unix 4.0D, Python 1.5.2) I get... a core
dump! (exclamation because it's one of the few Python core dumps I've seen).

[code modified to print i, x, x2]

python ieee.py
0 2.0 4.0
1 4.0 16.0
2 16.0 256.0
3 256.0 65536.0
4 65536.0 4294967296.0
5 4294967296.0 1.84467440737e+19
6 1.84467440737e+19 3.40282366921e+38
7 3.40282366921e+38 1.15792089237e+77
8 1.15792089237e+77 1.34078079299e+154
Floating exception (core dumped)

Python 1.5.2 (#1, Apr 17 1999, 05:27:57) [C] on osf1V4
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>>

dbx /usr/local/bin/python core
dbx version 3.11.10
Type 'help' for help.
Core file created by program "python"

thread 0x5 signal Floating point exception at >*[nxm_thread_kill, 0x3ff8058a608] ret r31, (r26), 1
(dbx) where
> 0 nxm_thread_kill(0x140081940, 0x0, 0x1400b13c0, 0x0, 0x3ff00000000) [0x3ff8058a608]
1 pthread_kill(0x0, 0x0, 0x11fffef20, 0x3ffc018a888, 0x3ff00000000) [0x3ff80577998]
2 (unknown)() [0x3ff8056c234]
3 (unknown)() [0x3ff807b22d8]
4 (unknown)() [0x3ff807b3824]
5 exc_unwind(0x3ff800d4544, 0x11fffdfe0, 0xabadabad00beed00, 0x1400b13c0, 0x3ff807b3af4) [0x3ff807b3864]
6 exc_raise_signal_exception(0x86, 0x0, 0x12005b218, 0x1, 0x8) [0x3ff807b3af0]
7 (unknown)() [0x3ff80578cc8]
8 PyFloat_FromDouble(0x0, 0x0, 0x12006f404, 0x14005c770, 0x1200533cc) [0x12005b214]
9 PyNumber_Multiply(0x1400b2988, 0x1400b13c0, 0x1400b13c0, 0x0, 0x3) [0x12006f400]
(dbx)




--
Email - mark@chem.uwa.edu.au ,-_|\ Mark C Favas
Phone - +61 9 380 3482 / \ Department of Chemistry
Fax - +61 9 380 1005 ---> *_,-._/ The University of Western Australia
v Nedlands
Loc - 31.97 S, 115.81 E Western Australia 6009
FP exception, core dump in Python 1.5.2 (Tim's doing <grin>) [ In reply to ]
[Tim, suggests some code to generate INFs and NANs]
> ...

[Mark Favas tries it, and...]
> On my platform, (DEC Alpha, Digital Unix 4.0D, Python 1.5.2) I
> get... a core dump! (exclamation because it's one of the few Python
> core dumps I've seen).

Excellent! Here's one of your problems:

> DEC Alpha

and here's the other <wink>:

> Digital Unix


> [code modified to print i, x, x2]
>
> python ieee.py
> 0 2.0 4.0
> 1 4.0 16.0
> 2 16.0 256.0
> 3 256.0 65536.0
> 4 65536.0 4294967296.0
> 5 4294967296.0 1.84467440737e+19
> 6 1.84467440737e+19 3.40282366921e+38
> 7 3.40282366921e+38 1.15792089237e+77
> 8 1.15792089237e+77 1.34078079299e+154
> Floating exception (core dumped)

Well, the next step is to square 1.3e154, and that will create an infinity
on an IEEE-754 conformant machine (the square is too big to fit in an IEEE
double). Your platform apparently triggers an unmasked IEEE (not Python)
Overflow exception instead, and your OS decides that's fatal. That means
your platform violates the 754 std in two ways, and, as advertised, ieee.py
raises an exception to gently inform you of that <wink>.

Presumably if you scrounge around long enough, you'll find the software
incantation you need to make your platform pretend to be 754 conformant.
There's not much use in trying to muck with 754 features so long as it's
not! Nothing Python can do about it on its own, either, short of simulating
754 arithmetic in software.

> ...
> 9 PyNumber_Multiply(0x1400b2988, 0x1400b13c0, 0x1400b13c0,
> 0x0, 0x3) [0x12006f400]
> (dbx)

Oh ya.

floating-point-is-its-own-reward-ly y'rs - tim
FP exception, core dump in Python 1.5.2 (Tim's doing <grin>) [ In reply to ]
In article <mark.925274556@declan>, Mark C Favas <mark@chem.uwa.edu.au>
wrote:

> [Tim Peters suggests some code to generate INFs and NANs]
> <snip>
> [Mark tries it, and...]
>
> On my platform, (DEC Alpha, Digital Unix 4.0D, Python 1.5.2) I get... a core
> dump! (exclamation because it's one of the few Python core dumps I've seen).
Unfortunately, the Alpha implementation of IEEE FP does not handle
overflow gracefully. With the default C compilation flags, the code
generated cannot recover from an overflow to stuff an Inf in the
result, so the only thing the OS can do is to kill the process.
Alternatively, with appropriate flags (can't remember them from the top
of my head, had to deal with this 6 months ago), the C compiler adds
machine instructions to allow recovery from FP exceptions, including
storing Inf as a result of overflow. Unfortunately, FP performance in
this mode is not nearly as good. None of the other machines I use (SGI,
Sun, Intel, Mac) have this problem. On the other hand, none of them
comes close to an Alpha in FP performance (with the dafault `fast'
compilation setting). Tradeoffs...

--
-- F
FP exception, core dump in Python 1.5.2 (Tim's doing <grin>) [ In reply to ]
[Fernando Pereira]
> Unfortunately, the Alpha implementation of IEEE FP does not handle
> overflow gracefully. With the default C compilation flags, the code
> generated cannot recover from an overflow to stuff an Inf in the
> result, so the only thing the OS can do is to kill the process.
> Alternatively, with appropriate flags (can't remember them from the top
> of my head, had to deal with this 6 months ago), the C compiler adds
> machine instructions to allow recovery from FP exceptions, including
> storing Inf as a result of overflow.

Mark (Favas) got around this by recompiling with -ieee. However, the Python
code I posted still didn't work for him. Code that does is attached, and
those with a passion for fp esoterica will be rolling on the floors with
childlike glee, delighting in the extreme convolutions this required <wink>.

> Unfortunately, FP performance in this mode is not nearly as good. None
> of the other machines I use (SGI, Sun, Intel, Mac) have this problem.

The Alpha is a silly chip <0.9 wink>. Denorms are a pain in the butt when
designing fast FP HW, but overflowing to an infinity is trivial (consider
that it's already got the logic to detect the overflow and signal an
exception as a result -- all they need to do instead is pass on a fixed,
simple bit pattern as the result).

> On the other hand, none of them comes close to an Alpha in FP
> performance (with the dafault `fast' compilation setting). Tradeoffs...

Luckily, Python's FP performance is poor on every platform <wink>.

the-alpha-is-a-cray-cpu-that-somehow-forgot-the-vectors-ly y'rs - tim

"""Module ieee: exports a few useful IEEE-754 constants and functions.

PINF positive infinity
MINF minus infinity
NAN a generic quiet NaN
PZERO positive zero
MZERO minus zero

isnan(x)
Return true iff x is a NaN.
"""

def _make_inf():
x = 2.0
x2 = x * x
i = 0
while i < 100 and x != x2:
x = x2
x2 = x * x
i = i + 1
if x != x2:
raise ValueError("This machine's floats go on forever!")
return x

# NaN-testing.
#
# The usual method (x != x) doesn't work.
# Python forces all comparisons thru a 3-outcome cmp protocol; unordered
# isn't a possible outcome. The float cmp outcome is essentially defined
# by this C expression (combining some cross-module implementation
# details, and where px and py are pointers to C double):
# px == py ? 0 : *px < *py ? -1 : *px > *py ? 1 : 0
# Comparing x to itself thus always yields 0 by the first clause, and so
# x != x is never true.
# If px and py point to distinct NaN objects, a strange thing happens:
# 1. On scrupulous 754 implementations, *px < *py returns false, and so
# does *px > *py. Python therefore returns 0, i.e. "equal"!
# 2. On Pentium HW, an unordered outcome sets an otherwise-impossible
# combination of condition codes, including both the "less than" and
# "equal to" flags. Microsoft C generates naive code that accepts
# the "less than" flag at face value, and so the *px < *py clause
# returns true, and Python returns -1, i.e. "not equal".
# So with a proper C 754 implementation Python returns the wrong result,
# and under MS's improper 754 implementation Python yields the right
# result -- both by accident. It's unclear who should be shot <wink>.
#
# Anyway, the point of all that was to convince you it's tricky getting
# the right answer in a portable way!

def isnan(x):
"""x -> true iff x is a NaN."""
# multiply by 1.0 to create a distinct object (x < x *always*
# false in Python, due to object identity forcing equality)
if x * 1.0 < x:
# it's a NaN and this is MS C on a Pentium
return 1
# Else it's non-NaN, or NaN on a non-MS+Pentium combo.
# If it's non-NaN, then x == 1.0 and x == 2.0 can't both be true,
# so we return false. If it is NaN, then assuming a good 754 C
# implementation Python maps both unordered outcomes to true.
return 1.0 == x == 2.0

PINF = _make_inf()
MINF = -PINF

NAN = PINF - PINF
if not isnan(NAN):
raise ValueError("This machine doesn't have NaNs, "
"'overflows' to a finite number, "
"suffers a novel way of implementing C comparisons, "
"or is 754-conformant but is using "
"a goofy rounding mode.")
PZERO = 0.0
MZERO = -PZERO