Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

448 lines (380 sloc) 12.998 kb
## generic complex number definitions ##
abstract Complex{T<:Real} <: Number
iscomplex(x::Complex) = true
iscomplex(x::Number) = false
real_valued{T<:Real}(z::Complex{T}) = imag(z) == 0
integer_valued(z::Complex) = real_valued(z) && integer_valued(real(z))
real(x::Real) = x
imag(x::Real) = zero(x)
isfinite(z::Complex) = isfinite(real(z)) && isfinite(imag(z))
reim(z) = (real(z), imag(z))
function _jl_show(io, z::Complex, compact::Bool)
r, i = reim(z)
if isnan(r) || isfinite(i)
compact ? showcompact(io,r) : show(io,r)
if signbit(i)==1 && !isnan(i)
i = -i
print(io, compact ? "-" : " - ")
else
print(io, compact ? "+" : " + ")
end
compact ? showcompact(io, i) : show(io, i)
if !(isa(i,Integer) || isa(i,Rational) ||
isa(i,FloatingPoint) && isfinite(i))
print(io, "*")
end
print(io, "im")
else
print(io, "complex(",r,",",i,")")
end
end
show(io, z::Complex) = _jl_show(io, z, false)
showcompact(io, z::Complex) = _jl_show(io, z, true)
## packed complex float types ##
bitstype 128 Complex128 <: Complex{Float64}
function complex128(r::Float64, i::Float64)
box(Complex128,
or_int(shl_int(zext_int(Complex128,unbox(Float64,i)), 64),
zext_int(Complex128,unbox(Float64,r))))
end
complex128(r::Real, i::Real) = complex128(float64(r),float64(i))
complex128(z) = complex128(real(z), imag(z))
real(c::Complex128) = box(Float64,trunc64(c))
imag(c::Complex128) = box(Float64,trunc64(ashr_int(c, 64)))
convert(::Type{Complex128}, x::Real) = complex128(x,0)
convert(::Type{Complex128}, z::Complex128) = z
convert(::Type{Complex128}, z::Complex) = complex128(real(z),imag(z))
promote_rule(::Type{Complex128}, ::Type{Float64}) = Complex128
promote_rule(::Type{Complex128}, ::Type{Float32}) = Complex128
promote_rule{S<:Integer}(::Type{Complex128}, ::Type{S}) = Complex128
promote_rule{S<:Real}(::Type{Complex128}, ::Type{S}) =
(P = promote_type(Float64,S);
is(P,Float64) ? Complex128 : ComplexPair{P})
function read(s, ::Type{Complex128})
r = read(s,Float64)
i = read(s,Float64)
complex128(r,i)
end
function write(s, z::Complex128)
write(s,real(z))
write(s,imag(z))
end
sizeof(::Type{Complex128}) = 16
bitstype 64 Complex64 <: Complex{Float32}
function complex64(r::Float32, i::Float32)
box(Complex64,
or_int(shl_int(zext_int(Complex64,unbox(Float32,i)), 32),
zext_int(Complex64,unbox(Float32,r))))
end
complex64(r::Real, i::Real) = complex64(float32(r),float32(i))
complex64(z) = complex64(real(z), imag(z))
real(c::Complex64) = box(Float32,trunc32(c))
imag(c::Complex64) = box(Float32,trunc32(ashr_int(c, 32)))
convert(::Type{Complex64}, x::Real) = complex64(x,0)
convert(::Type{Complex64}, z::Complex64) = z
convert(::Type{Complex64}, z::Complex) = complex64(real(z),imag(z))
promote_rule(::Type{Complex64}, ::Type{Float64}) = Complex128
promote_rule(::Type{Complex64}, ::Type{Float32}) = Complex64
promote_rule{S<:Integer}(::Type{Complex64}, ::Type{S}) = Complex64
promote_rule{S<:Real}(::Type{Complex64}, ::Type{S}) =
(P = promote_type(Float32,S);
is(P,Float64) ? Complex128 :
is(P,Float32) ? Complex64 : ComplexPair{P})
promote_rule(::Type{Complex128}, ::Type{Complex64}) = Complex128
function read(s, ::Type{Complex64})
r = read(s,Float32)
i = read(s,Float32)
complex64(r,i)
end
function write(s, z::Complex64)
write(s,real(z))
write(s,imag(z))
end
sizeof(::Type{Complex64}) = 8
complex(x::Float64, y::Float64) = complex128(x, y)
complex(x::Float32, y::Float32) = complex64(x, y)
complex(x::FloatingPoint, y::FloatingPoint) = complex(promote(x,y)...)
complex(x::FloatingPoint, y::Real) = complex(promote(x,y)...)
complex(x::Real, y::FloatingPoint) = complex(promote(x,y)...)
complex(x::FloatingPoint) = complex(x, zero(x))
## complex with arbitrary component type ##
type ComplexPair{T<:Real} <: Complex{T}
re::T
im::T
end
ComplexPair(x::Real, y::Real) = ComplexPair(promote(x,y)...)
ComplexPair(x::Real) = ComplexPair(x, zero(x))
real(z::ComplexPair) = z.re
imag(z::ComplexPair) = z.im
convert{T<:Real}(::Type{ComplexPair{T}}, x::Real) =
ComplexPair(convert(T,x), convert(T,0))
convert{T<:Real}(::Type{ComplexPair{T}}, z::ComplexPair{T}) = z
convert{T<:Real}(::Type{ComplexPair{T}}, z::Complex) =
ComplexPair(convert(T,real(z)),convert(T,imag(z)))
promote_rule{T<:Real}(::Type{ComplexPair{T}}, ::Type{T}) =
ComplexPair{T}
promote_rule{T<:Real,S<:Real}(::Type{ComplexPair{T}}, ::Type{S}) =
ComplexPair{promote_type(T,S)}
promote_rule{T<:Real,S<:Real}(::Type{ComplexPair{T}}, ::Type{ComplexPair{S}}) =
ComplexPair{promote_type(T,S)}
promote_rule{T<:Real}(::Type{ComplexPair{T}}, ::Type{Complex128}) =
(P = promote_type(Float64,T);
is(P,Float64) ? Complex128 : ComplexPair{P})
promote_rule{T<:Real}(::Type{ComplexPair{T}}, ::Type{Complex64}) =
(P = promote_type(Float32,T);
is(P,Float64) ? Complex128 : is(P,Float32) ? Complex64 : ComplexPair{P})
complex(x, y) = ComplexPair(x, y)
complex(x) = ComplexPair(x)
## singleton type for imaginary unit constant ##
type ImaginaryUnit <: Complex{Int32}; end
const im = ImaginaryUnit()
convert{T<:Real}(::Type{ComplexPair{T}}, ::ImaginaryUnit) =
ComplexPair(zero(T),one(T))
convert(::Type{Complex128}, ::ImaginaryUnit) = complex128(0,1)
convert(::Type{Complex64}, ::ImaginaryUnit) = complex64(0,1)
real(::ImaginaryUnit) = int32(0)
imag(::ImaginaryUnit) = int32(1)
promote_rule{T<:Complex}(::Type{ImaginaryUnit}, ::Type{T}) = T
promote_rule{T<:Real}(::Type{ImaginaryUnit}, ::Type{T}) = ComplexPair{T}
promote_rule(::Type{ImaginaryUnit}, ::Type{Float64}) = Complex128
promote_rule(::Type{ImaginaryUnit}, ::Type{Float32}) = Complex64
## generic functions of complex numbers ##
convert(::Type{Complex}, z::Complex) = z
convert(::Type{Complex}, x::Real) = complex(x)
==(z::Complex, w::Complex) = real(z) == real(w) && imag(z) == imag(w)
==(z::Complex, x::Real) = real_valued(z) && real(z) == x
==(x::Real, z::Complex) = real_valued(z) && real(z) == x
isequal(z::Complex, w::Complex) = isequal(real(z),real(w)) && isequal(imag(z),imag(w))
isequal(z::Complex, x::Real) = real_valued(z) && isequal(real(z),x)
isequal(x::Real, z::Complex) = real_valued(z) && isequal(real(z),x)
hash(z::Complex) = (r = hash(real(z)); real_valued(z) ? r : bitmix(r,hash(imag(z))))
eps(z::Complex) = eps(abs(z))
conj(z::Complex) = complex(real(z),-imag(z))
abs(z::Complex) = hypot(real(z), imag(z))
abs2(z::Complex) = real(z)*real(z) + imag(z)*imag(z)
inv(z::Complex) = conj(z)/abs2(z)
sign(z::Complex) = z/abs(z)
-(z::Complex) = complex(-real(z), -imag(z))
+(z::Complex, w::Complex) = complex(real(z) + real(w), imag(z) + imag(w))
-(z::Complex, w::Complex) = complex(real(z) - real(w), imag(z) - imag(w))
*(z::Complex, w::Complex) = complex(real(z) * real(w) - imag(z) * imag(w),
real(z) * imag(w) + imag(z) * real(w))
*(x::Real, z::Complex) = complex(x * real(z), x * imag(z))
*(z::Complex, x::Real) = complex(x * real(z), x * imag(z))
# multiplying by im is common
*(z::ImaginaryUnit, w::ImaginaryUnit) = complex(-imag(z), real(z))
*(z::ImaginaryUnit, x::Real) = complex(zero(x), x)
*(x::Real, z::ImaginaryUnit) = complex(zero(x), x)
*(z::ImaginaryUnit, w::Complex) = complex(-imag(w), real(w))
*(w::Complex, z::ImaginaryUnit) = complex(-imag(w), real(w))
/(z::Number, w::Complex) = z*inv(w)
/(z::Complex, x::Real) = complex(real(z)/x, imag(z)/x)
function /(a::Complex, b::Complex)
are = real(a); aim = imag(a); bre = real(b); bim = imag(b)
abr = abs(bre)
abi = abs(bim)
if abr <= abi
r = bre / bim
den = bim * (one(r) + r*r)
complex((are*r + aim)/den, (aim*r - are)/den)
else
r = bim / bre
den = bre * (one(r) + r*r)
complex((are + aim*r)/den, (aim - are*r)/den)
end
end
function /(a::Real, b::Complex)
bre = real(b); bim = imag(b)
abr = abs(bre)
abi = abs(bim)
if abr <= abi
r = bre / bim
den = bim * (one(r) + r*r)
complex(a*r/den, -a/den)
else
r = bim / bre
den = bre * (one(r) + r*r)
complex(a/den, -a*r/den)
end
end
function sqrt(z::Complex)
rz = float(real(z))
iz = float(imag(z))
T = promote_type(typeof(rz),typeof(z))
r = sqrt(0.5*(hypot(rz,iz)+abs(rz)))
if r == 0
return convert(T,complex(0.0, iz))
end
if rz >= 0
return convert(T,complex(r, 0.5*iz/r))
end
return convert(T,complex(0.5*abs(iz)/r, iz >= 0 ? r : -r))
end
cis(theta::Real) = complex(cos(theta),sin(theta))
function cis(z::Complex)
v = 1/exp(imag(z))
complex(v*cos(real(z)), v*sin(real(z)))
end
angle(z::Complex) = atan2(imag(z), real(z))
function sin(z::Complex)
u = exp(imag(z))
v = 1/u
rz = real(z)
u = 0.5(u+v)
v = u-v
complex(u*sin(rz), v*cos(rz))
end
function cos(z::Complex)
u = exp(imag(z))
v = 1/u
rz = real(z)
u = 0.5(u+v)
v = u-v
complex(u*cos(rz), -v*sin(rz))
end
function log(z::Complex)
ar = abs(real(z))
ai = abs(imag(z))
if ar < ai
r = ar/ai
re = log(ai) + 0.5*log1p(r*r)
else
if ar == 0
re = -inv(ar)
else
r = ai/ar
re = log(ar) + 0.5*log1p(r*r)
end
end
complex(re, atan2(imag(z), real(z)))
end
log10(z::Complex) = log(z)/2.302585092994046
log2(z::Complex) = log(z)/0.6931471805599453
function exp(z::Complex)
er = exp(real(z))
complex(er*cos(imag(z)), er*sin(imag(z)))
end
function ^{T<:Complex}(z::T, p::T)
realp = real(p)
if imag(p) == 0
if realp == 0
return one(z)
elseif realp == 1
return z
elseif realp == 2
return z*z
elseif realp == 0.5
return sqrt(z)
end
end
r = abs(z)
rp = r^realp
realz = real(z)
zer = zero(r)
if imag(p) == 0
ip = itrunc(realp)
if ip == realp
# integer multiples of pi/2
if imag(z) == 0 && realz < 0
return complex(isodd(ip) ? -rp : rp, zer)
elseif realz == 0 && imag(z) < 0
if isodd(ip)
return complex(zer, isodd(div(ip-1,2)) ? rp : -rp)
else
return complex(isodd(div(ip,2)) ? -rp : rp, zer)
end
elseif realz == 0 && imag(z) > 0
if isodd(ip)
return complex(zer, isodd(div(ip-1,2)) ? -rp : rp)
else
return complex(isodd(div(ip,2)) ? -rp : rp, zer)
end
end
else
dr = realp*2
ip = itrunc(dr)
# 1/2 multiples of pi
if ip == dr && imag(z) == 0
if realz < 0
return complex(zer, isodd(div(ip-1,2)) ? -rp : rp)
elseif realz >= 0
return complex(rp, zer)
end
end
end
end
imagz = imag(z)
if imagz==0 && realz>=0
ntheta = imag(p)*log(r)
else
theta = atan2(imagz, realz)
ntheta = realp*theta
if imag(p) != 0
rp = rp*exp(-imag(p)*theta)
ntheta = ntheta + imag(p)*log(r)
end
end
complex(rp*cos(ntheta), rp*sin(ntheta))
end
function tan(z::Complex)
u = exp(imag(z))
v = 1/u
u = 0.5(u+v)
v = u-v
sinre = sin(real(z))
cosre = cos(real(z))
d = cosre*cosre + v*v
complex(sinre*cosre/d, u*v/d)
end
function asin(z::Complex)
re = 1 - (real(z)*real(z) - imag(z)*imag(z))
im = -2real(z)*imag(z)
x = sqrt(complex(re,im))
re = real(x) - imag(z)
im = imag(x) + real(z)
complex(atan2(im, re), -log(hypot(re, im)))
end
function acos(z::Complex)
re = 1 - (real(z)*real(z) - imag(z)*imag(z))
im = -2real(z)*imag(z)
x = sqrt(complex(re,im))
re = real(z) - imag(x)
im = imag(z) + real(x)
complex(atan2(im, re), -log(hypot(re, im)))
end
function atan(z::Complex)
xsq = real(z)*real(z)
ysq = imag(z)*imag(z)
m1y = 1-imag(z)
yp1 = 1+imag(z)
m1ysq = m1y*m1y
yp1sq = yp1*yp1
complex(0.5(atan2(real(z),m1y) - atan2(-real(z),yp1)),
0.25*log((yp1sq + xsq)/(xsq + m1ysq)))
end
function sinh(z::Complex)
u = exp(real(z))
v = 1/u
u = 0.5(u+v)
v = u-v
complex(v*cos(imag(z)), u*sin(imag(z)))
end
function cosh(z::Complex)
u = exp(real(z))
v = 1/u
u = 0.5(u+v)
v = u-v
complex(u*cos(imag(z)), v*sin(imag(z)))
end
function tanh(z::Complex)
cosim = cos(imag(z))
u = exp(real(z))
v = 1/u
u = 0.5(u+v)
v = u-v
d = cosim*cosim + v*v
complex(u*v/d, sin(imag(z))*cosim/d)
end
asinh(z::Complex) = log(z + sqrt(z*z + 1))
acosh(z::Complex) = log(z + sqrt(z*z - 1))
atanh(z::Complex) = log(sqrt((1+z)/(1-z)))
Jump to Line
Something went wrong with that request. Please try again.