@@ -328,10 +328,7 @@ Stacktrace:
328328"""
329329log (b:: Number , x:: Number ) = log (promote (b,x)... )
330330
331- # type specific math functions
332-
333331const libm = Base. libm_name
334-
335332# functions with no domain error
336333"""
337334 sinh(x)
@@ -1149,148 +1146,7 @@ function modf(x::T) where T<:IEEEFloat
11491146 return (rx, ix)
11501147end
11511148
1152- @inline function use_power_by_squaring (n:: Integer )
1153- - 2 ^ 12 <= n <= 3 * 2 ^ 13
1154- end
1155-
1156- # @constprop aggressive to help the compiler see the switch between the integer and float
1157- # variants for callers with constant `y`
1158- @constprop :aggressive function ^ (x:: Float64 , y:: Float64 )
1159- xu = reinterpret (UInt64, x)
1160- xu == reinterpret (UInt64, 1.0 ) && return 1.0
1161- # Exponents greater than this will always overflow or underflow.
1162- # Note that NaN can pass through this, but that will end up fine.
1163- if ! (abs (y)< 0x1 .8 p62)
1164- isnan (y) && return y
1165- y = sign (y)* 0x1 .8 p62
1166- end
1167- yint = unsafe_trunc (Int64, y) # This is actually safe since julia freezes the result
1168- yisint = y == yint
1169- if yisint
1170- yint == 0 && return 1.0
1171- use_power_by_squaring (yint) && return @noinline pow_body (x, yint)
1172- end
1173- 2 * xu== 0 && return abs (y)* Inf * (! (y> 0 )) # if x === +0.0 or -0.0 (Inf * false === 0.0)
1174- s = 1
1175- if x < 0
1176- ! yisint && throw_exp_domainerror (x) # y isn't an integer
1177- s = ifelse (isodd (yint), - 1 , 1 )
1178- end
1179- ! isfinite (x) && return copysign (x,s)* (y> 0 || isnan (x)) # x is inf or NaN
1180- return copysign (pow_body (abs (x), y), s)
1181- end
1182-
1183- @assume_effects :foldable @noinline function pow_body (x:: Float64 , y:: Float64 )
1184- xu = reinterpret (UInt64, x)
1185- if xu < (UInt64 (1 )<< 52 ) # x is subnormal
1186- xu = reinterpret (UInt64, x * 0x1 p52) # normalize x
1187- xu &= ~ sign_mask (Float64)
1188- xu -= UInt64 (52 ) << 52 # mess with the exponent
1189- end
1190- logxhi,logxlo = _log_ext (xu)
1191- xyhi, xylo = two_mul (logxhi,y)
1192- xylo = muladd (logxlo, y, xylo)
1193- hi = xyhi+ xylo
1194- return @inline Base. Math. exp_impl (hi, xylo- (hi- xyhi), Val (:ℯ ))
1195- end
1196-
1197- # @constprop aggressive to help the compiler see the switch between the integer and float
1198- # variants for callers with constant `y`
1199- @constprop :aggressive function ^ (x:: T , y:: T ) where T <: Union{Float16, Float32}
1200- x == 1 && return one (T)
1201- # Exponents greater than this will always overflow or underflow.
1202- # Note that NaN can pass through this, but that will end up fine.
1203- max_exp = T == Float16 ? T (3 << 14 ) : T (0x1 . Ap30)
1204- if ! (abs (y)< max_exp)
1205- isnan (y) && return y
1206- y = sign (y)* max_exp
1207- end
1208- yint = unsafe_trunc (Int32, y) # This is actually safe since julia freezes the result
1209- yisint = y == yint
1210- if yisint
1211- yint == 0 && return one (T)
1212- use_power_by_squaring (yint) && return pow_body (x, yint)
1213- end
1214- s = 1
1215- if x < 0
1216- ! yisint && throw_exp_domainerror (x) # y isn't an integer
1217- s = ifelse (isodd (yint), - 1 , 1 )
1218- end
1219- ! isfinite (x) && return copysign (x,s)* (y> 0 || isnan (x)) # x is inf or NaN
1220- return copysign (pow_body (abs (x), y), s)
1221- end
1222-
1223- @inline function pow_body (x:: T , y) where T <: Union{Float16, Float32}
1224- return T (exp2 (log2 (abs (widen (x))) * y))
1225- end
1226-
1227- @inline function pow_body (x:: Union{Float16, Float32} , n:: Int32 )
1228- n == - 2 && return (i= inv (x); i* i)
1229- n == 3 && return x* x* x # keep compatibility with literal_pow
1230- n < 0 && return oftype (x, Base. power_by_squaring (inv (widen (x)), - n))
1231- return oftype (x, Base. power_by_squaring (widen (x), n))
1232- end
12331149
1234- @constprop :aggressive @inline function ^ (x:: Float64 , n:: Integer )
1235- n = clamp (n, Int64)
1236- n == 0 && return one (x)
1237- if use_power_by_squaring (n)
1238- return pow_body (x, n)
1239- else
1240- s = ifelse (x < 0 && isodd (n), - 1.0 , 1.0 )
1241- x = abs (x)
1242- y = float (n)
1243- if y == n
1244- return copysign (pow_body (x, y), s)
1245- else
1246- n2 = n % 1024
1247- y = float (n - n2)
1248- return pow_body (x, y) * copysign (pow_body (x, n2), s)
1249- end
1250- end
1251- end
1252-
1253- # compensated power by squaring
1254- # this method is only reliable for -2^20 < n < 2^20 (cf. #53881 #53886)
1255- @assume_effects :terminates_locally @noinline function pow_body (x:: Float64 , n:: Integer )
1256- y = 1.0
1257- xnlo = - 0.0
1258- ynlo = 0.0
1259- n == 3 && return x* x* x # keep compatibility with literal_pow
1260- if n < 0
1261- rx = inv (x)
1262- n== - 2 && return rx* rx # keep compatibility with literal_pow
1263- isfinite (x) && (xnlo = - fma (x, rx, - 1. ) * rx)
1264- x = rx
1265- n = - n
1266- end
1267- while n > 1
1268- if n& 1 > 0
1269- err = muladd (y, xnlo, x* ynlo)
1270- y, ynlo = two_mul (x,y)
1271- ynlo += err
1272- end
1273- err = x* 2 * xnlo
1274- x, xnlo = two_mul (x, x)
1275- xnlo += err
1276- n >>>= 1
1277- end
1278- err = muladd (y, xnlo, x* ynlo)
1279- return ifelse (isfinite (x) & isfinite (err), muladd (x, y, err), x* y)
1280- end
1281-
1282- # @constprop aggressive to help the compiler see the switch between the integer and float
1283- # variants for callers with constant `y`
1284- @constprop :aggressive @inline function ^ (x:: T , n:: Integer ) where T <: Union{Float16, Float32}
1285- n = clamp (n, Int32)
1286- # Exponents greater than this will always overflow or underflow.
1287- # Note that NaN can pass through this, but that will end up fine.
1288- n == 0 && return one (x)
1289- use_power_by_squaring (n) && return pow_body (x, n)
1290- s = ifelse (x < 0 && isodd (n), - one (T), one (T))
1291- x = abs (x)
1292- return pow_body (x, widen (T)(n))
1293- end
12941150
12951151# # rem2pi-related calculations ##
12961152
@@ -1305,19 +1161,6 @@ function add22condh(xh::Float64, xl::Float64, yh::Float64, yl::Float64)
13051161 return zh
13061162end
13071163
1308- # multiples of pi/2, as double-double (ie with "tail")
1309- const pi1o2_h = 1.5707963267948966 # convert(Float64, pi * BigFloat(1/2))
1310- const pi1o2_l = 6.123233995736766e-17 # convert(Float64, pi * BigFloat(1/2) - pi1o2_h)
1311-
1312- const pi2o2_h = 3.141592653589793 # convert(Float64, pi * BigFloat(1))
1313- const pi2o2_l = 1.2246467991473532e-16 # convert(Float64, pi * BigFloat(1) - pi2o2_h)
1314-
1315- const pi3o2_h = 4.71238898038469 # convert(Float64, pi * BigFloat(3/2))
1316- const pi3o2_l = 1.8369701987210297e-16 # convert(Float64, pi * BigFloat(3/2) - pi3o2_h)
1317-
1318- const pi4o2_h = 6.283185307179586 # convert(Float64, pi * BigFloat(2))
1319- const pi4o2_l = 2.4492935982947064e-16 # convert(Float64, pi * BigFloat(2) - pi4o2_h)
1320-
13211164"""
13221165 rem2pi(x, r::RoundingMode)
13231166
@@ -1350,135 +1193,6 @@ julia> rem2pi(7pi/4, RoundDown)
13501193```
13511194"""
13521195function rem2pi end
1353- function rem2pi (x:: Float64 , :: RoundingMode{:Nearest} )
1354- isnan (x) && return x
1355- isinf (x) && return NaN
1356-
1357- abs (x) < pi && return x
1358-
1359- n,y = rem_pio2_kernel (x)
1360-
1361- if iseven (n)
1362- if n & 2 == 2 # n % 4 == 2: add/subtract pi
1363- if y. hi <= 0
1364- return add22condh (y. hi,y. lo,pi2o2_h,pi2o2_l)
1365- else
1366- return add22condh (y. hi,y. lo,- pi2o2_h,- pi2o2_l)
1367- end
1368- else # n % 4 == 0: add 0
1369- return y. hi+ y. lo
1370- end
1371- else
1372- if n & 2 == 2 # n % 4 == 3: subtract pi/2
1373- return add22condh (y. hi,y. lo,- pi1o2_h,- pi1o2_l)
1374- else # n % 4 == 1: add pi/2
1375- return add22condh (y. hi,y. lo,pi1o2_h,pi1o2_l)
1376- end
1377- end
1378- end
1379- function rem2pi (x:: Float64 , :: RoundingMode{:ToZero} )
1380- isnan (x) && return x
1381- isinf (x) && return NaN
1382-
1383- ax = abs (x)
1384- ax <= 2 * Float64 (pi ,RoundDown) && return x
1385-
1386- n,y = rem_pio2_kernel (ax)
1387-
1388- if iseven (n)
1389- if n & 2 == 2 # n % 4 == 2: add pi
1390- z = add22condh (y. hi,y. lo,pi2o2_h,pi2o2_l)
1391- else # n % 4 == 0: add 0 or 2pi
1392- if y. hi > 0
1393- z = y. hi+ y. lo
1394- else # negative: add 2pi
1395- z = add22condh (y. hi,y. lo,pi4o2_h,pi4o2_l)
1396- end
1397- end
1398- else
1399- if n & 2 == 2 # n % 4 == 3: add 3pi/2
1400- z = add22condh (y. hi,y. lo,pi3o2_h,pi3o2_l)
1401- else # n % 4 == 1: add pi/2
1402- z = add22condh (y. hi,y. lo,pi1o2_h,pi1o2_l)
1403- end
1404- end
1405- copysign (z,x)
1406- end
1407- function rem2pi (x:: Float64 , :: RoundingMode{:Down} )
1408- isnan (x) && return x
1409- isinf (x) && return NaN
1410-
1411- if x < pi4o2_h
1412- if x >= 0
1413- return x
1414- elseif x > - pi4o2_h
1415- return add22condh (x,0.0 ,pi4o2_h,pi4o2_l)
1416- end
1417- end
1418-
1419- n,y = rem_pio2_kernel (x)
1420-
1421- if iseven (n)
1422- if n & 2 == 2 # n % 4 == 2: add pi
1423- return add22condh (y. hi,y. lo,pi2o2_h,pi2o2_l)
1424- else # n % 4 == 0: add 0 or 2pi
1425- if y. hi > 0
1426- return y. hi+ y. lo
1427- else # negative: add 2pi
1428- return add22condh (y. hi,y. lo,pi4o2_h,pi4o2_l)
1429- end
1430- end
1431- else
1432- if n & 2 == 2 # n % 4 == 3: add 3pi/2
1433- return add22condh (y. hi,y. lo,pi3o2_h,pi3o2_l)
1434- else # n % 4 == 1: add pi/2
1435- return add22condh (y. hi,y. lo,pi1o2_h,pi1o2_l)
1436- end
1437- end
1438- end
1439- function rem2pi (x:: Float64 , :: RoundingMode{:Up} )
1440- isnan (x) && return x
1441- isinf (x) && return NaN
1442-
1443- if x > - pi4o2_h
1444- if x <= 0
1445- return x
1446- elseif x < pi4o2_h
1447- return add22condh (x,0.0 ,- pi4o2_h,- pi4o2_l)
1448- end
1449- end
1450-
1451- n,y = rem_pio2_kernel (x)
1452-
1453- if iseven (n)
1454- if n & 2 == 2 # n % 4 == 2: sub pi
1455- return add22condh (y. hi,y. lo,- pi2o2_h,- pi2o2_l)
1456- else # n % 4 == 0: sub 0 or 2pi
1457- if y. hi < 0
1458- return y. hi+ y. lo
1459- else # positive: sub 2pi
1460- return add22condh (y. hi,y. lo,- pi4o2_h,- pi4o2_l)
1461- end
1462- end
1463- else
1464- if n & 2 == 2 # n % 4 == 3: sub pi/2
1465- return add22condh (y. hi,y. lo,- pi1o2_h,- pi1o2_l)
1466- else # n % 4 == 1: sub 3pi/2
1467- return add22condh (y. hi,y. lo,- pi3o2_h,- pi3o2_l)
1468- end
1469- end
1470- end
1471-
1472- rem2pi (x:: Float32 , r:: RoundingMode ) = Float32 (rem2pi (Float64 (x), r))
1473- rem2pi (x:: Float16 , r:: RoundingMode ) = Float16 (rem2pi (Float64 (x), r))
1474- rem2pi (x:: Int32 , r:: RoundingMode ) = rem2pi (Float64 (x), r)
1475-
1476- # general fallback
1477- function rem2pi (x:: Integer , r:: RoundingMode )
1478- fx = float (x)
1479- fx == x || throw (ArgumentError (LazyString (typeof (x), " argument to rem2pi is too large: " , x)))
1480- rem2pi (fx, r)
1481- end
14821196
14831197"""
14841198 mod2pi(x)
@@ -1558,7 +1272,10 @@ include("special/exp.jl")
15581272include (" special/hyperbolic.jl" )
15591273include (" special/trig.jl" )
15601274include (" special/rem_pio2.jl" )
1275+ include (" special/rem2pi.jl" )
15611276include (" special/log.jl" )
1277+ include (" special/pow.jl" )
1278+
15621279
15631280
15641281# Float16 definitions
0 commit comments