-
Notifications
You must be signed in to change notification settings - Fork 70
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
FIX #410 by changing type arguments passed to rationalize() on atomic() #411
Conversation
Thanks a lot for the contribution! Here are some feedback. First, we usually avoid conditional on type if not necessary (I do not think such conditional are bad, but that is how the convention goes) . Here this means adding a method to In the present case however, I wonder if using Finally, could you add some tests that would fail without your fix? That makes sure we will never reintroduce the bug in the future. |
Dear Benoît,
You have valid points. Indeed the 'julian' way of implementing cases
like this is through the type system rather than the embedded `if`.
I'll change the PR (Pull Request) somtime along this (busy) week, (i)
doing it in the 'julian' way, which will keep the speed unchanged for
the other DataTypes, and also (ii) adding pertinent tests.
Best regards,
|
A good way to do this would be to make an internal |
test/interval_tests/construction.jl
Outdated
# Interval{BigFloat} construction through ± involving a Float64 intermediate step ending up | ||
# with a _smaller_ interval radius | ||
setprecision(BigFloat, 256) do | ||
MID = BigFloat("0.1") |
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.
We do not use capitalized variable names in the codebase.
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.
OK. Will change.
src/intervals/conversion.jl
Outdated
@@ -104,7 +104,8 @@ end | |||
function atomic(::Type{Interval{T}}, x::S) where {T<:AbstractFloat, S<:AbstractFloat} | |||
isinf(x) && return wideinterval(T(x)) | |||
|
|||
xrat = rationalize(x) | |||
# TODO: Delegate type assertion to the type system | |||
xrat = T == BigFloat ? rationalize(BigInt, x) : rationalize(x) # Issue #410 |
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.
Please change this to use dispatch with appropriate methods.
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.
Done! PR updated with (i) more specialized
atomic(::Type{Interval{BigFloat}}, x::S) where {S<:AbstractFloat}
method definition and (ii) tests for the ±
and ..
interval construction operators with BigFloat
precision arguments (using lowercase variables only).
@@ -116,6 +116,21 @@ function atomic(::Type{Interval{T}}, x::S) where {T<:AbstractFloat, S<:AbstractF | |||
return atomic(Interval{T}, xrat) | |||
end | |||
|
|||
function atomic(::Type{Interval{BigFloat}}, x::S) where {S<:AbstractFloat} |
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.
There's no need to copy and paste this code (that is almost always a bad idea).
The only thing that needs doing is to make a function _rationalize
that knows what type of Float
is passed in and calls rationalize
with the corresponding integer type.
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.
Agreed with being almost always a bad idea copying/pasting code like that.
I understood your last reply (of using dispatch) as applying to atomic()
rather than to rationalize()
. The originally intended one is now abundantly clear.
The _rationalize()
method requires that some calling methods to be changed from rationalize(...)
to _rationalize(...)
.
Here's the list (on master's) of the sources that currently call rationalize()
:
IntervalArithmetic.jl$ grep rationalize $(find . -name '*jl')
./test/interval_tests/construction.jl: #@test Interval{Rational{Int}}(pi) == Interval(rationalize(1.0*pi))
./test/interval_tests/construction.jl: @test Interval(1//10).lo == rationalize(0.1)
./src/decorations/intervals.jl:# convert(DecoratedInterval{T}, rationalize(x))
./src/intervals/conversion.jl: xrat = rationalize(x)
./src/intervals/conversion.jl: Interval(rationalize(T, x))
./src/intervals/conversion.jl: Interval(rationalize(T, x))
I imagine that the tests should be left alone, as in them, rationalize()
is not being used in Interval construction and calls are part of RHS's — hence, expected values.
The cases in conversion.jl
are pretty clear.
What about the one in ./src/decorations/intervals.jl
? Should be left untouched or changed to _rationalize()
? (I'm unfamiliar with that part of the code and it's functionality).
Best regards!
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.
Oh, in the case that rationalize()
calls on multiple sources are to be changed, in which source file would be best to define _rationalize()
in your estimate?
The one-line change is believed to solve Issue #410. If preferred, the one-liner can be made into a full
if ... end
block. Let me know!