@@ -1261,6 +1261,10 @@ function modf(x::T) where T<:IEEEFloat
12611261 return (rx, ix)
12621262end
12631263
1264+ @inline function use_power_by_squaring (n:: Integer )
1265+ - 2 ^ 12 <= n <= 3 * 2 ^ 13
1266+ end
1267+
12641268# @constprop aggressive to help the compiler see the switch between the integer and float
12651269# variants for callers with constant `y`
12661270@constprop :aggressive function ^ (x:: Float64 , y:: Float64 )
@@ -1273,24 +1277,33 @@ end
12731277 y = sign (y)* 0x1 .8 p62
12741278 end
12751279 yint = unsafe_trunc (Int64, y) # This is actually safe since julia freezes the result
1276- y == yint && return @noinline x^ yint
1277- 2 * xu== 0 && return abs (y)* Inf * (! (y> 0 )) # if x==0
1278- x< 0 && throw_exp_domainerror (x) # |y| is small enough that y isn't an integer
1279- ! isfinite (x) && return x* (y> 0 || isnan (x)) # x is inf or NaN
1280+ yisint = y == yint
1281+ if yisint
1282+ yint == 0 && return 1.0
1283+ use_power_by_squaring (yint) && return @noinline pow_body (x, yint)
1284+ end
1285+ 2 * xu== 0 && return abs (y)* Inf * (! (y> 0 )) # if x === +0.0 or -0.0 (Inf * false === 0.0)
1286+ s = 1
1287+ if x < 0
1288+ ! yisint && throw_exp_domainerror (x) # y isn't an integer
1289+ s = ifelse (isodd (yint), - 1 , 1 )
1290+ end
1291+ ! isfinite (x) && return copysign (x,s)* (y> 0 || isnan (x)) # x is inf or NaN
1292+ return copysign (pow_body (abs (x), y), s)
1293+ end
1294+
1295+ @assume_effects :foldable @noinline function pow_body (x:: Float64 , y:: Float64 )
1296+ xu = reinterpret (UInt64, x)
12801297 if xu < (UInt64 (1 )<< 52 ) # x is subnormal
12811298 xu = reinterpret (UInt64, x * 0x1 p52) # normalize x
12821299 xu &= ~ sign_mask (Float64)
12831300 xu -= UInt64 (52 ) << 52 # mess with the exponent
12841301 end
1285- return pow_body (xu, y)
1286- end
1287-
1288- @inline function pow_body (xu:: UInt64 , y:: Float64 )
12891302 logxhi,logxlo = _log_ext (xu)
12901303 xyhi, xylo = two_mul (logxhi,y)
12911304 xylo = muladd (logxlo, y, xylo)
12921305 hi = xyhi+ xylo
1293- return Base. Math. exp_impl (hi, xylo- (hi- xyhi), Val (:ℯ ))
1306+ return @inline Base. Math. exp_impl (hi, xylo- (hi- xyhi), Val (:ℯ ))
12941307end
12951308
12961309@constprop :aggressive function ^ (x:: T , y:: T ) where T <: Union{Float16, Float32}
@@ -1314,12 +1327,29 @@ end
13141327 return T (exp2 (log2 (abs (widen (x))) * y))
13151328end
13161329
1317- # compensated power by squaring
13181330@constprop :aggressive @inline function ^ (x:: Float64 , n:: Integer )
1331+ x^ clamp (n, Int64)
1332+ end
1333+ @constprop :aggressive @inline function ^ (x:: Float64 , n:: Int64 )
13191334 n == 0 && return one (x)
1320- return pow_body (x, n)
1335+ if use_power_by_squaring (n)
1336+ return pow_body (x, n)
1337+ else
1338+ s = ifelse (x < 0 && isodd (n), - 1.0 , 1.0 )
1339+ x = abs (x)
1340+ y = float (n)
1341+ if y == n
1342+ return copysign (pow_body (x, y), s)
1343+ else
1344+ n2 = n % 1024
1345+ y = float (n - n2)
1346+ return pow_body (x, y) * copysign (pow_body (x, n2), s)
1347+ end
1348+ end
13211349end
13221350
1351+ # compensated power by squaring
1352+ # this method is only reliable for -2^20 < n < 2^20 (cf. #53881 #53886)
13231353@assume_effects :terminates_locally @noinline function pow_body (x:: Float64 , n:: Integer )
13241354 y = 1.0
13251355 xnlo = ynlo = 0.0
0 commit comments