Skip to content

Commit

Permalink
make @fastmath mirror how lowering applies literal_pow (#53819)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
KlausC and oscardssmith committed Apr 3, 2024
1 parent c749147 commit d7dc9a8
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
13 changes: 10 additions & 3 deletions base/fastmath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,12 @@ const rewrite_op =
function make_fastmath(expr::Expr)
if expr.head === :quote
return expr
elseif expr.head === :call && expr.args[1] === :^ && expr.args[3] isa Integer
# mimic Julia's literal_pow lowering of literal integer powers
return Expr(:call, :(Base.FastMath.pow_fast), make_fastmath(expr.args[2]), Val{expr.args[3]}())
elseif expr.head === :call && expr.args[1] === :^
ea = expr.args
if length(ea) >= 3 && isa(ea[3], Int)
# mimic Julia's literal_pow lowering of literal integer powers
return Expr(:call, :(Base.FastMath.pow_fast), make_fastmath(ea[2]), Val(ea[3]))
end
end
op = get(rewrite_op, expr.head, :nothing)
if op !== :nothing
Expand Down Expand Up @@ -364,6 +367,10 @@ for f in (:^, :atan, :hypot, :log)
# fall-back implementation that applies after promotion
$f_fast(x::T, y::T) where {T<:Number} = $f(x, y)
end
# Issue 53886 - avoid promotion of Int128 etc to be consistent with non-fastmath
if f === :^
@eval $f_fast(x::Number, y::Integer) = $f(x, y)
end
end

# Reductions
Expand Down
16 changes: 16 additions & 0 deletions test/fastmath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,22 @@ end

@testset "literal powers" begin
@test @fastmath(2^-2) == @fastmath(2.0^-2) == 0.25
# Issue #53817
# Note that exponent -2^63 fails testing because of issue #53881
# Therefore we test with -(2^63-1). For Int == Int32 there is an analogue restriction.
# See also PR #53860.
if Int == Int64
@test @fastmath(2^-9223372036854775807) === 0.0
@test_throws DomainError @fastmath(2^-9223372036854775809)
@test @fastmath(1^-9223372036854775807) isa Float64
@test @fastmath(1^-9223372036854775809) isa Int
elseif Int == Int32
@test @fastmath(2^-2147483647) === 0.0
@test_throws DomainError @fastmath(2^-2147483649)
@test @fastmath(1^-2147483647) isa Float64
@test @fastmath(1^-2147483649) isa Int
end
@test_throws MethodError @fastmath(^(2))
end

@testset "sincos fall-backs" begin
Expand Down

0 comments on commit d7dc9a8

Please sign in to comment.