Julia: incorrect (Inf + Inf*im)^2.0 and other complex^float

Created on 7 Nov 2017  Â·  5Comments  Â·  Source: JuliaLang/julia

In Julia 0.4–0.7, I get:

julia> (Inf + Inf*im)^2.0
0.0 + Inf*im

which seems wrong (it assumes that the two Inf components are the "same"). The correct answer is given for ^2:

julia> (Inf + Inf*im)^2
NaN + Inf*im

The error seems to be due to this line, which dates back to #2891 by @jiahao.

My first inclination is to remove the entire p==2 special case from this ^ method. As I commented in #24497, that seems to be a performance optimization that is probably largely superseded, since most cases that need a fast z^2 probably use (a) an integer exponent (that calls a different method) and/or (b) a literal integer exponent (for which z^2 is inlined as z*z for Complex64 and Complex128).

complex maths

Most helpful comment

I'm working at a patch that fixes this, and also makes the code 60% faster for complex^complex and 120% faster for real^complex.

All 5 comments

On the other hand, we have:

julia> m = realmax(Float64)
1.7976931348623157e308

julia> (m + m*im)^2      # incorrect
NaN + Inf*im

julia> (m + m*im)^2.0    # correct
0.0 + Inf*im

I don't think that it is worth the extra checks to deal with this overflow case correctly, however. You'd have to slow down all complex multiplications to make (m + m*im) * (m + m*im) give 0.0 + Inf*im.

Wow, I found some even worse bugs:

julia> (0+0im)^-3.0
0.0 + 0.0im

(!!!) and

julia> (1.0+0.0im)^1e300
ERROR: InexactError: convert(Int64, 1.0e300)
Stacktrace:
 [1] convert at ./float.jl:703 [inlined]
 [2] convert at ./int.jl:530 [inlined]
 [3] convert at ./int.jl:534 [inlined]
 [4] ^(::Complex{Float64}, ::Complex{Float64}) at ./complex.jl:657
 [5] ^(::Complex{Float64}, ::Float64) at ./promotion.jl:310

I'm working at a patch that fixes this, and also makes the code 60% faster for complex^complex and 120% faster for real^complex.

Another bad case?

julia> Inf^(-Inf + 0.0im)
-0.0 - 0.0im

Actually, maybe that's correct: Inf^(-Inf + 0.0im) = exp((-Inf + 0.0im) * log(Inf)) = exp((-Inf + 0.0im) * Inf) = exp(-Inf + NaN*im), and it makes sense that the latter would be zero (though the sign of zero is unclear).

Python seems to get this one wrong:

In [1]: inf = float('inf')
In [2]: inf ** (-inf + 0j)
Out[2]: (nan+nanj)

Closed by #24570.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wilburtownsend picture wilburtownsend  Â·  3Comments

helgee picture helgee  Â·  3Comments

yurivish picture yurivish  Â·  3Comments

dpsanders picture dpsanders  Â·  3Comments

felixrehren picture felixrehren  Â·  3Comments