Skip to content

Commit

Permalink
fix overflows in rational comparisons. part of #2960
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Jul 2, 2013
1 parent cf01a16 commit d4c4d2a
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 5 deletions.
6 changes: 4 additions & 2 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,9 @@ end
ndigits(x::BigInt) = ccall((:__gmpz_sizeinbase,:libgmp), Culong, (Ptr{BigInt}, Int32), &x, 10)
isprime(x::BigInt, reps=25) = ccall((:__gmpz_probab_prime_p,:libgmp), Cint, (Ptr{BigInt}, Cint), &x, reps) > 0

widemul(x::BigInt, y::BigInt) = x*y
widemul(x::Union(Int128,Uint128), y::Union(Int128,Uint128)) = BigInt(x)*BigInt(y)
widemul(x::BigInt, y::BigInt) = x*y
widemul(x::Int128, y::Uint128) = BigInt(x)*BigInt(y)
widemul(x::Uint128, y::Int128) = BigInt(x)*BigInt(y)
widemul{T<:Integer}(x::T, y::T) = BigInt(x)*BigInt(y)

end # module
2 changes: 2 additions & 0 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,8 @@ widemul(x::Uint16, y::Uint16) = uint32(x)*uint32(y)
widemul(x::Int32, y::Int32) = int64(x)*int64(y)
widemul(x::Uint32, y::Uint32) = uint64(x)*uint64(y)

widemul(x::Integer, y::Integer) = widemul(promote(x,y)...)

if WORD_SIZE==32
function widemul(u::Int64, v::Int64)
local u0::Uint64, v0::Uint64, w0::Uint64
Expand Down
10 changes: 8 additions & 2 deletions base/rational.jl
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,18 @@ end
==(q::Rational, x::FloatingPoint) = ispow2(q.den) & (x == q.num/q.den) & (x*q.den == q.num)

# TODO: fix inequalities to be in line with equality check
< (x::Rational, y::Rational) = x.den == y.den ? x.num < y.num : x.num*y.den < x.den*y.num
< (x::Rational, y::Rational) = x.den == y.den ? x.num < y.num :
widemul(x.num,y.den) < widemul(x.den,y.num)
< (x::Rational, y::Integer ) = x.num < widemul(x.den,y)
< (x::Rational, y::Real ) = x.num < x.den*y
< (x::Integer , y::Rational) = widemul(x,y.den) < y.num
< (x::Real , y::Rational) = x*y.den < y.num

<=(x::Rational, y::Rational) = x.den == y.den ? x.num <= y.num : x.num*y.den <= x.den*y.num
<=(x::Rational, y::Rational) = x.den == y.den ? x.num <= y.num :
widemul(x.num,y.den) <= widemul(x.den,y.num)
<=(x::Rational, y::Integer ) = x.num <= widemul(x.den,y)
<=(x::Rational, y::Real ) = x.num <= x.den*y
<=(x::Integer , y::Rational) = widemul(x,y.den) <= y.num
<=(x::Real , y::Rational) = x*y.den <= y.num

div(x::Rational, y::Rational) = div(x.num*y.den, x.den*y.num)
Expand Down
2 changes: 1 addition & 1 deletion src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ static std::map<std::string, void*> libMap;

extern "C" int add_library_mapping(char *lib, void *hnd)
{
JL_PUTS((char*)"WARNING: add_library_mapping is deprecated, use push!(DL_LOAD_PATH,\"/path/to/search\") instead.\n", JL_STDERR);
JL_PUTS(const_cast<char*>("WARNING: add_library_mapping is deprecated, use push!(DL_LOAD_PATH,\"/path/to/search\") instead.\n"), JL_STDERR);
if (libMap[lib] == NULL && hnd != NULL) {
libMap[lib] = hnd;
return 0;
Expand Down
4 changes: 4 additions & 0 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1479,3 +1479,7 @@ end

# issue #3520 - certain int literals on 32-bit systems
@test -536870913 === -536870912-1

# overflow in rational comparison
@test 3//2 < typemax(Int)
@test 3//2 <= typemax(Int)

0 comments on commit d4c4d2a

Please sign in to comment.