-
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
Introduce atomic
function, extracted out of convert
#114
Conversation
Codecov Report
@@ Coverage Diff @@
## master #114 +/- ##
==========================================
+ Coverage 92.69% 92.81% +0.11%
==========================================
Files 21 21
Lines 958 960 +2
==========================================
+ Hits 888 891 +3
+ Misses 70 69 -1
Continue to review full report at Codecov.
|
src/intervals/conversion.jl
Outdated
isinf(x) && return wideinterval(T(x)) | ||
|
||
Interval{T}( T(x, RoundDown), T(x, RoundUp) ) | ||
# the rounding up could be done as nextfloat of the rounded down one? | ||
# use @round_up and @round_down here? | ||
end | ||
|
||
function convert(::Type{Interval{T}}, x::S) where {T<:AbstractFloat, S<:AbstractFloat} | ||
function closure(::Type{Interval{T}}, x::S) where {T<:AbstractFloat, S<:AbstractFloat} | ||
isinf(x) && return wideinterval(x)#Interval{T}(prevfloat(T(x)), nextfloat(T(x))) |
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.
A small remark, which is not due to the changes you propose (perhaps it is me the one to be blamed!), but this is a good chance to correct it: This method is not type stable. To be type stable, I think it should return wideinterval(T(x))
.
An example that shows the problem is:
julia> typeof( IntervalArithmetic.closure(Interval{BigFloat}, Inf) )
IntervalArithmetic.Interval{Float64}
julia> typeof( IntervalArithmetic.closure(Interval{BigFloat}, 0.1) )
IntervalArithmetic.Interval{BigFloat}
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.
While I agree this change should be made, I think it should be made in a separate pull request.
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.
As you prefer...
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.
@tkoolen Thanks a lot for the contribution! I have taken a look on this PR and I am totally in favor of merging it. The only comment I have is related to a type-unstable method, which comes from the past, but it is a good occasion to correct it.
I agree with your comments (in the tests) about the undesirability of certain behavior, e.g. that
convert(Interval, 0.1) == Interval(0.09999999999999999, 0.1)
returns true
. This is in a sense consistent with the behavior of Interval(0.1,0.1)
, which is not properly rounded (nor checked that the lower bound is less-or-equal to the upper one). Since this may appear to be "not so natural", I think it is worth to write it somewhere (docs, and perhaps in the docstrings of closure)! And to emphasize this point, it is worth to have the proper tests.
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.
Alright, so still to do:
- documentation (docstring for
closure
) - remove previous tests with undesired behavior instead of just commenting them out
- decide whether the
convert
methods that aren't getting called in tests should be deleted or should be covered by additional tests - test coverage for
^(a::Interval{Rational{T}}, x::AbstractFloat) where T<:Integer
and^(a::Interval{Rational{T}}, x::AbstractFloat) where T<:Integer
- test coverage for
closure(::Type{Interval{Rational{Int}}}, x::Irrational)
andclosure(::Type{Interval{Rational{BigInt}}}, x::Irrational)
src/intervals/conversion.jl
Outdated
isinf(x) && return wideinterval(T(x)) | ||
|
||
Interval{T}( T(x, RoundDown), T(x, RoundUp) ) | ||
# the rounding up could be done as nextfloat of the rounded down one? | ||
# use @round_up and @round_down here? | ||
end | ||
|
||
function convert(::Type{Interval{T}}, x::S) where {T<:AbstractFloat, S<:AbstractFloat} | ||
function closure(::Type{Interval{T}}, x::S) where {T<:AbstractFloat, S<:AbstractFloat} | ||
isinf(x) && return wideinterval(x)#Interval{T}(prevfloat(T(x)), nextfloat(T(x))) |
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.
While I agree this change should be made, I think it should be made in a separate pull request.
Re: test coverage for julia> convert(Interval{Rational{Int}}, π)
ERROR: MethodError: Cannot `convert` an object of type IntervalArithmetic.Interval{BigFloat} to an object of type IntervalArithmetic.Interval{Rational{Int64}}
This may have arisen from a call to the constructor IntervalArithmetic.Interval{Rational{Int64}}(...),
since type constructors fall back to convert methods.
Stacktrace:
[1] convert(::Type{IntervalArithmetic.Interval{Rational{Int64}}}, ::Irrational{:π}) at /home/twan/code/RigidBodyDynamics/v0.6/IntervalArithmetic/src/intervals/conversion.jl:62 How should this be fixed? Edit: similarly, on master: julia> convert(Interval{Rational{Int}}, Interval(0.1))
ERROR: MethodError: Cannot `convert` an object of type IntervalArithmetic.Interval{Float64} to an object of type IntervalArithmetic.Interval{Rational{Int64}}
This may have arisen from a call to the constructor IntervalArithmetic.Interval{Rational{Int64}}(...),
since type constructors fall back to convert methods. which causes julia> Interval(5//2)^3.0
ERROR: MethodError: Cannot `convert` an object of type IntervalArithmetic.Interval{Float64} to an object of type IntervalArithmetic.Interval{Rational{Int64}}
This may have arisen from a call to the constructor IntervalArithmetic.Interval{Rational{Int64}}(...),
since type constructors fall back to convert methods.
Stacktrace:
[1] ^(::IntervalArithmetic.Interval{Rational{Int64}}, ::Float64) at /home/twan/code/RigidBodyDynamics/v0.6/IntervalArithmetic/src/intervals/functions.jl:138 |
The following is an idea, so feel free to change it as you want.
The following function does that in a very non-optimized way: function clausure(::Type{Interval{Rational{T}}}, x::S) where {T<:Integer, S<:Irrational}
x_rat = rationalize(T, x)
p_rat = numerator(x_rat)
q_rat = denominator(x_rat)
lo = max( p_rat//(q_rat+1), (p_rat-1)//q_rat )
hi = min( p_rat//(q_rat-1), (p_rat+1)//q_rat )
return Interval(lo,hi)
end And it seems to work: julia> π ∈ clausure(Interval{Rational{Int}}, π)
true
julia> big(π) ∈ clausure(Interval{Rational{Int}}, π)
true
julia> eu ∈ clausure(Interval{Rational{Int}}, eu)
true
julia> big(eu) ∈ clausure(Interval{Rational{Int}}, eu)
true
julia> float( diam(clausure(Interval{Rational{Int}}, π)) )
2.373975753932138e-18
julia> float( diam(clausure(Interval{Rational{Int}}, eu)) )
9.472290677529826e-19
julia> diam(@interval(π))
4.440892098500626e-16 I hope this is useful! |
Yeah, might be a good idea to merge now if you're sufficiently happy with it. It'd be another couple of days (maybe even a week) before I would have time to make and test the changes proposed by @lbenet. |
I think we will definitely merge then. My only doubt would be about the name closure. In true julia style, we should bikeshed it... I suggest enclosure (standard in the interval community) or atomic (as in atomic - indivisible). |
I think I prefer |
|
Thanks again for this contribution, @tkoolen! |
closure
function, extracted out of convert
atomic
function, extracted out of convert
This implements #104 (comment).
closure
essentially does whatconvert
did previously.convert
will now avoid callingclosure
when doing so makes senseconvert
in the package are replaced withclosure
Result:
Fixes #104.
I'm not married to the name
closure
, but it kind of works.Tests almost pass, but there's a couple of failures fortan
; this is the first:IntervalArithmetic.jl/test/ITF1788_tests/libieeep1788_tests_elem.jl
Line 3629 in e6375b0
lo_quadrant
appears to be wrong. Any idea why that would be the case?Never mind, already fixed it; all tests pass now.