@@ -500,24 +500,38 @@ besselk_power_series(v, x::ComplexF32) = ComplexF32(besselk_power_series(v, Comp
500
500
501
501
function besselk_power_series (v, x:: ComplexOrReal{T} ) where T
502
502
Math. isnearint (v) && return besselk_power_series_int (v, x)
503
- MaxIter = 5000
504
- gam = gamma (v)
505
- ngam = π / (sinpi (- abs (v)) * gam * v)
506
-
507
- s1, s2 = zero (T), zero (T)
508
- t1, t2 = one (T), one (T)
509
-
510
- for k in 1 : MaxIter
511
- s1 += t1
512
- s2 += t2
513
- t1 *= x^ 2 / (4 k * (k - v))
514
- t2 *= x^ 2 / (4 k * (k + v))
515
- abs (t1) < eps (T) && break
503
+ MaxIter = 1000
504
+ S = eltype (x)
505
+ v, x = S (v), S (x)
506
+
507
+ z = x / 2
508
+ zz = z * z
509
+ logz = log (z)
510
+ xd2_v = exp (v* logz)
511
+ xd2_nv = inv (xd2_v)
512
+
513
+ # use the reflection identify to calculate gamma(-v)
514
+ # use relation gamma(v)*v = gamma(v+1) to avoid two gamma calls
515
+ gam_v = gamma (v)
516
+ gam_nv = π / (sinpi (- abs (v)) * gam_v * v)
517
+ gam_1mv = - gam_nv * v
518
+ gam_1mnv = gam_v * v
519
+
520
+ _t1 = gam_v * xd2_nv * gam_1mv
521
+ _t2 = gam_nv * xd2_v * gam_1mnv
522
+ (xd2_pow, fact_k, out) = (one (S), one (S), zero (S))
523
+ for k in 0 : MaxIter
524
+ t1 = xd2_pow * T (0.5 )
525
+ tmp = muladd (_t1, gam_1mnv, _t2 * gam_1mv)
526
+ tmp *= inv (gam_1mv * gam_1mnv * fact_k)
527
+ term = t1 * tmp
528
+ out += term
529
+ abs (term / out) < eps (T) && break
530
+ (gam_1mnv, gam_1mv) = (gam_1mnv* (one (S) + v + k), gam_1mv* (one (S) - v + k))
531
+ xd2_pow *= zz
532
+ fact_k *= k + one (S)
516
533
end
517
-
518
- xpv = (x/ 2 )^ v
519
- s = gam * s1 + xpv^ 2 * ngam * s2
520
- return s / (2 * xpv)
534
+ return out
521
535
end
522
536
besselk_power_series_cutoff (nu, x:: Float64 ) = x < 2.0 || nu > 1.6 x - 1.0
523
537
besselk_power_series_cutoff (nu, x:: Float32 ) = x < 10.0f0 || nu > 1.65f0 * x - 8.0f0
0 commit comments