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

Check for overflow when negating typemin in Rational #31090

Closed
wants to merge 19 commits into from
Closed

Check for overflow when negating typemin in Rational #31090

wants to merge 19 commits into from

Conversation

JeffreySarnoff
Copy link
Contributor

This PR corrects the check for rational overflow when either unary - or abs is applied to a value q::Rational{S} where {S::BitSigned} && (numerator(q) == typemin(S) || denominator(q) == typemin(S)).

tests have been added

@JeffreySarnoff
Copy link
Contributor Author

last two updates removed trailing whitespaces

@JeffreySarnoff
Copy link
Contributor Author

I don't understand the Appveyor failure on x86_64 when it passes on i686 (and should care).
Please squash the commits so there is one for rationals.jl and one for test/rationals.jl if that is best.

My PR is to plug overflow on -typemin abs(typemin) and to deal with

julia> Rational(-3, typemin(Int)) > 0
true

julia> Rational(typemin(Int), -3) > 0
false

base/rational.jl Outdated
end
@noinline __throw_rational_argerror(T) = throw(ArgumentError("invalid rational: zero($T)//zero($T)"))
@noinline __throw_rational_ovferror(T) = throw(OverflowError("num[den] is typemin(T) and den[num] is negative"))
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

I find this error message a bit confusing: perhaps two different errors for the two cases? Or vaguer wording about one of the numerator or denominator being too large?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the note. Revised it:

@noinline __throw_rational_ovferror(num::T, den::T) where {T} =
    (num < den) ? throw(OverflowError("typemin($T)//$den")) : throw(OverflowError("$num//typemin($T)"))

@@ -19,7 +19,12 @@ using Test
@test -7//0 == -1//0

@test_throws OverflowError -(0x01//0x0f)
@test_throws OverflowError typemin(Int)//(-1)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
@test_throws OverflowError typemin(Int)//(-1)
@test_throws OverflowError typemin(Int)//(-1)
@test typemin(Int)//(-2) == abs(typemin(Int)>>1)//1

@mbauman mbauman changed the title Jas/rational+typemin Check for overflow when negating typemin in Rational Feb 21, 2019
Co-Authored-By: JeffreySarnoff <JeffreySarnoff@users.noreply.github.com>
base/rational.jl Outdated

function Rational{T}(num::Integer, den::Integer) where T<:BitSigned
num == den == zero(T) && __throw_rational_argerror(T)
num < 0 && den < 0 && (num === typemin(T) || den === typemin(T)) && __throw_rational_ovferror(num, den)
Copy link
Contributor

Choose a reason for hiding this comment

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

This check may have to move after the divgcd to handle the typemin(Int)//-2 case

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right about that. I made the change. I see no distinction between Int < 0 and sign(Int) < 0 in generated code -- is there a reason to prefer one over the other?

Copy link
Contributor

Choose a reason for hiding this comment

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

not that I can think of?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is an additional gotcha

julia> divgcd(-2,typemin(Int64))
(-1, -4611686018427387904)

julia> Rational{Int}(-2,typemin(Int))
Rational{Int64}(1, -4611686018427387904) # both should be positive

@JeffreySarnoff
Copy link
Contributor Author

The latest revision to rational.jl is passing its tests -- the failures are about other tests being broken.

@JeffreySarnoff
Copy link
Contributor Author

restart

@JeffreySarnoff
Copy link
Contributor Author

I just wanted to restart the build -- thinking the stuff that broke the build of Julia has been remedied and, if so this PR likely passes the tests. Usually close then reopen forces the build to restart. This time close closed and my ability to reopen flew the proverbial coop. ❓ ❓ ⛑️

@JeffreySarnoff
Copy link
Contributor Author

perhaps deleting the fork I branched for this work was not the best move ...

two files are involved: base/rational.jl and tests/rational.jl
I have copied them here.

please advise ☺️

@StefanKarpinski
Copy link
Sponsor Member

So what's the deal here? You deleted the fork that this branch was from? Fortunately, the patch is still visible so it should be possible to reconstruct the changes from that.

@JeffreySarnoff
Copy link
Contributor Author

Yes -- the changes are here.
I cannot reopen this -- github wont let me.

@StefanKarpinski
Copy link
Sponsor Member

Just make a new PR then, I guess.

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

3 participants