Skip to content

Commit 2366342

Browse files
committed
add complex log1p (fix #3141)
1 parent 2bc0003 commit 2366342

File tree

4 files changed

+45
-4
lines changed

4 files changed

+45
-4
lines changed

NEWS.md

+2
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ Library improvements
144144

145145
* `rand` now supports arbitrary `Ranges` arguments ([#5059]).
146146

147+
* `expm1` and `log1p` now support complex arguments ([#3141]).
148+
147149
* `String` improvements
148150

149151
* Triple-quoted regex strings, `r"""..."""` ([#4934]).

base/complex.jl

+21-3
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ log2(z::Complex) = log(z)/oftype(real(z),0.6931471805599453)
329329
function exp(z::Complex)
330330
zr, zi = reim(z)
331331
if isnan(zr)
332-
Complex(zr, zi==zero(zi) ? zi : zr)
332+
Complex(zr, zi==0 ? zi : zr)
333333
elseif !isfinite(zi)
334334
if zr == inf(zr)
335335
Complex(-zr, nan(zr))
@@ -351,7 +351,7 @@ end
351351
function expm1(z::Complex)
352352
zr,zi = reim(z)
353353
if isnan(zr)
354-
Complex(zr, zi==zero(zi) ? zi : zr)
354+
Complex(zr, zi==0 ? zi : zr)
355355
elseif !isfinite(zi)
356356
if zr == inf(zr)
357357
Complex(-zr, nan(zr))
@@ -362,7 +362,7 @@ function expm1(z::Complex)
362362
end
363363
else
364364
erm1 = expm1(zr)
365-
if zi == zero(zi)
365+
if zi == 0
366366
Complex(erm1, zi)
367367
else
368368
er = erm1+one(erm1)
@@ -372,6 +372,24 @@ function expm1(z::Complex)
372372
end
373373
end
374374

375+
function log1p{T}(z::Complex{T})
376+
zr,zi = reim(z)
377+
if isfinite(zr)
378+
isinf(zi) && return log(z)
379+
# This is based on a well-known trick for log1p of real z,
380+
# allegedly due to Kahan, only modified to handle real(u) <= 0
381+
# differently to avoid inaccuracy near z==-2 and for correct branch cut
382+
u = float(one(T)) + z
383+
u == 1 ? convert(typeof(u), z) : real(u) <= 0 ? log(u) : log(u)*z/(u-1)
384+
elseif isnan(zr)
385+
Complex(zr, zr)
386+
elseif isfinite(zi)
387+
Complex(inf(T), copysign(zr > 0 ? zero(T) : convert(T, pi), zi))
388+
else
389+
Complex(inf(T), nan(T))
390+
end
391+
end
392+
375393
function ^{T<:FloatingPoint}(z::Complex{T}, p::Complex{T})
376394
if p==2 #square
377395
zr, zi = reim(z)

base/math.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export sin, cos, tan, sinh, cosh, tanh, asin, acos, atan,
2121
import Base: log, exp, sin, cos, tan, sinh, cosh, tanh, asin,
2222
acos, atan, asinh, acosh, atanh, sqrt, log2, log10,
2323
max, min, minmax, ceil, floor, trunc, round, ^, exp2,
24-
exp10, expm1
24+
exp10, expm1, log1p
2525

2626
import Core.Intrinsics: nan_dom_err, sqrt_llvm, box, unbox, powi_llvm
2727

test/complex.jl

+21
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,27 @@
151151
@test_approx_eq expm1(complex(-10.0, 10.0)) exp(complex(-10.0, 10.0))-1
152152
@test_approx_eq expm1(complex(-10.0,-10.0)) exp(complex(-10.0,-10.0))-1
153153

154+
# log1p:
155+
@test isequal(log1p(complex(Inf, 3)), complex(Inf, +0.))
156+
@test isequal(log1p(complex(Inf, -3)), complex(Inf, -0.))
157+
@test isequal(log1p(complex(-Inf, 3)), complex(Inf, +pi))
158+
@test isequal(log1p(complex(-Inf, -3)), complex(Inf, -pi))
159+
@test isequal(log1p(complex(Inf, NaN)), complex(Inf, NaN))
160+
@test isequal(log1p(complex(NaN, 0)), complex(NaN, NaN))
161+
@test isequal(log1p(complex(0, NaN)), complex(NaN, NaN))
162+
@test isequal(log1p(complex(-1, +0.)), complex(-Inf, +0.))
163+
@test isequal(log1p(complex(-1, -0.)), complex(-Inf, -0.))
164+
@test isequal(log1p(complex(-2, 1e-10)), log(1 + complex(-2, 1e-10)))
165+
@test isequal(log1p(complex(1, Inf)), complex(Inf, pi/2))
166+
@test isequal(log1p(complex(1, -Inf)), complex(Inf, -pi/2))
167+
import Base.Math.@horner
168+
for z in (1e-10+1e-9im, 1e-10-1e-9im, -1e-10+1e-9im, -1e-10-1e-9im)
169+
@test_approx_eq log1p(z) @horner(z, 0, 1, -0.5, 1/3, -0.25, 0.2)
170+
end
171+
for z in (15+4im, 0.2+3im, 0.08-0.9im)
172+
@test_approx_eq log1p(z) log(1+z)
173+
end
174+
154175

155176
# ^ (cpow)
156177
# equivalent to exp(y*log(x))

0 commit comments

Comments
 (0)