From 0c1b5a07322cbfb59f0d7bc39f5cca58f350a03f Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Mon, 20 Aug 2018 12:08:26 +0200 Subject: [PATCH 1/2] make cmp with BigInt return in [-1, 0, 1] This is to adhere to the documentation. --- base/gmp.jl | 8 ++++---- test/bigint.jl | 13 +++++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index d80182646732e..4a7f6945e050d 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -487,13 +487,13 @@ count_ones_abs(x::BigInt) = iszero(x) ? 0 : MPZ.mpn_popcount(x) divrem(x::BigInt, y::BigInt) = MPZ.tdiv_qr(x, y) -cmp(x::BigInt, y::BigInt) = MPZ.cmp(x, y) -cmp(x::BigInt, y::ClongMax) = MPZ.cmp_si(x, y) -cmp(x::BigInt, y::CulongMax) = MPZ.cmp_ui(x, y) +cmp(x::BigInt, y::BigInt) = sign(MPZ.cmp(x, y)) +cmp(x::BigInt, y::ClongMax) = sign(MPZ.cmp_si(x, y)) +cmp(x::BigInt, y::CulongMax) = sign(MPZ.cmp_ui(x, y)) cmp(x::BigInt, y::Integer) = cmp(x, big(y)) cmp(x::Integer, y::BigInt) = -cmp(y, x) -cmp(x::BigInt, y::CdoubleMax) = isnan(y) ? -1 : MPZ.cmp_d(x, y) +cmp(x::BigInt, y::CdoubleMax) = isnan(y) ? -1 : sign(MPZ.cmp_d(x, y)) cmp(x::CdoubleMax, y::BigInt) = -cmp(y, x) isqrt(x::BigInt) = MPZ.sqrt(x) diff --git a/test/bigint.jl b/test/bigint.jl index 01acd5449b8c3..484bad8b32a28 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -401,3 +401,16 @@ end # Issue #24298 @test mod(BigInt(6), UInt(5)) == mod(6, 5) + +@testset "cmp has values in [-1, 0, 1], issue #28780" begin + bigrand() = rand(-big(2)^rand(1:rand(1:1000)):big(2)^rand(1:rand(1:1000))) + for T in (Base.BitInteger_types..., BigInt, Float64, Float32, Float16, BigFloat) + @test cmp(big(2)^130, one(T)) == 1 + @test cmp(-big(2)^130, one(T)) == -1 + T === BigInt && continue + @test cmp(big(2)^130, rand(T)) == 1 + @test cmp(-big(2)^130, rand(T)) == -1 + @test cmp(bigrand(), rand(T)) ∈ (-1, 0, 1) + end + @test cmp(bigrand(), bigrand()) ∈ (-1, 0, 1) +end From aa956778ad17777c3874d9492de61bb630a570db Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Tue, 21 Aug 2018 12:15:49 +0200 Subject: [PATCH 2/2] add more tests (Stefan) --- test/bigint.jl | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/test/bigint.jl b/test/bigint.jl index 484bad8b32a28..cd4c48f44873d 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -403,14 +403,25 @@ end @test mod(BigInt(6), UInt(5)) == mod(6, 5) @testset "cmp has values in [-1, 0, 1], issue #28780" begin - bigrand() = rand(-big(2)^rand(1:rand(1:1000)):big(2)^rand(1:rand(1:1000))) - for T in (Base.BitInteger_types..., BigInt, Float64, Float32, Float16, BigFloat) - @test cmp(big(2)^130, one(T)) == 1 - @test cmp(-big(2)^130, one(T)) == -1 - T === BigInt && continue - @test cmp(big(2)^130, rand(T)) == 1 - @test cmp(-big(2)^130, rand(T)) == -1 - @test cmp(bigrand(), rand(T)) ∈ (-1, 0, 1) + # _rand produces values whose log2 is better distributed than rand + _rand(::Type{BigInt}, n=1000) = let x = big(2)^rand(1:rand(1:n)) + rand(-x:x) end - @test cmp(bigrand(), bigrand()) ∈ (-1, 0, 1) + _rand(F::Type{<:AbstractFloat}) = F(_rand(BigInt, round(Int, log2(floatmax(F))))) + rand(F) + _rand(T) = rand(T) + for T in (Base.BitInteger_types..., BigInt, Float64, Float32, Float16) + @test cmp(big(2)^130, one(T)) === 1 + @test cmp(-big(2)^130, one(T)) === -1 + c = cmp(_rand(BigInt), _rand(T)) + @test c ∈ (-1, 0, 1) + @test c isa Int + (T <: Integer && T !== BigInt) || continue + x = rand(T) + @test cmp(big(2)^130, x) === cmp(x, -big(2)^130) === 1 + @test cmp(-big(2)^130, x) === cmp(x, big(2)^130) === -1 + @test cmp(big(x), x) === cmp(x, big(x)) === 0 + end + c = cmp(_rand(BigInt), _rand(BigInt)) + @test c ∈ (-1, 0, 1) + @test c isa Int end