From 0af01243781c99a3752ce52c593e2a3025bf2826 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Tue, 8 Oct 2024 15:25:00 +0200 Subject: [PATCH] fix `power_by_squaring`: use `promote` instead of type inference (#55634) Fixes #53504 Fixes #55633 --- base/intfuncs.jl | 6 +++++- test/math.jl | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 06a0213e7141c5..0421877a166235 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -298,7 +298,11 @@ function invmod(n::T) where {T<:BitInteger} end # ^ for any x supporting * -to_power_type(x) = convert(Base._return_type(*, Tuple{typeof(x), typeof(x)}), x) +function to_power_type(x::Number) + T = promote_type(typeof(x), typeof(one(x)), typeof(x*x)) + convert(T, x) +end +to_power_type(x) = oftype(x*x, x) @noinline throw_domerr_powbysq(::Any, p) = throw(DomainError(p, LazyString( "Cannot raise an integer x to a negative power ", p, ".", "\nConvert input to float."))) diff --git a/test/math.jl b/test/math.jl index c0a2d8bf8c9f8f..5a9f3248e59f4e 100644 --- a/test/math.jl +++ b/test/math.jl @@ -1498,6 +1498,28 @@ end n = Int64(1024 / log2(E)) @test E^n == Inf @test E^float(n) == Inf + + # #55633 + struct Issue55633_1 <: Number end + struct Issue55633_3 <: Number end + struct Issue55633_9 <: Number end + Base.one(::Issue55633_3) = Issue55633_1() + Base.:(*)(::Issue55633_3, ::Issue55633_3) = Issue55633_9() + Base.promote_rule(::Type{Issue55633_1}, ::Type{Issue55633_3}) = Int + Base.promote_rule(::Type{Issue55633_3}, ::Type{Issue55633_9}) = Int + Base.promote_rule(::Type{Issue55633_1}, ::Type{Issue55633_9}) = Int + Base.promote_rule(::Type{Issue55633_1}, ::Type{Int}) = Int + Base.promote_rule(::Type{Issue55633_3}, ::Type{Int}) = Int + Base.promote_rule(::Type{Issue55633_9}, ::Type{Int}) = Int + Base.convert(::Type{Int}, ::Issue55633_1) = 1 + Base.convert(::Type{Int}, ::Issue55633_3) = 3 + Base.convert(::Type{Int}, ::Issue55633_9) = 9 + for x ∈ (im, pi, Issue55633_3()) + p = promote(one(x), x, x*x) + for y ∈ 0:2 + @test all((t -> ===(t...)), zip(x^y, p[y + 1])) + end + end end # Test that sqrt behaves correctly and doesn't exhibit fp80 double rounding.