Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add methods for IntervalBox previously in IntervalRootFinding #160

Merged
merged 4 commits into from
Jun 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/IntervalArithmetic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ import Base:
asin, acos, atan, atan2,
sinh, cosh, tanh, asinh, acosh, atanh,
union, intersect, isempty,
convert, promote_rule, eltype,
convert, promote_rule, eltype, size,
BigFloat, float, widen, big,
∩, ∪, ⊆, eps,
floor, ceil, trunc, sign, round,
expm1, log1p,
precision,
isfinite, isnan,
isfinite, isnan, isinf, iszero,
show, showall,
isinteger, setdiff,
parse
Expand All @@ -40,9 +40,9 @@ export
@interval, @biginterval, @floatinterval, @make_interval,
diam, radius, mid, mag, mig, hull,
emptyinterval, ∅, ∞, isempty, isinterior, isdisjoint, ⪽,
precedes, strictprecedes, ≺, ⊂, ⊃, ⊇,
precedes, strictprecedes, ≺, ⊂, ⊃, ⊇, contains_zero,
entireinterval, isentire, nai, isnai, isthin, iscommon, isatomic,
widen, inf, sup,
widen, inf, sup, bisect,
parameters, eps, dist,
pi_interval,
midpoint_radius, interval_from_midpoint_radius,
Expand Down Expand Up @@ -88,6 +88,7 @@ end

include("intervals/intervals.jl")
include("multidim/multidim.jl")
include("bisect.jl")
include("decorations/decorations.jl")

include("parsing.jl")
Expand Down
42 changes: 42 additions & 0 deletions src/bisect.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

const where_bisect = 0.49609375

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a magic constant :) 0.5 - 1/256, if I'm not mistaken. Is there a particular reason for that?


doc"""
bisect(X::Interval, α=0.49609375)

Split the interval `X` at position α; α=0.5 corresponds to the midpoint.
Returns a tuple of the new intervals.
"""
function bisect(X::Interval, α=where_bisect)
@assert 0 ≤ α ≤ 1

m = mid(X, α)

return (Interval(X.lo, m), Interval(m, X.hi))
end

doc"""
bisect(X::IntervalBox, α=0.49609375)

Bisect the `IntervalBox` `X` at position α ∈ [0,1] along its longest side.
"""
function bisect(X::IntervalBox, α=where_bisect)
i = indmax(diam.(X)) # find longest side

return bisect(X, i, α)
end

doc"""
bisect(X::IntervalBox, i::Integer, α=0.49609375)

Bisect the `IntervalBox` in side number `i`.
"""
function bisect(X::IntervalBox, i::Integer, α=where_bisect)

x1, x2 = bisect(X[i], α)

X1 = setindex(X, x1, i)
X2 = setindex(X, x2, i)

return (X1, X2)
end
3 changes: 3 additions & 0 deletions src/intervals/intervals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ Interval{T}(x) where T = Interval(convert(T, x))

Interval{T}(x::Interval) where T = atomic(Interval{T}, x)

size(x::Interval) = (1,)


"""
is_valid_interval(a::Real, b::Real)

Expand Down
6 changes: 5 additions & 1 deletion src/intervals/special.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ entireinterval(x::Interval{T}) where T<:Real = entireinterval(T)
entireinterval() = entireinterval(precision(Interval)[1])

isentire(x::Interval) = x.lo == -Inf && x.hi == Inf
isinf(x::Interval) = isentire(x)
isunbounded(x::Interval) = x.lo == -Inf || x.hi == Inf


Expand Down Expand Up @@ -75,7 +76,10 @@ This occurs when the interval is empty, or when the upper bound equals the lower
"""
isatomic(x::Interval) = isempty(x) || (x.hi == x.lo) || (x.hi == nextfloat(x.lo))

Base.iszero(x::Interval) = iszero(x.lo) && iszero(x.hi)
iszero(x::Interval) = iszero(x.lo) && iszero(x.hi)

contains_zero(X::Interval{T}) where {T} = zero(T) ∈ X


# """
# widen(x)
Expand Down
6 changes: 6 additions & 0 deletions src/multidim/intervalbox.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ diam(X::IntervalBox) = maximum(diam.(X.v))

emptyinterval(X::IntervalBox{N,T}) where {N,T} = IntervalBox(emptyinterval.(X.v))

isinf(X::IntervalBox) = any(isinf(X))

isinterior(X::IntervalBox{N,T}, Y::IntervalBox{N,T}) where {N,T} = all(isinterior.(X, Y))

contains_zero(X::SVector) = all(contains_zero(X))
contains_zero(X::IntervalBox) = all(contains_zero(X))

import Base.×
×(a::Interval...) = IntervalBox(a...)
Expand Down
30 changes: 30 additions & 0 deletions test/interval_tests/bisect.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using IntervalArithmetic
using Base.Test


@testset "`bisect` function" begin
X = 0..1
@test bisect(X, 0.5) == (0..0.5, 0.5..1)
@test bisect(X, 0.25) == (0..0.25, 0.25..1)

@test bisect(X) == (interval(0.0, 0.49609375), interval(0.49609375, 1.0))

X = -∞..∞
@test bisect(X, 0.5) == (-∞..0, 0..∞)
@test bisect(X, 0.75) == (-∞..0, 0..∞)

X = 1..∞
@test bisect(X) == (Interval(1, prevfloat(∞)), Interval(prevfloat(∞), ∞))

X = (0..1) × (0..2)
@test bisect(X, 0.5) == ( (0..1) × (0..1), (0..1) × (1..2) )
@test bisect(X, 0.25) == ( (0..1) × (0..0.5), (0..1) × (0.5..2) )
@test bisect(X, 1, 0.5) == ( (0..0.5) × (0..2), (0.5..1) × (0..2) )
@test bisect(X, 1, 0.25) == ( (0..0.25) × (0..2), (0.25..1) × (0..2) )

@test bisect(X) == (IntervalBox(0..1, interval(0.0, 0.9921875)),
IntervalBox(0..1, Interval(0.9921875, 2.0)))

X = (-∞..∞) × (-∞..∞)
@test bisect(X) == ( (-∞..0) × (-∞..∞), (0..∞) × (-∞..∞))
end
3 changes: 1 addition & 2 deletions test/interval_tests/complex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ end

@testset "Complex functions" begin
Z = (3 ± 1e-7) + (4 ± 1e-7)*im
@test sin(Z) == Interval(3.853734949309744, 3.8537411265295543) - Interval(27.016810169394066, 27.016816346613904)*im

@test sin(Z) == complex(sin(real(Z))*cosh(imag(Z)),sinh(imag(Z))*cos(real(Z)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I though this way is more stable :-)

@test exp(-im * Interval(π)) == Interval(-1.0, -0.9999999999999999) - Interval(1.224646799147353e-16, 1.2246467991473532e-16)*im
end
1 change: 1 addition & 0 deletions test/interval_tests/construction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ using Base.Test

# Naive constructors, with no conversion involved
@test Interval(1) == Interval(1.0, 1.0)
@test size(Interval(1)) == (1,)
@test Interval(big(1)) == Interval(1.0, 1.0)
@test Interval(eu) == Interval(1.0*eu)
@test Interval(1//10) == Interval{Rational{Int}}(1//10, 1//10)
Expand Down
4 changes: 2 additions & 2 deletions test/interval_tests/intervals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ include("loops.jl")
include("parsing.jl")
include("rounding_macros.jl")
include("rounding.jl")

# include("complex.jl")
include("bisect.jl")
include("complex.jl")