Skip to content

Commit 3222749

Browse files
authored
RFC: lower x^literal as x^Val{literal} for integer literals (#20530)
lower x^literal as x^Val{literal} for integer literals (closes #20527)
1 parent 7ab6428 commit 3222749

File tree

5 files changed

+30
-0
lines changed

5 files changed

+30
-0
lines changed

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ Language changes
7373
* The `typealias` keyword is deprecated, and should be replaced with
7474
`Vector{T} = Array{T,1}` or a `const` assignment.
7575
76+
* Experimental feature: `x^n` for integer literals `n` (e.g. `x^3`
77+
or `x^-3`) is now lowered to `x^Val{n}`, to enable compile-time
78+
specialization for literal integer exponents ([#20530]).
79+
7680
Breaking changes
7781
----------------
7882

base/intfuncs.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,11 @@ end
195195
^(x::Number, p::Integer) = power_by_squaring(x,p)
196196
^(x, p::Integer) = power_by_squaring(x,p)
197197

198+
# x^p for any literal integer p is lowered to x^Val{p},
199+
# to enable compile-time optimizations specialized to p.
200+
# However, we still need a fallback that calls the general ^:
201+
^{p}(x, ::Type{Val{p}}) = x^p
202+
198203
# b^p mod m
199204

200205
"""

base/promotion.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,11 @@ end
253253
254254
Exponentiation operator. If `x` is a matrix, computes matrix exponentiation.
255255
256+
If `y` is an `Int` literal (e.g. `2` in `x^2` or `-3` in `x^-3`), the Julia code
257+
`x^y` is transformed by the compiler to `x^Val{y}`, to enable compile-time
258+
specialization on the value of the exponent. (As a default fallback,
259+
however, `x^Val{y}` simply calls the `^(x,y)` function.)
260+
256261
```jldoctest
257262
julia> 3^5
258263
243

src/julia-syntax.scm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2057,6 +2057,10 @@
20572057
(expand-forms
20582058
`(call (core _apply) ,f ,@(tuple-wrap argl '())))))
20592059

2060+
((and (eq? f '^) (length= e 4) (integer? (cadddr e)))
2061+
(expand-forms
2062+
`(call ^ ,(caddr e) (call (core apply_type) (top Val) ,(cadddr e)))))
2063+
20602064
((and (eq? f '*) (length= e 4))
20612065
(expand-transposed-op
20622066
e

test/numbers.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2902,6 +2902,18 @@ end
29022902
@test rem2pi(T(-4), RoundUp) == -4
29032903
end
29042904

2905+
import Base.^
2906+
immutable PR20530; end
2907+
^(::PR20530, p::Int) = 1
2908+
^{p}(::PR20530, ::Type{Val{p}}) = 2
2909+
@testset "literal powers" begin
2910+
x = PR20530()
2911+
p = 2
2912+
@test x^p == 1
2913+
@test x^2 == 2
2914+
@test [x,x,x].^2 == [2,2,2]
2915+
end
2916+
29052917
@testset "iszero" begin
29062918
# Numeric scalars
29072919
for T in [Float16, Float32, Float64, BigFloat,

0 commit comments

Comments
 (0)