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

return empty interval when an invalid input is given #461

Merged
merged 7 commits into from
Jun 2, 2021
Merged
Show file tree
Hide file tree
Changes from 2 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
4 changes: 2 additions & 2 deletions src/decorations/intervals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ DecoratedInterval(I::Interval{T}, d::DECORATION) where T<:AbstractFloat =
DecoratedInterval{T}(I, d)

function DecoratedInterval(a::T, b::T, d::DECORATION) where T<:Real
a > b && return nai(T)
lucaferranti marked this conversation as resolved.
Show resolved Hide resolved
is_valid_interval(a, b) || return nai(T)
DecoratedInterval(Interval(a,b), d)
end

Expand All @@ -63,7 +63,7 @@ DecoratedInterval(a::T, b::S, d::DECORATION) where {T<:Real, S<:Real} =
DecoratedInterval(I::Interval) = DecoratedInterval(I, decoration(I))

function DecoratedInterval(a::T, b::T) where T<:Real
a > b && return nai(T)
is_valid_interval(a, b) || return nai(T)
DecoratedInterval(Interval(a,b))
end

Expand Down
11 changes: 4 additions & 7 deletions src/intervals/intervals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,7 @@ function is_valid_interval(a::Real, b::Real)
# println("isvalid()")

if isnan(a) || isnan(b)
if isnan(a) && isnan(b)
return true
else
return false
end
return false
end

if a > b
Expand All @@ -106,9 +102,10 @@ end

`interval(a, b)` checks whether [a, b] is a valid `Interval`, which is the case if `-∞ <= a <= b <= ∞`, using the (non-exported) `is_valid_interval` function. If so, then an `Interval(a, b)` object is returned; if not, then an error is thrown.
"""
function interval(a::Real, b::Real)
function interval(a::T, b::S) where {T<:Real, S<:Real}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This docstring is no longer correct, it never throws an error.

Also precising that this is the way of creating IEEE compliant interval would be great.

Copy link
Member Author

@lucaferranti lucaferranti May 31, 2021

Choose a reason for hiding this comment

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

right! I had a separated PR (#460 ) for the docstrings which I had opened before this. The idea was to rebase that once this is merged and fix the docstrings there but indeed... it makes no sense! I'll close that PR and take care of the docstrings here :D

Copy link
Member Author

@lucaferranti lucaferranti Jun 1, 2021

Choose a reason for hiding this comment

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

updated the docstring. II think the note about IEEE compliance may be more appropriate after the package is actually IEEE compliant? what do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it is fine like that. This will be discussed in #468 where will have to sort out what we want each constructor to do anyway.

Even if the full package is not yet compliant, I think it will be good to declare our intent on which constructor corresponds to the IEEE constructors.

if !is_valid_interval(a, b)
throw(ArgumentError("`[$a, $b]` is not a valid interval. Need `a ≤ b` to construct `interval(a, b)`."))
@warn "Invalid input, empty interval is returned"
return emptyinterval(promote_type(T, S, Float64))
lbenet marked this conversation as resolved.
Show resolved Hide resolved
lbenet marked this conversation as resolved.
Show resolved Hide resolved
end

return Interval(a, b)
Expand Down
9 changes: 9 additions & 0 deletions test/decoration_tests/decoration_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ let b
b = @decorated 3 4

@test dist(a, b) == 2.0

# invalid input
@test isnai(@decorated(3, 1, com))
@test isnai(@decorated(3, 1))
@test isnai(@decorated(Inf, Inf))
@test isnai(@decorated(-Inf, -Inf))
@test isnai(@decorated(NaN, 3))
@test isnai(@decorated(3, NaN))
@test isnai(@decorated(NaN, NaN))
end

@testset "Convert string to DecoratedInterval" begin
Expand Down
4 changes: 2 additions & 2 deletions test/interval_tests/consistency.jl
Original file line number Diff line number Diff line change
Expand Up @@ -380,10 +380,10 @@ setprecision(Interval, Float64)
@test interval(1, 2) == Interval(1, 2)

@test inf(Interval(3, 2)) == 3
@test_throws ArgumentError interval(3, 2)
@test isempty(interval(3, 2))

@test sup(Interval(Inf, Inf)) == Inf
@test_throws ArgumentError interval(Inf, Inf)
@test isempty(interval(Inf, Inf))

end

Expand Down
47 changes: 24 additions & 23 deletions test/interval_tests/construction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,20 +69,20 @@ const eeuler = Base.MathConstants.e

# Disallowed conversions with a > b

@test_throws ArgumentError interval(2, 1)
@test_throws ArgumentError interval(big(2), big(1))
@test_throws ArgumentError interval(BigInt(1), 1//10)
@test_throws ArgumentError interval(1, 0.1)
@test_throws ArgumentError interval(big(1), big(0.1))

@test_throws ArgumentError @interval(2, 1)
@test_throws ArgumentError @interval(big(2), big(1))
@test_throws ArgumentError @interval(big(1), 1//10)
@test_throws ArgumentError @interval(1, 0.1)
@test_throws ArgumentError @interval(big(1), big(0.1))
@test_throws ArgumentError interval(Inf)
@test_throws ArgumentError interval(-Inf, -Inf)
@test_throws ArgumentError interval(Inf, Inf)
@test isempty(interval(2, 1))
@test isempty(interval(big(2), big(1)))
@test isempty(interval(BigInt(1), 1//10))
@test isempty(interval(1, 0.1))
@test isempty(interval(big(1), big(0.1)))

@test isempty(@interval(2, 1))
@test isempty(@interval(big(2), big(1)))
@test isempty(@interval(big(1), 1//10))
@test isempty(@interval(1, 0.1))
@test isempty(@interval(big(1), big(0.1)))
@test isempty(interval(Inf))
@test isempty(interval(-Inf, -Inf))
@test isempty(interval(Inf, Inf))

# Conversion to Interval without type
@test convert(Interval, 1) == Interval(1.0)
Expand Down Expand Up @@ -237,10 +237,10 @@ end
a = big(0.1)..2
@test typeof(a) == Interval{BigFloat}

@test_throws ArgumentError 2..1
@test_throws ArgumentError π..1
@test_throws ArgumentError π..eeuler
@test_throws ArgumentError 4..π
@test isempty(2..1)
@test isempty(π..1)
@test isempty(π..eeuler)
@test isempty(4..π)
@test 1..π == Interval(1, π)
end

Expand Down Expand Up @@ -292,9 +292,10 @@ end
end

# issue 192:
@testset "Disallow a single NaN in an interval" begin
@test_throws ArgumentError interval(NaN, 2)
@test_throws ArgumentError interval(Inf, NaN)
@testset "Disallow NaN in an interval" begin
@test isempty(interval(NaN, 2))
@test isempty(interval(Inf, NaN))
@test isempty(interval(NaN, NaN))
end

# issue 206:
Expand Down Expand Up @@ -342,7 +343,7 @@ end
end

@testset "a..b with a > b" begin
@test_throws ArgumentError 3..2
@test isempty(3..2)
end

@testset "Hashing of Intervals" begin
Expand Down Expand Up @@ -374,7 +375,7 @@ import IntervalArithmetic: force_interval
@test force_interval(4, Inf) == Interval(4, Inf)
@test force_interval(Inf, 4) == Interval(4, Inf)
@test force_interval(Inf, -Inf) == Interval(-Inf, Inf)
@test_throws ArgumentError force_interval(NaN, 3)
@test isempty(force_interval(NaN, 3))
end

@testset "Zero interval" begin
Expand Down
8 changes: 4 additions & 4 deletions test/interval_tests/numeric.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ setprecision(Interval, Float64)
y = 4..5
a = 3
b = 12

@test sqrt(sum(x.^2 .+ y.^2)) == 5..13

for i in 1:20
Expand All @@ -24,7 +24,7 @@ setprecision(Interval, Float64)
end

a = 4
b = 5
b = 5
for i in 1:20
@test y.+i == (a+i)..(b+i)
end
Expand Down Expand Up @@ -115,7 +115,7 @@ end
@test Interval(1,2) ^ -3 == Interval(1/8, 1.0)
@test Interval(0,3) ^ -3 == @interval(1/27, Inf)
@test Interval(-1,2) ^ -3 == entireinterval()
@test_throws ArgumentError interval(-1, -2) ^ -3 # wrong way round
@test isempty(interval(-1, -2) ^ -3) # wrong way round
@test Interval(-3,2) ^ (3//1) == Interval(-27, 8)
@test Interval(0.0) ^ 1.1 == Interval(0, 0)
@test Interval(0.0) ^ 0.0 == emptyinterval()
Expand Down Expand Up @@ -432,4 +432,4 @@ end
@test nthroot(Interval{BigFloat}(-27, 27), -3) == Interval{BigFloat}(-Inf, Inf)
@test nthroot(Interval{BigFloat}(-81, -16), -4) == ∅
@test nthroot(Interval{BigFloat}(-81, -16), 1) == Interval{BigFloat}(-81, -16)
end
end