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

FIX #410 by changing type arguments passed to rationalize() on atomic() #411

Closed
wants to merge 7 commits into from

Conversation

cnaak
Copy link

@cnaak cnaak commented Sep 4, 2020

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!

@coveralls
Copy link

coveralls commented Sep 4, 2020

Coverage Status

Coverage remained the same at 91.123% when pulling 2740606 on cnaak:fix_#410 into f80b683 on JuliaIntervals:master.

@cnaak cnaak changed the title FIX type arguments to rationalize() on atomic() due to #410 FIX #410 by changing type arguments passed to rationalize() on atomic() Sep 4, 2020
@Kolaru
Copy link
Collaborator

Kolaru commented Sep 4, 2020

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 atomic for interval with BigFloat parameter.

In the present case however, I wonder if using rationalize(BigInt, x) in all cases would be acceptable (@dpsanders). On my machine this incurs a 10x speed penalty (6.7 us instead of 500 ns), but atomic should never be a bottleneck anyway. Also this would remove the need for the corner-case check that follow.

Finally, could you add some tests that would fail without your fix? That makes sure we will never reintroduce the bug in the future.

@cnaak
Copy link
Author

cnaak commented Sep 6, 2020 via email

@dpsanders
Copy link
Member

A good way to do this would be to make an internal _rationalize function that chooses the correct integer type to call rationalize with. [Note that you can pass an integer type as the first argument to rationalize (as I only just discovered!).]

# Interval{BigFloat} construction through ± involving a Float64 intermediate step ending up
# with a _smaller_ interval radius
setprecision(BigFloat, 256) do
MID = BigFloat("0.1")
Copy link
Member

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.

Copy link
Author

Choose a reason for hiding this comment

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

OK. Will change.

@@ -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
Copy link
Member

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.

Copy link
Author

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}
Copy link
Member

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.

Copy link
Author

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!

Copy link
Author

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?

@cnaak cnaak closed this by deleting the head repository Sep 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants