Skip to content

Commit

Permalink
fix powermod problems, add test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
stevengj committed Nov 14, 2013
1 parent ef40cd9 commit 96cf532
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 2 deletions.
2 changes: 1 addition & 1 deletion base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ function powermod(x::BigInt, p::BigInt, m::BigInt)
ccall((:__gmpz_powm, :libgmp), Void,
(Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}, Ptr{BigInt}),
&r, &x, &p, &m)
return r
return m < 0 && r > 0 ? r + m : r # choose sign conistent with mod(x^p, m)
end
powermod(x::BigInt, p::Integer, m::BigInt) = powermod(x, BigInt(p), m)
powermod(x::BigInt, p::Integer, m::Integer) = powermod(x, BigInt(p), BigInt(m))
Expand Down
4 changes: 3 additions & 1 deletion base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ end
# b^p mod m
function powermod{T}(b::Integer, p::Integer, m::T)
p < 0 && throw(DomainError())
p == 0 && return one(b)
p == 0 && return m == 0 ? throw(DivideError()) : m < 0 ?
(m == -1 ? zero(promote_type(typeof(b),typeof(m))) : one(b)+m) :
(m == 1 ? zero(promote_type(typeof(b),typeof(m))) : one(promote_type(typeof(b),typeof(m))))
b = oftype(m,mod(b,m))
t = prevpow2(p)
local r::T
Expand Down
8 changes: 8 additions & 0 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1524,3 +1524,11 @@ for i = -20:20, j = -20:20
@test gcdx(i,j) == gcdx(ib,jb)
@test d != 1 || invmod(i,j) == invmod(ib,jb)
end

# check powermod function against GMP
for i = -10:10, p = 0:5, m = -10:10
if m != 0
@test powermod(i,p,m) == powermod(i,p,big(m)) == powermod(big(i),big(p),big(m))
@test mod(i^p,m) == powermod(i,p,m) == mod(big(i)^p,big(m))
end
end

0 comments on commit 96cf532

Please sign in to comment.