Skip to content

Invalid corner cases (resulting in nan+nanj) in complex division#119372

@skirpichev

Description

@skirpichev

Bug report

Bug description:

Reproducer:

>>> (1+1j)/(cmath.inf+0j) # ok 0j >>> (1+1j)/cmath.infj # ok -0j >>> (1+1j)/(cmath.inf+cmath.infj) # should be 0j, isn't? (nan+nanj)

c.f. MPC:

>>> gmpy2.mpc('(1+1j)')/gmpy2.mpc('(inf+infj)') mpc('0.0+0.0j')

It seems, there are not so much such cases (i.e. when the numerator is finite and the denominator has infinite and infinite/nan components, or if the numerator has infinite components and the denominator has zeros). Following patch (mostly literally taken from the C11 Annex G.5.1 _Cdivd()'s example, except for the denom == 0.0 case) should fix the issue:

diff --git a/Objects/complexobject.c b/Objects/complexobject.c index b3d57b8337..9041cbb8ae 100644 --- a/Objects/complexobject.c+++ b/Objects/complexobject.c@@ -122,6 +122,27 @@ _Py_c_quot(Py_complex a, Py_complex b) /* At least one of b.real or b.imag is a NaN */ r.real = r.imag = Py_NAN} ++ /* Recover infinities and zeros that computed as nan+nanj */+ if (isnan(r.real) && isnan(r.imag)){+ if ((isinf(a.real) || isinf(a.imag))+ && isfinite(b.real) && isfinite(b.imag))+{+ const double x = copysign(isinf(a.real) ? 1.0 : 0.0, a.real);+ const double y = copysign(isinf(a.imag) ? 1.0 : 0.0, a.imag);+ r.real = Py_INFINITY * (x*b.real + y*b.imag);+ r.imag = Py_INFINITY * (y*b.real - x*b.imag);+ }+ else if ((fmax(abs_breal, abs_bimag) == Py_INFINITY)+ && isfinite(a.real) && isfinite(a.imag))+{+ const double x = copysign(isinf(b.real) ? 1.0 : 0.0, b.real);+ const double y = copysign(isinf(b.imag) ? 1.0 : 0.0, b.imag);+ r.real = 0.0 * (a.real*x + a.imag*y);+ r.imag = 0.0 * (a.imag*x - a.real*y);+ }+ }+ return r} 

Perhaps, we could also clear ending remark in _Py_c_quot() comment:

* University). As usual, though, we're still ignoring all IEEE
* endcases.

I'll prepare a PR, if this issue will be accepted.

CPython versions tested on:

CPython main branch

Operating systems tested on:

No response

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions