Skip to content

Commit

Permalink
inline ^ for literal powers of numbers
Browse files Browse the repository at this point in the history
  • Loading branch information
stevengj committed Feb 16, 2017
1 parent 3222749 commit 701e28d
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 0 deletions.
4 changes: 4 additions & 0 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,10 @@ function ^(x::BigInt, y::Culong)
ccall((:__gmpz_pow_ui, :libgmp), Void, (Ptr{BigInt}, Ptr{BigInt}, Culong), &z, &x, y)
return z
end
@generated function ^{p}(x::BigInt, ::Type{Val{p}})
p < 0 && return :(inv(x)^p)
return :(x^p)
end

function bigint_pow(x::BigInt, y::Integer)
if y<0; throw(DomainError()); end
Expand Down
32 changes: 32 additions & 0 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,38 @@ end
# However, we still need a fallback that calls the general ^:
^{p}(x, ::Type{Val{p}}) = x^p

# for numbers, inline the power_by_squaring method for literal p.
# (this also allows integer^-p to give a floating-point result
# in a type-stable fashion).
@generated function ^{p}(x::Number, ::Type{Val{p}})
p == 0 && return :(one(x))
ex = Union{Expr,Symbol}[]
if p < 0
x_ = :x0
push!(ex, :(x0 = inv(x)))
p_ = -p
else
x_ = :x
p_ = p
end
y_ = 1
while p_ > 1
xp = gensym()
push!(ex, :($xp = $x_ * $x_))
if isodd(p_)
yp = gensym()
push!(ex, y_ === 1 ? :($yp = $x_) : :($yp = $x_ * $y_))
y_ = yp
end
x_ = xp
p_ >>= 1
end
push!(ex, y_ === 1 ? x_ : :($x_ * $y_))
return Expr(:block, ex...)
end
# we already have specialized ^ methods for floating-point types
^{p}(x::AbstractFloat, ::Type{Val{p}}) = x^p

# b^p mod m

"""
Expand Down
1 change: 1 addition & 0 deletions base/irrationals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ catalan
for T in (Irrational, Rational, Integer, Number)
^(::Irrational{:e}, x::T) = exp(x)
end
^{p}(::Irrational{:e}, ::Type{Val{p}}) = exp(p)

log(::Irrational{:e}) = 1 # use 1 to correctly promote expressions like log(x)/log(e)
log(::Irrational{:e}, x::Number) = log(x)
Expand Down

0 comments on commit 701e28d

Please sign in to comment.