Some Q&A with Kahan on IEEE 754

Tim Peters tim_one at
Tue Oct 17 01:18:48 CEST 2000

[Kevin Jacobs, working hard to make some progress]

Briefly, as the 2.0 release is today and I'm swamped:

> I'm glad to see that Dr. Kahan's opinions are in line with what
> _everyone_ here wants.

They won't be if we flesh them out more, but so it goes.

> I am drafting a PEP and reference implementation
> that embodies these ideas and goals:

> ...
>   5) Thread specific handling of traps with creation-time inheritance of
>      settings.

Yes, all 754 state (rounding, precision, sticky flags, trap masks) must be
part of thread state.  Someone else questioned that before, but it's a
no-brainer.  Inheriting precision, rounding and trap masks from the parent
thread works best in practice.  Less clear is whether sticky flags should be
inherited too or cleared in a new thread; I favor the latter (a new thread
hasn't caused any exceptions yet, so the principle of least surprise
dictates that its sticky flags reflect that).

> ...
> Of the many issues to be resolved, here are a few things to consider:
>   1) Handling of signaling NaNs.  This can get expensive since it
>      involves a test every time a floatobject is used or requires
>      mucking about with signal handlers.

Signaling NaNs are a minor feature; I'm not sure I've *ever* seen them used
(on purpose <wink>).

>   2) Speaking of signal handlers, Tim Peters stated that returns are not
>      allowed from sIGFPE handlers.  I have yet to see this restriction in
>      any platform documentation.  What is the deal?

C standard.  Here's the exact text from C99, section ("The 'signal'

    ... [in context, "the function" means the signal handler] ...
    If and when the function returns, if the value of sig is SIGFPE,
    SIGILL, SIGSEGV, or any other implementation-defined value
    corresponding to a computational exception, the behavior is undefined;
    otherwise the program will resume execution at the point it was

Note that it doesn't say returning from a SIGFPE handler is not allowed, it
says what happens if you *do* return is simply undefined.  There is nothing
portable you can rely on here, and that's what the std is warning about.
For example, if you try to return from a SIGFPE handler on a WinTel box, you
*usually* get into an infinite loop, as the offending instruction is
restarted and just raises the same exception again (which goes back to the
SIGFPE handler, which returns, which goes back to etc etc).  This is (in
part) why the current fpectl module longjmps out of its SIGFPE handler.

Overall, current fpectl would probably be cheaper if the "open" macro saved
the current sticky flags and the "after" macro xor'ed them with the current
values, to see whether a 754 condition had been signaled.  But I don't
believe the fpectl module author had only 754-like machines in mind, so
funneled everything into SIGFPE instead.

>   3) Thread support -- Python threading will have to know about
>      per-thread floating point data-structures.

There's already a thread-state structure in Python for holding per-thread
implementation details; this part should be easy.

>  There are also implications for uthreads.

uthreads aren't in the std distribution; since their primary purpose is to
allow screamingly fast context switches with minimal memory burden, I expect
that Will Ware and Christian Tismer will want all uthreads to share the 754
state of the "real thread" they're running in.

Note that I/O is a problem:  different platforms spell Inf and NaN in
different ways, and Python currently defers to the platform atod and strtod
to do string->float input.  Similarly for output.  I expect everyone will
eventually move to the C99 spellings for these things, but before then
Python may need to write its own (and just porting David Gay's routines for
754 I/O to all the platforms Python uses could consume a good chunk of a
release cycle ...).

Note that comparisons are a problem.  754 implicitly defines 32 distinct
binary comparison predicates (16 for which subset of {lt, eq, gt, unordered}
is of interest, times 2 for whether or not a quiet NaN signals invalid
operation).  But there's no way Python will grow new language syntax for
these.  So this needs to be funneled thru a vanilla function interface.
Also doubtful that

    x == x

will be changed to special-case NaNs; this currently returns 1 no matter
what x is bound to because the same ("x is x") objects are being compared,
and object identity is fundamental in Python.

>   4) I am going to need help implementing support for many of the commonly
>      used Python platforms.  I have access to Windows 95/98/NT/2000,
>      Compaq/Digital Unix, AIX (Power3), IRIX, Linux (i386+glibc2.1+), and
>      Solaris.  Edward Jason Riedy has offered to help with AIX, Linux,
>      Solaris and Unicos/mk.  We still need volunteers for the following:
> 	Windows
> 	OS/2
> 	BeOS
> 	VxWorks
> 	OpenVMS
> 	QNX
> 	Others?  Speak now!

I'll take Windows.  Note a peculiar feature of the Pentium architecture:  it
doesn't raise a 754 exception until executing the fp instruction *following*
(in time) the instruction that actually caused the problem.  So an unbounded
number of cycles and (non-fp) instructions can pass between the time, e.g.,
a divide by 0 happens, and the time a divby0 trap occurs.  That's why the
"close macro" in fpectl calls a silly function that just returns 1.0, and
the caller immediately casts that to an int:  it's forcing another FP
instruction to get executed so that the Pentium will finally act on
*earlier* problems.  Like I said before, this stuff is a x-platform delight

> ...
> I think the problem here is in the definition of "Enable IEEE".  Your
> meaning seems to be "Enable IEEE" == "Enable all/some IEEE 754 traps". My
> meaning, and I believe the standard one is "use features available in
> conforming IEEE 754 implementations." This is, by necessity, a superset of
> the generic C floating point support (with a few notable, but minor
> exceptions).

Actually, all Huaiyu has been talking about is whether libm functions return
Infs and NaNs.  Strictly speaking, that's not a 754 issue at all, as sqrt is
the only libm function 754 mentions.  I know what he means, though, so
haven't picked on that point <wink>.  He just never wants to see an
exception raised by any fp operation.  That's a legit thing to want, but
also a minority thing to want.  But getting libm to work predictably across
platforms is a whole other can of worms, above and beyond 754 support.

there's-several-person-years-of-work-here-ly y'rs  - tim

More information about the Python-list mailing list