@@ -328,10 +328,6 @@ Stacktrace:
328
328
"""
329
329
log (b:: Number , x:: Number ) = log (promote (b,x)... )
330
330
331
- # type specific math functions
332
-
333
- const libm = Base. libm_name
334
-
335
331
# functions with no domain error
336
332
"""
337
333
sinh(x)
@@ -1149,148 +1145,7 @@ function modf(x::T) where T<:IEEEFloat
1149
1145
return (rx, ix)
1150
1146
end
1151
1147
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
1148
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
1233
-
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
1294
1149
1295
1150
# # rem2pi-related calculations ##
1296
1151
@@ -1305,19 +1160,6 @@ function add22condh(xh::Float64, xl::Float64, yh::Float64, yl::Float64)
1305
1160
return zh
1306
1161
end
1307
1162
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
-
1321
1163
"""
1322
1164
rem2pi(x, r::RoundingMode)
1323
1165
@@ -1350,135 +1192,6 @@ julia> rem2pi(7pi/4, RoundDown)
1350
1192
```
1351
1193
"""
1352
1194
function 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
1482
1195
1483
1196
"""
1484
1197
mod2pi(x)
@@ -1559,6 +1272,7 @@ include("special/hyperbolic.jl")
1559
1272
include (" special/trig.jl" )
1560
1273
include (" special/rem_pio2.jl" )
1561
1274
include (" special/log.jl" )
1275
+ include (" special/pow.jl" )
1562
1276
1563
1277
1564
1278
# Float16 definitions
0 commit comments