From b31925cda1b25fbe486a07dd5b404e36fb1c5d11 Mon Sep 17 00:00:00 2001 From: Simon Byrne Date: Wed, 30 Sep 2015 10:19:45 +0100 Subject: [PATCH] add trunc methods to BigInt, fixes #13367 --- base/gmp.jl | 16 +++++++++++++--- test/bigint.jl | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index b6f67fec91b0c..de70240fa21ac 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -8,7 +8,7 @@ import Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), ($), binomial, cmp, convert, div, divrem, factorial, fld, gcd, gcdx, lcm, mod, ndigits, promote_rule, rem, show, isqrt, string, isprime, powermod, sum, trailing_zeros, trailing_ones, count_ones, base, tryparse_internal, - bin, oct, dec, hex, isequal, invmod, prevpow2, nextpow2, ndigits0z, widen, signed + bin, oct, dec, hex, isequal, invmod, prevpow2, nextpow2, ndigits0z, widen, signed, unsafe_trunc, trunc if Clong == Int32 typealias ClongMax Union{Int8, Int16, Int32} @@ -120,13 +120,23 @@ end convert(::Type{BigInt}, x::Bool) = BigInt(UInt(x)) -function convert(::Type{BigInt}, x::Float64) - !isinteger(x) && throw(InexactError()) + +function unsafe_trunc(::Type{BigInt}, x::CdoubleMax) z = BigInt() ccall((:__gmpz_set_d, :libgmp), Void, (Ptr{BigInt}, Cdouble), &z, x) return z end +function convert(::Type{BigInt}, x::CdoubleMax) + isinteger(x) || throw(InexactError()) + unsafe_trunc(BigInt,x) +end + +function trunc(::Type{BigInt}, x::CdoubleMax) + isfinite(x) || throw(InexactError()) + unsafe_trunc(BigInt,x) +end + convert(::Type{BigInt}, x::Float16) = BigInt(Float64(x)) convert(::Type{BigInt}, x::Float32) = BigInt(Float64(x)) diff --git a/test/bigint.jl b/test/bigint.jl index 50bb8bc3137e6..c2a11443c2d78 100644 --- a/test/bigint.jl +++ b/test/bigint.jl @@ -280,3 +280,19 @@ ndigits_mismatch(n) = ndigits(n) != ndigits(BigInt(n)) @test BigInt(2.0) == BigInt(2.0f0) == BigInt(big(2.0)) == 2 @test_throws InexactError convert(BigInt, 2.1) @test_throws InexactError convert(BigInt, big(2.1)) + +# issue #13367 +@test trunc(BigInt,2.1) == 2 +@test round(BigInt,2.1) == 2 +@test floor(BigInt,2.1) == 2 +@test ceil(BigInt,2.1) == 3 + +@test trunc(BigInt,2.1f0) == 2 +@test round(BigInt,2.1f0) == 2 +@test floor(BigInt,2.1f0) == 2 +@test ceil(BigInt,2.1f0) == 3 + +@test_throws InexactError trunc(BigInt,Inf) +@test_throws InexactError round(BigInt,Inf) +@test_throws InexactError floor(BigInt,Inf) +@test_throws InexactError ceil(BigInt,Inf)