diff --git a/base/gmp.jl b/base/gmp.jl index d4d533ca9a91b..80d6055ca955f 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -363,7 +363,7 @@ function isqrt(x::BigInt) return z end -function ^(x::BigInt, y::UInt) +function ^(x::BigInt, y::Culong) z = BigInt() ccall((:__gmpz_pow_ui, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Culong), &z, &x, y) return z @@ -373,8 +373,20 @@ function bigint_pow(x::BigInt, y::Integer) if y<0; throw(DomainError()); end if x== 1; return x; end if x==-1; return isodd(y) ? x : -x; end - if y>typemax(UInt); throw(DomainError()); end - return x^uint(y) + if y>typemax(Culong) + x==0 && return x + + #At this point, x is not 1, 0 or -1 and it is not possible to use + #gmpz_pow_ui to compute the answer. Note that the magnitude of the + #answer is: + #- at least 2^(2^32-1) ≈ 10^(1.3e9) (if Culong === UInt32). + #- at least 2^(2^64-1) ≈ 10^(5.5e18) (if Culong === UInt64). + # + #Assume that the answer will definitely overflow. + + throw(OverflowError()) + end + return x^convert(Culong, y) end ^(x::BigInt , y::BigInt ) = bigint_pow(x, y) diff --git a/test/numbers.jl b/test/numbers.jl index 5cdb62675d9ce..0a98165cb8953 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2126,3 +2126,8 @@ end #Issue #5570 @test map(x -> int(mod1(uint(x),uint(5))), 0:15) == [5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5] +# Issue #9618: errors thrown by large exponentiations +@test_throws DomainError big(2)^-(big(typemax(UInt))+1) +@test_throws OverflowError big(2)^(big(typemax(UInt))+1) +@test 0==big(0)^(big(typemax(UInt))+1) +