Skip to content

Commit caa7f04

Browse files
stevengjJeffBezanson
authored andcommitted
specialized complex^real methods (#24497)
1 parent d7a171e commit caa7f04

File tree

3 files changed

+36
-20
lines changed

3 files changed

+36
-20
lines changed

base/complex.jl

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,24 @@ function log1p(z::Complex{T}) where T
631631
end
632632
end
633633

634-
function ^(z::Complex{T}, p::Complex{T})::Complex{T} where T<:AbstractFloat
634+
function exp2(z::Complex{T}) where T<:AbstractFloat
635+
er = exp2(real(z))
636+
theta = imag(z) * log(convert(T, 2))
637+
s, c = sincos(theta)
638+
Complex(er * c, er * s)
639+
end
640+
exp2(z::Complex) = exp2(float(z))
641+
642+
function exp10(z::Complex{T}) where T<:AbstractFloat
643+
er = exp10(real(z))
644+
theta = imag(z) * log(convert(T, 10))
645+
s, c = sincos(theta)
646+
Complex(er * c, er * s)
647+
end
648+
exp10(z::Complex) = exp10(float(z))
649+
650+
# _cpow helper function to avoid method ambiguity with ^(::Complex,::Real)
651+
function _cpow(z::Complex{T}, p::Union{T,Complex{T}})::Complex{T} where T<:AbstractFloat
635652
if p == 2 #square
636653
zr, zi = reim(z)
637654
x = (zr-zi)*(zr+zi)
@@ -665,24 +682,7 @@ function ^(z::Complex{T}, p::Complex{T})::Complex{T} where T<:AbstractFloat
665682
Complex(one(T), zer)
666683
end
667684
end
668-
669-
function exp2(z::Complex{T}) where T<:AbstractFloat
670-
er = exp2(real(z))
671-
theta = imag(z) * log(convert(T, 2))
672-
s, c = sincos(theta)
673-
Complex(er * c, er * s)
674-
end
675-
exp2(z::Complex) = exp2(float(z))
676-
677-
function exp10(z::Complex{T}) where T<:AbstractFloat
678-
er = exp10(real(z))
679-
theta = imag(z) * log(convert(T, 10))
680-
s, c = sincos(theta)
681-
Complex(er * c, er * s)
682-
end
683-
exp10(z::Complex) = exp10(float(z))
684-
685-
function ^(z::T, p::T) where T<:Complex
685+
function _cpow(z::Complex{T}, p::Union{T,Complex{T}}) where T<:Real
686686
if isinteger(p)
687687
rp = real(p)
688688
if rp < 0
@@ -738,6 +738,8 @@ function ^(z::T, p::T) where T<:Complex
738738

739739
Complex(re, im)
740740
end
741+
^(z::Complex{T}, p::Complex{T}) where T<:Real = _cpow(z, p)
742+
^(z::Complex{T}, p::T) where T<:Real = _cpow(z, p)
741743

742744
^(z::Complex, n::Bool) = n ? z : one(z)
743745
^(z::Complex, n::Integer) = z^Complex(n)
@@ -749,6 +751,11 @@ end
749751
n>=0 ? power_by_squaring(z,n) : power_by_squaring(inv(z),-n)
750752
^(z::Complex{<:Integer}, n::Integer) = power_by_squaring(z,n) # DomainError for n<0
751753

754+
function ^(z::Complex{T}, p::S) where {T<:Real,S<:Real}
755+
P = promote_type(T,S)
756+
return Complex{P}(z) ^ P(p)
757+
end
758+
752759
function sin(z::Complex{T}) where T
753760
F = float(T)
754761
zr, zi = reim(z)

base/rational.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ end
426426

427427
^(x::Number, y::Rational) = x^(y.num/y.den)
428428
^(x::T, y::Rational) where {T<:AbstractFloat} = x^convert(T,y)
429-
^(x::Complex{T}, y::Rational) where {T<:AbstractFloat} = x^convert(T,y)
429+
^(z::Complex{T}, p::Rational) where {T<:Real} = z^convert(typeof(one(T)^p), p)
430430

431431
^(z::Complex{<:Rational}, n::Bool) = n ? z : one(z) # to resolve ambiguity
432432
function ^(z::Complex{<:Rational}, n::Integer)

test/complex.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,3 +989,12 @@ end
989989
@test isequal(one(T) / complex(one(T), -zero(T)), Complex(one(T), zero(T)))
990990
end
991991
end
992+
993+
@testset "complex^real, issue #14342" begin
994+
for T in (Float32, Float64, BigFloat), p in (T(-21//10), -21//10)
995+
z = T(2)+0im
996+
@test real(z^p) 2^p
997+
@test signbit(imag(z^p))
998+
end
999+
@test (2+0im)^(-21//10) === (2//1+0im)^(-21//10) === 2^-2.1 - 0.0im
1000+
end

0 commit comments

Comments
 (0)