Skip to content

Commit

Permalink
digits!: check for typemax only when applicable (#16844)
Browse files Browse the repository at this point in the history
  • Loading branch information
rfourquet committed Jul 15, 2017
1 parent 0b2774e commit a2f4a05
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 4 deletions.
4 changes: 3 additions & 1 deletion base/gmp.jl
Expand Up @@ -9,7 +9,7 @@ import Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor,
ndigits, promote_rule, rem, show, isqrt, string, powermod,
sum, trailing_zeros, trailing_ones, count_ones, base, tryparse_internal,
bin, oct, dec, hex, isequal, invmod, prevpow2, nextpow2, ndigits0zpb,
widen, signed, unsafe_trunc, trunc, iszero, big, flipsign, signbit
widen, signed, unsafe_trunc, trunc, iszero, big, flipsign, signbit, hastypemax

if Clong == Int32
const ClongMax = Union{Int8, Int16, Int32}
Expand Down Expand Up @@ -228,6 +228,8 @@ signed(x::BigInt) = x

convert(::Type{BigInt}, x::BigInt) = x

hastypemax(::Type{BigInt}) = false

function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, endpos::Int, base_::Integer, raise::Bool)
_n = Nullable{BigInt}()

Expand Down
2 changes: 2 additions & 0 deletions base/int.jl
Expand Up @@ -29,6 +29,8 @@ const BitIntegerSmall = Union{BitIntegerSmall_types...}
const BitSigned64T = Union{Type{Int8}, Type{Int16}, Type{Int32}, Type{Int64}}
const BitUnsigned64T = Union{Type{UInt8}, Type{UInt16}, Type{UInt32}, Type{UInt64}}

const BitIntegerType = Union{map(T->Type{T}, BitInteger_types)...}

throw_inexacterror(f::Symbol, ::Type{T}, val) where T =
(@_noinline_meta; throw(InexactError(f, T, val)))

Expand Down
11 changes: 10 additions & 1 deletion base/intfuncs.jl
Expand Up @@ -743,6 +743,14 @@ function digits(T::Type{<:Integer}, n::Integer, base::Integer=10, pad::Integer=1
digits!(zeros(T, ndigits(n, base, pad)), n, base)
end

"""
hastypemax(T::Type) -> Bool
Return `true` if and only if `typemax(T)` is defined.
"""
hastypemax(::Base.BitIntegerType) = true
hastypemax(::Type{T}) where {T} = applicable(typemax, T)

"""
digits!(array, n::Integer, base::Integer=10)
Expand Down Expand Up @@ -772,7 +780,8 @@ julia> digits!([2,2,2,2,2,2], 10, 2)
function digits!(a::AbstractVector{T}, n::Integer, base::Integer=10) where T<:Integer
base < 0 && isa(n, Unsigned) && return digits!(a, convert(Signed, n), base)
2 <= abs(base) || throw(ArgumentError("base must be ≥ 2 or ≤ -2, got $base"))
abs(base) - 1 <= typemax(T) || throw(ArgumentError("type $T too small for base $base"))
hastypemax(T) && abs(base) - 1 > typemax(T) &&
throw(ArgumentError("type $T too small for base $base"))
for i in eachindex(a)
if base > 0
a[i] = rem(n, base)
Expand Down
3 changes: 1 addition & 2 deletions base/random.jl
Expand Up @@ -28,8 +28,7 @@ mutable struct Close1Open2 <: FloatInterval end

## RandomDevice

const BitIntegerType = Union{map(T->Type{T}, Base.BitInteger_types)...}
const BoolBitIntegerType = Union{Type{Bool},BitIntegerType}
const BoolBitIntegerType = Union{Type{Bool},Base.BitIntegerType}
const BoolBitIntegerArray = Union{Array{Bool},Base.BitIntegerArray}

if Sys.iswindows()
Expand Down
3 changes: 3 additions & 0 deletions test/bigint.jl
Expand Up @@ -289,6 +289,9 @@ end

@test Base.ndigits0zpb(big(0), big(rand(2:100))) == 0

# digits with BigInt bases (#16844)
@test digits(big(2)^256, big(2)^128) == [0, 0, 1]

# conversion from float
@test BigInt(2.0) == BigInt(2.0f0) == BigInt(big(2.0)) == 2
@test_throws InexactError convert(BigInt, 2.1)
Expand Down

0 comments on commit a2f4a05

Please sign in to comment.