@@ -1173,6 +1173,8 @@ end
11731173 return @inline Base. Math. exp_impl (hi, xylo- (hi- xyhi), Val (:ℯ ))
11741174end
11751175
1176+ # @constprop aggressive to help the compiler see the switch between the integer and float
1177+ # variants for callers with constant `y`
11761178@constprop :aggressive function ^ (x:: T , y:: T ) where T <: Union{Float16, Float32}
11771179 x == 1 && return one (T)
11781180 # Exponents greater than this will always overflow or underflow.
@@ -1183,17 +1185,31 @@ end
11831185 y = sign (y)* max_exp
11841186 end
11851187 yint = unsafe_trunc (Int32, y) # This is actually safe since julia freezes the result
1186- y == yint && return x^ yint
1187- x < 0 && throw_exp_domainerror (x)
1188- ! isfinite (x) && return x* (y> 0 || isnan (x))
1189- x== 0 && return abs (y)* T (Inf )* (! (y> 0 ))
1190- return pow_body (x, y)
1188+ yisint = y == yint
1189+ if yisint
1190+ yint == 0 && return one (T)
1191+ use_power_by_squaring (yint) && return pow_body (x, yint)
1192+ end
1193+ s = 1
1194+ if x < 0
1195+ ! yisint && throw_exp_domainerror (x) # y isn't an integer
1196+ s = ifelse (isodd (yint), - 1 , 1 )
1197+ end
1198+ ! isfinite (x) && return copysign (x,s)* (y> 0 || isnan (x)) # x is inf or NaN
1199+ return copysign (pow_body (abs (x), y), s)
11911200end
11921201
1193- @inline function pow_body (x:: T , y:: T ) where T <: Union{Float16, Float32}
1202+ @inline function pow_body (x:: T , y) where T <: Union{Float16, Float32}
11941203 return T (exp2 (log2 (abs (widen (x))) * y))
11951204end
11961205
1206+ @inline function pow_body (x:: Union{Float16, Float32} , n:: Int32 )
1207+ n == - 2 && return (i= inv (x); i* i)
1208+ n == 3 && return x* x* x # keep compatibility with literal_pow
1209+ n < 0 && return oftype (x, Base. power_by_squaring (inv (widen (x)), - n))
1210+ return oftype (x, Base. power_by_squaring (widen (x), n))
1211+ end
1212+
11971213@constprop :aggressive @inline function ^ (x:: Float64 , n:: Integer )
11981214 n = clamp (n, Int64)
11991215 n == 0 && return one (x)
@@ -1242,11 +1258,17 @@ end
12421258 return ifelse (isfinite (x) & isfinite (err), muladd (x, y, err), x* y)
12431259end
12441260
1245- function ^ (x:: Union{Float16,Float32} , n:: Integer )
1246- n == - 2 && return (i= inv (x); i* i)
1247- n == 3 && return x* x* x # keep compatibility with literal_pow
1248- n < 0 && return oftype (x, Base. power_by_squaring (inv (widen (x)),- n))
1249- oftype (x, Base. power_by_squaring (widen (x),n))
1261+ # @constprop aggressive to help the compiler see the switch between the integer and float
1262+ # variants for callers with constant `y`
1263+ @constprop :aggressive @inline function ^ (x:: T , n:: Integer ) where T <: Union{Float16, Float32}
1264+ n = clamp (n, Int32)
1265+ # Exponents greater than this will always overflow or underflow.
1266+ # Note that NaN can pass through this, but that will end up fine.
1267+ n == 0 && return one (x)
1268+ use_power_by_squaring (n) && return pow_body (x, n)
1269+ s = ifelse (x < 0 && isodd (n), - one (T), one (T))
1270+ x = abs (x)
1271+ return pow_body (x, widen (T)(n))
12501272end
12511273
12521274# # rem2pi-related calculations ##
0 commit comments