Skip to content

Commit bebff47

Browse files
authored
fix type stability of powermod (#48367)
* type stability of powermod regressed in #48192
1 parent 532643d commit bebff47

File tree

2 files changed

+10
-6
lines changed

2 files changed

+10
-6
lines changed

base/intfuncs.jl

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -375,18 +375,20 @@ function powermod(x::Integer, p::Integer, m::T) where T<:Integer
375375
# but will work for integer types like `BigInt` that don't have `typemin` defined
376376
# It needs special handling otherwise will cause overflow problem.
377377
if p == -p
378-
t = powermod(invmod(x, m), -(p÷2), m)
379-
t = mod(widemul(t, t), m)
380-
iseven(p) && return t
378+
imod = invmod(x, m)
379+
rhalf = powermod(imod, -(p÷2), m)
380+
r::T = mod(widemul(rhalf, rhalf), m)
381+
isodd(p) && (r = mod(widemul(r, imod), m))
381382
#else odd
382-
return mod(widemul(t, invmod(x, m)), m)
383+
return r
384+
elseif p < 0
385+
return powermod(invmod(x, m), -p, m)
383386
end
384-
p < 0 && return powermod(invmod(x, m), -p, m)
385387
(m == 1 || m == -1) && return zero(m)
386388
b = oftype(m,mod(x,m)) # this also checks for divide by zero
387389

388390
t = prevpow(2, p)
389-
r::T = 1
391+
r = 1
390392
while true
391393
if p >= t
392394
r = mod(widemul(r,b),m)

test/intfuncs.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ end
273273

274274
@test powermod(2, big(3), 5) == 3
275275
@test powermod(2, big(3), -5) == -2
276+
@inferred powermod(2, -2, -5)
277+
@inferred powermod(big(2), -2, UInt(5))
276278
end
277279

278280
@testset "nextpow/prevpow" begin

0 commit comments

Comments
 (0)