I have to say that signed zeroes and signed infinities don't work well
in 754 for complex numbers. I know Kahan _wanted_ signed zeroes to
help sort out branch cuts for complex functions, but he appears to be
alone in the world in finding them useful for that ;-)

Complex multiplication for values with signed zero components isn't
even associative. At least not under any implementation I've tried. I
pointed that out on David Hough's "numeric-interest" mailing list
while 754 was still being hammered out, but it was "already too late"
to do anything about it.

Here's a short driver:

    from itertools import product
    pz = 0.0
    cs = [complex(*t) for t in product((pz, -pz), repeat=2)]
    for x, y, z in product(cs, repeat=3):
        t1 = (x*y)*z
        t2 = x*(y*z)
        if repr(t1) != repr(t2):
            print(x, y, z, t1, t2)

On my Windows 3.10.1, associativity fails in 24 (of the 64) cases:

0j 0j (-0-0j) -0j 0j
0j -0j (-0+0j) (-0+0j) 0j
0j -0j (-0-0j) -0j (-0+0j)
0j (-0+0j) (-0+0j) -0j 0j
0j (-0-0j) -0j -0j (-0+0j)
0j (-0-0j) (-0-0j) (-0+0j) 0j
-0j 0j (-0+0j) (-0+0j) 0j
-0j -0j (-0-0j) (-0+0j) 0j
-0j (-0+0j) (-0+0j) (-0+0j) -0j
-0j (-0+0j) (-0-0j) -0j 0j
-0j (-0-0j) 0j (-0+0j) -0j
-0j (-0-0j) (-0+0j) -0j 0j
(-0+0j) 0j -0j 0j (-0+0j)
(-0+0j) -0j 0j 0j (-0+0j)
(-0+0j) (-0+0j) 0j 0j -0j
(-0+0j) (-0+0j) -0j -0j (-0+0j)
(-0+0j) (-0-0j) -0j 0j -0j
(-0+0j) (-0-0j) (-0-0j) -0j (-0+0j)
(-0-0j) 0j 0j 0j -0j
(-0-0j) -0j 0j (-0+0j) -0j
(-0-0j) -0j -0j 0j (-0+0j)
(-0-0j) (-0+0j) -0j 0j -0j
(-0-0j) (-0-0j) 0j 0j (-0+0j)
(-0-0j) (-0-0j) (-0+0j) (-0+0j) -0j

That isn't just academic. My employer's FORTRAN compiler failed to
pass the US govt's validation suite at the time, because of a bizarre
test failure: the accidental signs of these zeroes can have very
visible consequences (e.g., as arguments to atan2(), which the
validation suite called on the real and imag components after raising
a complex zero to an integer power - and _which_ of the four complex
zeroes you got depended on the grouping of the multiplies).

Don't try to sell me the idea that any of that is logical ;-) BTW,
exactly which cases in the above fail can also depend on the rounding
mode (because x + -x is +0 for any finite x, _except_ under
to-minus-infinity rounding, where the result changes to -0).

Signed infinities are even sillier here. You want a single projective
infinity in the complex plane, not a pair of signed infinities on each
axis. And early drafts of 754 had a control bit to determine which
flavor of infinity you got. But it's one of the few bits of esoterica
that got dropped near the end. Partly because signed zeroes seemingly
demand signed infinities too, like lutefisk demands haggis ;-)

There was much to applaud in 754, but to my eyes signed zeroes, and
NaN != NaN, caused far more trouble than they helped - and the
exception model is such a pain it's almost never been implemented as
intended (Python's `decimal` module being an exception, and Apple's
long-dead SANE environment).

BTW, complex was added as a full-blown built-in type in 1.4b1, long
before Python had a major user base (mid-1990s). I think Guido added
it because he was trained as a mathematician, so felt obligated ;-)
Seriously, various Python versions of it (and rationals) were long in
use as test cases for hammering out rules and APIs for coercion (and
other native language features).
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/3IY3NTJRAMSQZYTCVQABTYPM2TGS3UVN/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to