Skip to content

Commit cdf6a07

Browse files
committed
Avoid unnecessary complex power recomputation
1 parent c0eeaee commit cdf6a07

1 file changed

Lines changed: 20 additions & 18 deletions

File tree

Objects/complexobject.c

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -361,24 +361,26 @@ c_powi(Py_complex x, long n)
361361
return c_powu(x,n);
362362

363363
Py_complex r = _Py_c_quot(c_1, c_powu(x, -n));
364-
if (errno == EDOM
365-
|| (isfinite(r.real) && isfinite(r.imag)
366-
&& (r.real != 0.0 || r.imag != 0.0)))
367-
return r;
368-
369-
/* gh-156695: x**|n| left the exponent range although the result is
370-
representable. Redo it with x scaled to exponent zero; both the
371-
scaling and its undoing are exact. */
372-
double m = fabs(x.real) > fabs(x.imag) ? fabs(x.real) : fabs(x.imag);
373-
if (m == 0.0 || !isfinite(m))
374-
return r;
375-
376-
int e;
377-
frexp(m, &e);
378-
Py_complex w = {ldexp(x.real, -e), ldexp(x.imag, -e)};
379-
r = _Py_c_quot(c_1, c_powu(w, -n));
380-
r.real = ldexp(r.real, (int)(e * n));
381-
r.imag = ldexp(r.imag, (int)(e * n));
364+
365+
/* gh-156695: x**|n| needs roughly twice the exponent range of the
366+
result, so it can leave the range even when the result itself is
367+
representable, leaving the quotient degenerate. Only then redo the
368+
computation with x scaled to exponent zero; both the scaling and its
369+
undoing are exact. The common path above is untouched. */
370+
if (!(isfinite(r.real) && isfinite(r.imag)
371+
&& (r.real != 0.0 || r.imag != 0.0))
372+
&& errno != EDOM)
373+
{
374+
double m = fabs(x.real) > fabs(x.imag) ? fabs(x.real) : fabs(x.imag);
375+
if (m != 0.0 && isfinite(m)) {
376+
int e;
377+
frexp(m, &e);
378+
Py_complex w = {ldexp(x.real, -e), ldexp(x.imag, -e)};
379+
r = _Py_c_quot(c_1, c_powu(w, -n));
380+
r.real = ldexp(r.real, (int)(e * n));
381+
r.imag = ldexp(r.imag, (int)(e * n));
382+
}
383+
}
382384
return r;
383385
}
384386

0 commit comments

Comments
 (0)