-
Notifications
You must be signed in to change notification settings - Fork 71
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
Make Interval constructor fast by not including checks #26
Changes from all commits
29729f6
c0614cf
16422ed
db4d74d
37d22be
032642d
c04bf67
92d087b
3755f9b
c2d0355
62421ca
c459399
ecd7f59
edca3bd
6ba41f1
b78255a
6fee75e
dc84de5
2db536b
ada3fe9
237d334
d4628a8
42124cc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,37 +5,38 @@ | |
|
||
## Interval type | ||
|
||
if haskey(ENV, "IA_VALID") == true | ||
const validity_check = true | ||
else | ||
const validity_check = false | ||
end | ||
|
||
abstract type AbstractInterval{T} <: Real end | ||
|
||
struct Interval{T<:Real} <: AbstractInterval{T} | ||
lo :: T | ||
hi :: T | ||
|
||
function Interval{T}(a::Real, b::Real) where T | ||
function Interval{T}(a::Real, b::Real) where T<:Real | ||
|
||
if isnan(a) || isnan(b) | ||
return new(NaN, NaN) # nai | ||
end | ||
if validity_check | ||
|
||
if a > b | ||
# empty interval = [∞,-∞] | ||
(isinf(a) && isinf(b)) && return new(a, b) | ||
throw(ArgumentError("Must have a ≤ b to construct Interval(a, b).")) | ||
end | ||
if is_valid_interval(a, b) | ||
new(a, b) | ||
|
||
else | ||
throw(ArgumentError("Interval of form [$a, $b] not allowed. Must have a ≤ b to construct interval(a, b).")) | ||
end | ||
|
||
# The IEEE Std 1788-2015 states that a < Inf and b > -Inf; | ||
# see page 6, "bounds". | ||
if a == Inf || b == -Inf | ||
throw(ArgumentError( | ||
"Must satisfy `a < Inf` and `b > -Inf` to construct Interval(a, b).")) | ||
end | ||
|
||
return new(a,b) | ||
new(a, b) | ||
|
||
end | ||
end | ||
|
||
|
||
|
||
## Outer constructors | ||
|
||
Interval(a::T, b::T) where T<:Real = Interval{T}(a, b) | ||
|
@@ -57,6 +58,54 @@ Interval{T}(x) where T = Interval(convert(T, x)) | |
|
||
Interval{T}(x::Interval) where T = convert(Interval{T}, x) | ||
|
||
""" | ||
is_valid_interval(a::Real, b::Real) | ||
|
||
Check if `(a, b)` constitute a valid interval | ||
""" | ||
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 | ||
end | ||
|
||
if a > b | ||
if isinf(a) && isinf(b) | ||
return true # empty interval = [∞,-∞] | ||
else | ||
return false | ||
end | ||
end | ||
|
||
if a == Inf || b == -Inf | ||
return false | ||
end | ||
|
||
return true | ||
end | ||
|
||
""" | ||
interval(a, b) | ||
|
||
`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) | ||
if !is_valid_interval(a, b) | ||
throw(ArgumentError("`[$a, $b]` is not a valid interval. Need `a ≤ b` to construct `interval(a, b)`.")) | ||
end | ||
|
||
return Interval(a, b) | ||
end | ||
|
||
interval(a::Real) = interval(a, a) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, exactly: the user is supposed to use the In fact, my idea would be that the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you also add some docstrings here? |
||
|
||
## Include files | ||
include("special.jl") | ||
include("macros.jl") | ||
|
@@ -75,11 +124,11 @@ include("hyperbolic.jl") | |
|
||
# a..b = Interval(convert(Interval, a).lo, convert(Interval, b).hi) | ||
|
||
..(a::Integer, b::Integer) = Interval(a, b) | ||
..(a::Integer, b::Real) = Interval(a, nextfloat(float(b))) | ||
..(a::Real, b::Integer) = Interval(prevfloat(float(a)), b) | ||
..(a::Integer, b::Integer) = interval(a, b) | ||
..(a::Integer, b::Real) = interval(a, nextfloat(float(b))) | ||
..(a::Real, b::Integer) = interval(prevfloat(float(a)), b) | ||
|
||
..(a::Real, b::Real) = Interval(prevfloat(float(a)), nextfloat(float(b))) | ||
..(a::Real, b::Real) = interval(prevfloat(float(a)), nextfloat(float(b))) | ||
|
||
macro I_str(ex) # I"[3,4]" | ||
@interval(ex) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,20 +43,20 @@ using Base.Test | |
|
||
# 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(BigInt(1), 1//10) | ||
@test_throws ArgumentError interval(1, 0.1) | ||
@test_throws ArgumentError interval(big(1), big(0.1)) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If my comment about EDIT: Fix the 's |
||
@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_throws ArgumentError interval(Inf) | ||
@test_throws ArgumentError interval(-Inf, -Inf) | ||
@test_throws ArgumentError interval(Inf, Inf) | ||
|
||
# Conversion to Interval without type | ||
@test convert(Interval, 1) == Interval(1.0) | ||
|
@@ -254,12 +254,8 @@ end | |
|
||
# issue 192: | ||
@testset "Disallow a single NaN in an interval" begin | ||
a = Interval(NaN, 2) | ||
@test isnan(a.lo) && isnan(a.hi) | ||
|
||
a = Interval(Inf, NaN) | ||
@test isnan(a.lo) && isnan(a.hi) | ||
|
||
@test_throws ArgumentError interval(NaN, 2) | ||
@test_throws ArgumentError interval(Inf, NaN) | ||
end | ||
|
||
# issue 206: | ||
|
@@ -305,3 +301,7 @@ end | |
x = 3..4 | ||
@test @interval(f(x.lo), f(x.hi)) == Interval(0.75, 0.8) | ||
end | ||
|
||
@testset "a..b with a > b" begin | ||
@test_throws ArgumentError 3..2 | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This was not there when I began reviewing.)
My suggestion (see elsewhere) is that the default is to have the validity being checked.