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