The built-in complex division is unreasonably slow

@btime x/y setup=(x=rand(ComplexF64);y=rand(ComplexF64));

gives

9.853 ns (0 allocations: 0 bytes)

while

function frac(x::ComplexF64, y::ComplexF64)
    y2=y.re^2+y.im^2
    return Complex((x.re*y.re+x.im*y.im)/y2, (x.im*y.re-x.re*y.im)/y2)
end

@btime frac(x,y) setup=(x=rand(ComplexF64);y=rand(ComplexF64));

gives only

3.694 ns (0 allocations: 0 bytes)

Why?

the short answer is getting good accuracy for these is hard. If you look at @btime @fastmath x/y you’ll see faster results results.

1 Like

To elaborate just a little: the extra runtime is spent ensuring proper behavior for Inf and for cases where intermediate quantities (such as your y2=y.re^2+y.im^2) would over/underflow. You can take a look at the current implementation in the source code.

3 Likes

It might be possible to add a better fast path (similar to faster `inv` for normal sized `ComplexF64` by oscardssmith · Pull Request #47255 · JuliaLang/julia · GitHub).

2 Likes