|
11 | 11 |
|
12 | 12 | # sin_kernel and cos_kernel functions are only valid for |x| < pi/4 = 0.7854
|
13 | 13 | # translated from openlibm code: k_sin.c, k_cos.c, k_sinf.c, k_cosf.c.
|
| 14 | +# atan functions are based on openlibm code: s_atan.c, s_atanf.c. |
14 | 15 | # acos functions are based on openlibm code: e_acos.c, e_acosf.c.
|
15 | 16 | # asin functions are based on openlibm code: e_asin.c, e_asinf.c. The above
|
16 | 17 | # functions are made available under the following licence:
|
@@ -444,6 +445,108 @@ function asin(x::T) where T<:Union{Float32, Float64}
|
444 | 445 | end
|
445 | 446 | asin(x::Real) = asin(float(x))
|
446 | 447 |
|
| 448 | +# atan methods |
| 449 | +ATAN_1_O_2_HI(::Type{Float64}) = 4.63647609000806093515e-01 # atan(0.5).hi |
| 450 | +ATAN_2_O_2_HI(::Type{Float64}) = 7.85398163397448278999e-01 # atan(1.0).hi |
| 451 | +ATAN_3_O_2_HI(::Type{Float64}) = 9.82793723247329054082e-01 # atan(1.5).hi |
| 452 | +ATAN_INF_HI(::Type{Float64}) = 1.57079632679489655800e+00 # atan(Inf).hi |
| 453 | + |
| 454 | +ATAN_1_O_2_HI(::Type{Float32}) = 4.6364760399f-01 # atan(0.5).hi |
| 455 | +ATAN_2_O_2_HI(::Type{Float32}) = 7.8539812565f-01 # atan(1.0).hi |
| 456 | +ATAN_3_O_2_HI(::Type{Float32}) = 9.8279368877f-01 # atan(1.5).hi |
| 457 | +ATAN_INF_HI(::Type{Float32}) = 1.5707962513f+00 # atan(Inf).hi |
| 458 | + |
| 459 | +ATAN_1_O_2_LO(::Type{Float64}) = 2.26987774529616870924e-17 # atan(0.5).lo |
| 460 | +ATAN_2_O_2_LO(::Type{Float64}) = 3.06161699786838301793e-17 # atan(1.0).lo |
| 461 | +ATAN_3_O_2_LO(::Type{Float64}) = 1.39033110312309984516e-17 # atan(1.5).lo |
| 462 | +ATAN_INF_LO(::Type{Float64}) = 6.12323399573676603587e-17 # atan(Inf).lo |
| 463 | + |
| 464 | +ATAN_1_O_2_LO(::Type{Float32}) = 5.0121582440f-09 # atan(0.5).lo |
| 465 | +ATAN_2_O_2_LO(::Type{Float32}) = 3.7748947079f-08 # atan(1.0).lo |
| 466 | +ATAN_3_O_2_LO(::Type{Float32}) = 3.4473217170f-08 # atan(1.5).lo |
| 467 | +ATAN_INF_LO(::Type{Float32}) = 7.5497894159f-08 # atan(Inf).lo |
| 468 | + |
| 469 | +ATAN_LARGE_X(::Type{Float64}) = 2.0^66 # seems too large? 2.0^60 gives the same |
| 470 | +ATAN_SMALL_X(::Type{Float64}) = 2.0^-27 |
| 471 | +ATAN_LARGE_X(::Type{Float32}) = 2.0f0^26 |
| 472 | +ATAN_SMALL_X(::Type{Float32}) = 2.0f0^-12 |
| 473 | + |
| 474 | +atan_p(z::Float64, w::Float64) = z*@horner(w, |
| 475 | + 3.33333333333329318027e-01, |
| 476 | + 1.42857142725034663711e-01, |
| 477 | + 9.09088713343650656196e-02, |
| 478 | + 6.66107313738753120669e-02, |
| 479 | + 4.97687799461593236017e-02, |
| 480 | + 1.62858201153657823623e-02) |
| 481 | +atan_q(w::Float64) = w*@horner(w, |
| 482 | + -1.99999999998764832476e-01, |
| 483 | + -1.11111104054623557880e-01, |
| 484 | + -7.69187620504482999495e-02, |
| 485 | + -5.83357013379057348645e-02, |
| 486 | + -3.65315727442169155270e-02) |
| 487 | +atan_p(z::Float32, w::Float32) = z*@horner(w, 3.3333328366f-01, 1.4253635705f-01, 6.1687607318f-02) |
| 488 | +atan_q(w::Float32) = w*@horner(w, -1.9999158382f-01, -1.0648017377f-01) |
| 489 | +@inline function atan_pq(x) |
| 490 | + x² = x*x |
| 491 | + x⁴ = x²*x² |
| 492 | + # break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly |
| 493 | + atan_p(x², x⁴), atan_q(x⁴) |
| 494 | +end |
| 495 | +function atan(x::T) where T<:Union{Float32, Float64} |
| 496 | + # Method |
| 497 | + # 1. Reduce x to positive by atan(x) = -atan(-x). |
| 498 | + # 2. According to the integer k=4t+0.25 chopped, t=x, the argument |
| 499 | + # is further reduced to one of the following intervals and the |
| 500 | + # arctangent of t is evaluated by the corresponding formula: |
| 501 | + # |
| 502 | + # [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) |
| 503 | + # [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) |
| 504 | + # [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) |
| 505 | + # [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) |
| 506 | + # [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) |
| 507 | + # |
| 508 | + # If isnan(x) is true, then the nan value will eventually be passed to |
| 509 | + # atan_pq(x) and return the appropriate nan value. |
| 510 | + |
| 511 | + absx = abs(x) |
| 512 | + if absx >= ATAN_LARGE_X(T) |
| 513 | + return copysign(T(1.5707963267948966), x) |
| 514 | + end |
| 515 | + if absx < T(7/16) |
| 516 | + # no reduction needed |
| 517 | + if absx < ATAN_SMALL_X(T) |
| 518 | + return x |
| 519 | + end |
| 520 | + p, q = atan_pq(x) |
| 521 | + return x - x*(p + q) |
| 522 | + end |
| 523 | + xsign = sign(x) |
| 524 | + if absx < T(19/16) # 7/16 <= |x| < 19/16 |
| 525 | + if absx < T(11/16) # 7/16 <= |x| <11/16 |
| 526 | + hi = ATAN_1_O_2_HI(T) |
| 527 | + lo = ATAN_1_O_2_LO(T) |
| 528 | + x = (T(2.0)*absx - T(1.0))/(T(2.0) + absx) |
| 529 | + else # 11/16 <= |x| < 19/16 |
| 530 | + hi = ATAN_2_O_2_HI(T) |
| 531 | + lo = ATAN_2_O_2_LO(T) |
| 532 | + x = (absx - T(1.0))/(absx + T(1.0)) |
| 533 | + end |
| 534 | + else |
| 535 | + if absx < T(39/16) # 19/16 <= |x| < 39/16 |
| 536 | + hi = ATAN_3_O_2_HI(T) |
| 537 | + lo = ATAN_3_O_2_LO(T) |
| 538 | + x = (absx - T(1.5))/(T(1.0) + T(1.5)*absx) |
| 539 | + else # 39/16 <= |x| < upper threshold (2.0^66 or 2.0f0^26) |
| 540 | + hi = ATAN_INF_HI(T) |
| 541 | + lo = ATAN_INF_LO(T) |
| 542 | + x = -T(1.0)/absx |
| 543 | + end |
| 544 | + end |
| 545 | + # end of argument reduction |
| 546 | + p, q = atan_pq(x) |
| 547 | + z = hi - ((x*(p + q) - lo) - x) |
| 548 | + copysign(z, xsign) |
| 549 | +end |
447 | 550 | # atan2 methods
|
448 | 551 | ATAN2_PI_LO(::Type{Float32}) = -8.7422776573f-08
|
449 | 552 | ATAN2_RATIO_BIT_SHIFT(::Type{Float32}) = 23
|
|
0 commit comments