Skip to content

Commit d7dc9a8

Browse files
KlausCoscardssmith
andauthored
make @fastmath mirror how lowering applies literal_pow (#53819)
The expressions `a^x` and `@fastmath a^x` are now producing equivalent results (apart from floating point accuracy) in the case of literal integer `x`. The logic in the `fastmath` macro, trying to mimic the behaviour of the compiler is fixed. Fixes #53817 --------- Co-authored-by: Oscar Smith <oscardssmith@gmail.com>
1 parent c749147 commit d7dc9a8

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

base/fastmath.jl

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,12 @@ const rewrite_op =
101101
function make_fastmath(expr::Expr)
102102
if expr.head === :quote
103103
return expr
104-
elseif expr.head === :call && expr.args[1] === :^ && expr.args[3] isa Integer
105-
# mimic Julia's literal_pow lowering of literal integer powers
106-
return Expr(:call, :(Base.FastMath.pow_fast), make_fastmath(expr.args[2]), Val{expr.args[3]}())
104+
elseif expr.head === :call && expr.args[1] === :^
105+
ea = expr.args
106+
if length(ea) >= 3 && isa(ea[3], Int)
107+
# mimic Julia's literal_pow lowering of literal integer powers
108+
return Expr(:call, :(Base.FastMath.pow_fast), make_fastmath(ea[2]), Val(ea[3]))
109+
end
107110
end
108111
op = get(rewrite_op, expr.head, :nothing)
109112
if op !== :nothing
@@ -364,6 +367,10 @@ for f in (:^, :atan, :hypot, :log)
364367
# fall-back implementation that applies after promotion
365368
$f_fast(x::T, y::T) where {T<:Number} = $f(x, y)
366369
end
370+
# Issue 53886 - avoid promotion of Int128 etc to be consistent with non-fastmath
371+
if f === :^
372+
@eval $f_fast(x::Number, y::Integer) = $f(x, y)
373+
end
367374
end
368375

369376
# Reductions

test/fastmath.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,22 @@ end
256256

257257
@testset "literal powers" begin
258258
@test @fastmath(2^-2) == @fastmath(2.0^-2) == 0.25
259+
# Issue #53817
260+
# Note that exponent -2^63 fails testing because of issue #53881
261+
# Therefore we test with -(2^63-1). For Int == Int32 there is an analogue restriction.
262+
# See also PR #53860.
263+
if Int == Int64
264+
@test @fastmath(2^-9223372036854775807) === 0.0
265+
@test_throws DomainError @fastmath(2^-9223372036854775809)
266+
@test @fastmath(1^-9223372036854775807) isa Float64
267+
@test @fastmath(1^-9223372036854775809) isa Int
268+
elseif Int == Int32
269+
@test @fastmath(2^-2147483647) === 0.0
270+
@test_throws DomainError @fastmath(2^-2147483649)
271+
@test @fastmath(1^-2147483647) isa Float64
272+
@test @fastmath(1^-2147483649) isa Int
273+
end
274+
@test_throws MethodError @fastmath(^(2))
259275
end
260276

261277
@testset "sincos fall-backs" begin

0 commit comments

Comments
 (0)