Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion base/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1245,7 +1245,18 @@ end
function ^(x::Union{Float16,Float32}, n::Integer)
n == -2 && return (i=inv(x); i*i)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cases n == 0, n == 1and n == -1 perform unnecessary conversions (widen and recast).

n == 3 && return x*x*x #keep compatibility with literal_pow
n < 0 && return oftype(x, Base.power_by_squaring(inv(widen(x)),-n))
if n < 0
# It won't work to do `inv(x)^-n` if `n` and `-n` are both less than zero (e.g., if
# `n` is typemin).
if -n < 0
i = inv(widen(x))
y = Base.power_by_squaring(i, -fld(n, 2))
y = y * y
isodd(n) && (y = y * i)
return oftype(x, y)
end
return oftype(x, Base.power_by_squaring(inv(widen(x)),-n))
Comment on lines +1249 to +1258
Copy link
Contributor

@KlausC KlausC Apr 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not simply for all n < 0:

    i = inv(widen(x))
    return oftype(x, Base.power_by_squaring(i, -(n+1)) * i)

end
oftype(x, Base.power_by_squaring(widen(x),n))
end

Expand Down
27 changes: 27 additions & 0 deletions test/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1538,6 +1538,33 @@ end
@test all((t -> ===(t...)), zip(x^y, p[y + 1]))
end
end
# issue #57464
@test Float32(1.1)^typemin(Int) == Float32(0.0)
@test Float16(1.1)^typemin(Int) == Float16(0.0)
@test Float32(1.1)^unsigned(0) === Float32(1.0)
@test Float32(1.1)^big(0) === Float32(1.0)

# By using a limited-precision integer (3 bits) we can trigger issue 57464
# for a case where the answer isn't zero.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same is true, if you use for example Int8 or Int16. So why define Int3 ?

struct Int3 <: Integer
x::Int8
function Int3(x::Integer)
if x < -4 || x > 3
Core.throw_inexacterror(:Int3, Int3, x)
end
return new(x)
end
end
Base.typemin(::Type{Int3}) = Int3(-4)
Base.promote_rule(::Type{Int3}, ::Type{Int}) = Int
Base.convert(::Type{Int64}, x::Int3) = convert(Int64, x.x)
Base.:-(x::Int3) = x.x == -4 ? x : Int3(-x.x)
Base.trailing_zeros(x::Int3) = trailing_zeros(x.x)
Base.:>>(x::Int3, n::UInt64) = Int3(x.x>>n)

@test 1.001f0^-3 == 1.001f0^Int3(-3)
@test 1.001f0^-4 == 1.001f0^typemin(Int3)

end

# Test that sqrt behaves correctly and doesn't exhibit fp80 double rounding.
Expand Down