Skip to content

Commit a9d3ef0

Browse files
wormelldpsanders
authored andcommitted
Added complex sqrt and some complex set functions (#195)
* Added complex sqrt and some complex set functions Added complex sqrt and some complex set functions Added complex sqrt and some complex set functions Fixed test Fixed complex sqrt test Added more tests Fixed complex in added tests back in * Updated LICENSE.md to include sqrt code attribution
1 parent cab2433 commit a9d3ef0

File tree

5 files changed

+141
-2
lines changed

5 files changed

+141
-2
lines changed

LICENSE.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,30 @@ distributed under the License is distributed on an "AS IS" BASIS,
224224
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
225225
See the License for the specific language governing permissions and
226226
limitations under the License.
227+
228+
The code for ssqs and sqrt{::Complex{<:Interval}} is modified from Base
229+
module in Julia 0.6.4, licensed also under the MIT license:
230+
231+
> Copyright (c) 2009-2016: Jeff Bezanson, Stefan Karpinski, Viral B. Shah,
232+
> and other contributors:
233+
>
234+
> https://github.com/JuliaLang/julia/contributors
235+
>
236+
> Permission is hereby granted, free of charge, to any person obtaining
237+
> a copy of this software and associated documentation files (the
238+
> "Software"), to deal in the Software without restriction, including
239+
> without limitation the rights to use, copy, modify, merge, publish,
240+
> distribute, sublicense, and/or sell copies of the Software, and to
241+
> permit persons to whom the Software is furnished to do so, subject to
242+
> the following conditions:
243+
>
244+
> The above copyright notice and this permission notice shall be
245+
> included in all copies or substantial portions of the Software.
246+
>
247+
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
248+
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
249+
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
250+
> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
251+
> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
252+
> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
253+
> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

src/intervals/complex.jl

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
function ssqs(x::T, y::T,RND::RoundingMode) where T<:AbstractFloat
2+
k::Int = 0
3+
ρ = +(*(x,x,RND),*(y,y,RND),RND)
4+
if !isfinite(ρ) && (isinf(x) || isinf(y))
5+
ρ = convert(T, Inf)
6+
elseif isinf(ρ) ||==0 && (x!=0 || y!=0)) || ρ<nextfloat(zero(T))/(2*eps(T)^2)
7+
m::T = max(abs(x), abs(y))
8+
k = m==0 ? m : exponent(m)
9+
xk, yk = ldexp(x,-k), ldexp(y,-k)
10+
ρ = +(*(xk,xk,RND),*(yk,yk,RND),RND)
11+
end
12+
ρ, k
13+
end
14+
15+
# function ssqs(x::Interval{T}, y::Interval{T}) where T<:AbstractFloat
16+
# x = abs(x); y = abs(y)
17+
# ρl,kl = ssqs(inf(x),inf(y),RoundDown)
18+
# ρu,ku = ssqs(sup(x),sup(y),RoundUp)
19+
# ρl, kl, ρu, ku
20+
# end
21+
22+
function sqrt_realpart(x::T, y::T,RND::RoundingMode) where T<:AbstractFloat
23+
# @assert x ≥ 0
24+
ρ, k = ssqs(x,y,RND)
25+
if isfinite(x) ρ = +(ldexp(x,-k),sqrt(ρ,RND),RND) end
26+
27+
if isodd(k)
28+
k = div(k-1,2)
29+
else
30+
k = div(k,2)-1
31+
ρ *= 2
32+
end
33+
ρ = ldexp(sqrt(ρ,RND),k) #sqrt((abs(z)+abs(x))/2) without over/underflow
34+
end
35+
36+
function sqrt(z::Complex{Interval{T}}) where T<:AbstractFloat
37+
x, y = reim(z)
38+
39+
(inf(x) < 0 && inf(y) < 0 && sup(y) >= 0) && error("Interval lies across branch cut")
40+
x == y == 0 && return Complex(zero(x),y)
41+
42+
(inf(x) < 0 && sup(x) > 0) && return sqrt((inf(x)..0) + im*y) sqrt((0..sup(x)) + im*y)
43+
44+
absx = abs(x)
45+
46+
absy= abs(y)
47+
ρl = sqrt_realpart(inf(absx),inf(absy),RoundDown)
48+
ρu = sqrt_realpart(sup(absx),sup(absy),RoundUp)
49+
50+
ηu = sup(y)
51+
if isfinite(ηu)
52+
if ηu >= 0
53+
ηu_re = sqrt_realpart(inf(absx),ηu,RoundDown)
54+
else
55+
ηu_re = sqrt_realpart(sup(absx),ηu,RoundUp)
56+
end
57+
ηu = ηu_re 0 ? /(ηu,2ηu_re,RoundUp) : zero(T)
58+
end
59+
60+
ηl = inf(y)
61+
if ηl >= 0
62+
ηl_re = sqrt_realpart(sup(absx),ηl,RoundUp)
63+
else
64+
ηl_re = sqrt_realpart(inf(absx),ηl,RoundDown)
65+
end
66+
ηl = ηl_re 0 ? /(ηl,2ηl_re,RoundDown) : zero(T)
67+
68+
ξ = ρl..ρu
69+
η = ηl..ηu
70+
71+
if mid(x)<0
72+
ξ = flipsign(η,mid(η))
73+
η = flipsign((ρl..ρu),mid(η))
74+
end
75+
76+
Complex(ξ,η)
77+
end

src/intervals/intervals.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ include("arithmetic.jl")
122122
include("functions.jl")
123123
include("trigonometric.jl")
124124
include("hyperbolic.jl")
125-
125+
include("complex.jl")
126126

127127
# Syntax for intervals
128128

src/intervals/set_operations.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ function in(x::T, a::Interval) where T<:Real
1313
a.lo <= x <= a.hi
1414
end
1515

16+
in(x::T, a::Complex{<:Interval}) where T<:Real = x real(a) && 0 imag(a)
17+
in(x::Complex{T}, a::Complex{<:Interval}) where T<:Real = real(x) real(a) && imag(x) imag(a)
18+
1619

1720

1821
"""
@@ -52,6 +55,10 @@ function isdisjoint(a::Interval, b::Interval)
5255
islessprime(b.hi, a.lo) || islessprime(a.hi, b.lo)
5356
end
5457

58+
function isdisjoint(a::Complex{<:Interval}, b::Complex{<:Interval})
59+
isdisjoint(real(a),real(b)) || isdisjoint(imag(a),imag(b))
60+
end
61+
5562

5663
# Intersection
5764
"""
@@ -71,6 +78,14 @@ end
7178
intersect(a::Interval{T}, b::Interval{S}) where {T,S} =
7279
intersect(promote(a, b)...)
7380

81+
function intersect(a::Complex{Interval{T}},b::Complex{Interval{T}}) where T
82+
isdisjoint(a,b) && return complex(emptyinterval(T),emptyinterval(T)) # for type stability
83+
84+
complex(intersect(real(a),real(b)),intersect(imag(a),imag(b)))
85+
end
86+
intersect(a::Interval{Complex{T}}, b::Interval{Complex{S}}) where {T,S} =
87+
intersect(promote(a, b)...)
88+
7489

7590
## Hull
7691
"""
@@ -83,6 +98,8 @@ all of `a` and `b`.
8398
hull(a::Interval, b::Interval) = Interval(min(a.lo, b.lo), max(a.hi, b.hi))
8499
#
85100
# hull{T,S}(a::Interval{T}, b::Interval{S}) = hull(promote(a, b)...)
101+
hull(a::Complex{<:Interval},b::Complex{<:Interval}) =
102+
complex(hull(real(a),real(b)),hull(imag(a),imag(b)))
86103

87104
"""
88105
union(a, b)
@@ -94,6 +111,7 @@ to `hull(a,b)`.
94111
union(a::Interval, b::Interval) = hull(a, b)
95112
#
96113
# union(a::Interval, b::Interval) = union(promote(a, b)...)
114+
union(a::Complex{<:Interval},b::Complex{<:Interval}) = hull(a, b)
97115

98116

99117
"""

test/interval_tests/complex.jl

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,34 @@ end
77

88
@testset "Complex interval operations" begin
99
a = @interval 1im
10-
@test typeof(a)== Complex{IntervalArithmetic.Interval{Float64}}
10+
b = @interval 4im + 3
11+
c = (@interval -1 4) + (@interval 0 2)*im
12+
13+
@test typeof(a) == Complex{IntervalArithmetic.Interval{Float64}}
1114
@test a == Interval(0) + Interval(1)*im
1215
@test a * a == Interval(-1)
1316
@test a + a == Interval(2)*im
1417
@test a - a == 0
1518
@test a / a == 1
1619
@test a^2 == -1
20+
21+
@test 3+2im c
22+
@test a b == (@interval 0 3) + (@interval 1 4)*im
23+
@test c (a b) == (@interval 0 3) + (@interval 1 2)*im
24+
@test a b ==+*im
25+
@test isdisjoint(a,b) == true
1726
end
1827

1928
@testset "Complex functions" begin
2029
Z = (3 ± 1e-7) + (4 ± 1e-7)*im
2130
@test sin(Z) == complex(sin(real(Z))*cosh(imag(Z)),sinh(imag(Z))*cos(real(Z)))
2231
@test exp(-im * Interval(π)) == Interval(-1.0, -0.9999999999999999) - Interval(1.224646799147353e-16, 1.2246467991473532e-16)*im
32+
33+
sZ = sqrt(Z)
34+
@test sZ == Interval(1.99999996999999951619,2.00000003000000070585) + Interval(0.99999996999999984926,1.00000003000000048381)*im
35+
@test sqrt(-Z) == imag(sZ) - real(sZ)*im
36+
37+
@test sqrt((@interval -1 0) + (@interval 0)*im) .== (@interval 0 1)*im
38+
@test sqrt((@interval -1 1) + (@interval 0)*im) .== (@interval 0 1) + (@interval 0 1)*im
39+
@test sqrt((@interval -9//32 Inf)*im + (@interval 0)) .== (@interval 0 Inf) + (@interval -3//8 Inf)*im
2340
end

0 commit comments

Comments
 (0)