1
1
# This file contains code that was formerly a part of Julia. License is MIT: http://julialang.org/license
2
2
3
- using Base. Math: signflip, f16, f32, f64
4
3
using Base. MPFR: ROUNDING_MODE, big_ln2
5
4
5
+ typealias ComplexOrReal{T} Union{T,Complex{T}}
6
+
6
7
# Bernoulli numbers B_{2k}, using tabulated numerators and denominators from
7
8
# the online encyclopedia of integer sequences. (They actually have data
8
9
# up to k=249, but we stop here at k=20.) Used for generating the polygamma
@@ -16,7 +17,7 @@ using Base.MPFR: ROUNDING_MODE, big_ln2
16
17
17
18
Compute the digamma function of `x` (the logarithmic derivative of `gamma(x)`).
18
19
"""
19
- function digamma (z:: Union {Float64,Complex{Float64} } )
20
+ function digamma (z:: ComplexOrReal {Float64} )
20
21
# Based on eq. (12), without looking at the accompanying source
21
22
# code, of: K. S. Kölbig, "Programs for computing the logarithm of
22
23
# the gamma function, and the digamma function, for complex
56
57
57
58
Compute the trigamma function of `x` (the logarithmic second derivative of `gamma(x)`).
58
59
"""
59
- function trigamma (z:: Union {Float64,Complex{Float64} } )
60
+ function trigamma (z:: ComplexOrReal {Float64} )
60
61
# via the derivative of the Kölbig digamma formulation
61
62
x = real (z)
62
63
if x <= 0 # reflection formula
@@ -79,6 +80,9 @@ function trigamma(z::Union{Float64,Complex{Float64}})
79
80
ψ += t* w * @evalpoly (w,0.16666666666666666 ,- 0.03333333333333333 ,0.023809523809523808 ,- 0.03333333333333333 ,0.07575757575757576 ,- 0.2531135531135531 ,1.1666666666666667 ,- 7.092156862745098 )
80
81
end
81
82
83
+ signflip (m:: Number , z) = (- 1 + 0im )^ m * z
84
+ signflip (m:: Integer , z) = iseven (m) ? z : - z
85
+
82
86
# (-1)^m d^m/dz^m cot(z) = p_m(cot z), where p_m is a polynomial
83
87
# that satisfies the recurrence p_{m+1}(x) = p_m′(x) * (1 + x^2).
84
88
# Note that p_m(x) has only even powers of x if m is odd, and
@@ -213,8 +217,7 @@ this definition is equivalent to the Hurwitz zeta function
213
217
``\\ sum_{k=0}^\\ infty (k+z)^{-s}``. For ``z=1``, it yields
214
218
the Riemann zeta function ``\\ zeta(s)``.
215
219
"""
216
- function zeta (s:: Union{Int,Float64,Complex{Float64}} ,
217
- z:: Union{Float64,Complex{Float64}} )
220
+ function zeta (s:: ComplexOrReal{Float64} , z:: ComplexOrReal{Float64} )
218
221
ζ = zero (promote_type (typeof (s), typeof (z)))
219
222
220
223
(z == 1 || z == 0 ) && return oftype (ζ, zeta (s))
@@ -263,7 +266,8 @@ function zeta(s::Union{Int,Float64,Complex{Float64}},
263
266
minus_z = - z
264
267
ζ += pow_oftype (ζ, minus_z, minus_s) # ν = 0 term
265
268
if xf != z
266
- ζ += pow_oftype (ζ, z - nx, minus_s) # real(z - nx) > 0, so use correct branch cut
269
+ ζ += pow_oftype (ζ, z - nx, minus_s)
270
+ # real(z - nx) > 0, so use correct branch cut
267
271
# otherwise, if xf==z, then the definition skips this term
268
272
end
269
273
# do loop in different order, depending on the sign of s,
@@ -316,10 +320,10 @@ end
316
320
"""
317
321
polygamma(m, x)
318
322
319
- Compute the polygamma function of order `m` of argument `x` (the `(m+1)th` derivative of the
323
+ Compute the polygamma function of order `m` of argument `x` (the `(m+1)`th derivative of the
320
324
logarithm of `gamma(x)`)
321
325
"""
322
- function polygamma (m:: Integer , z:: Union {Float64,Complex{Float64} } )
326
+ function polygamma (m:: Integer , z:: ComplexOrReal {Float64} )
323
327
m == 0 && return digamma (z)
324
328
m == 1 && return trigamma (z)
325
329
@@ -337,40 +341,25 @@ function polygamma(m::Integer, z::Union{Float64,Complex{Float64}})
337
341
# constants. We throw a DomainError() since the definition is unclear.
338
342
real (m) < 0 && throw (DomainError ())
339
343
340
- s = m+ 1
344
+ s = Float64 (m+ 1 )
345
+ # It is safe to convert any integer (including `BigInt`) to a float here
346
+ # as underflow occurs before precision issues.
341
347
if real (z) <= 0 # reflection formula
342
348
(zeta (s, 1 - z) + signflip (m, cotderiv (m,z))) * (- gamma (s))
343
349
else
344
350
signflip (m, zeta (s,z) * (- gamma (s)))
345
351
end
346
352
end
347
353
348
- # If we really cared about single precision, we could make a faster
349
- # Float32 version by truncating the Stirling series at a smaller cutoff.
350
- for (f,T) in ((:f32 ,Float32),(:f16 ,Float16))
351
- @eval begin
352
- zeta (s:: Integer , z:: Union{$T,Complex{$T}} ) = $ f (zeta (Int (s), f64 (z)))
353
- zeta (s:: Union{Float64,Complex128} , z:: Union{$T,Complex{$T}} ) = zeta (s, f64 (z))
354
- zeta (s:: Number , z:: Union{$T,Complex{$T}} ) = $ f (zeta (f64 (s), f64 (z)))
355
- polygamma (m:: Integer , z:: Union{$T,Complex{$T}} ) = $ f (polygamma (Int (m), f64 (z)))
356
- digamma (z:: Union{$T,Complex{$T}} ) = $ f (digamma (f64 (z)))
357
- trigamma (z:: Union{$T,Complex{$T}} ) = $ f (trigamma (f64 (z)))
358
- end
359
- end
360
-
361
- zeta (s:: Integer , z:: Number ) = zeta (Int (s), f64 (z))
362
- zeta (s:: Number , z:: Number ) = zeta (f64 (s), f64 (z))
363
- for f in (:digamma , :trigamma )
364
- @eval begin
365
- $ f (z:: Number ) = $ f (f64 (z))
366
- end
367
- end
368
- polygamma (m:: Integer , z:: Number ) = polygamma (m, f64 (z))
354
+ """
355
+ invdigamma(x)
369
356
370
- # Inverse digamma function:
371
- # Implementation of fixed point algorithm described in
372
- # "Estimating a Dirichlet distribution" by Thomas P. Minka, 2000
357
+ Compute the inverse [`digamma`](@ref) function of `x`.
358
+ """
373
359
function invdigamma (y:: Float64 )
360
+ # Implementation of fixed point algorithm described in
361
+ # "Estimating a Dirichlet distribution" by Thomas P. Minka, 2000
362
+
374
363
# Closed form initial estimates
375
364
if y >= - 2.22
376
365
x_old = exp (y) + 0.5
@@ -392,18 +381,16 @@ function invdigamma(y::Float64)
392
381
393
382
return x_new
394
383
end
395
- invdigamma (x:: Float32 ) = Float32 (invdigamma (Float64 (x)))
396
384
397
385
"""
398
- invdigamma(x )
386
+ zeta(s )
399
387
400
- Compute the inverse [`digamma`](@ref) function of `x `.
388
+ Riemann zeta function `` \\ zeta(s)` `.
401
389
"""
402
- invdigamma (x:: Real ) = invdigamma (Float64 (x))
390
+ function zeta (s:: ComplexOrReal{Float64} )
391
+ # Riemann zeta function; algorithm is based on specializing the Hurwitz
392
+ # zeta function above for z==1.
403
393
404
- # Riemann zeta function; algorithm is based on specializing the Hurwitz
405
- # zeta function above for z==1.
406
- function zeta (s:: Union{Float64,Complex{Float64}} )
407
394
# blows up to ±Inf, but get correct sign of imaginary zero
408
395
s == 1 && return NaN + zero (s) * imag (s)
409
396
@@ -448,23 +435,18 @@ function zeta(s::Union{Float64,Complex{Float64}})
448
435
return ζ
449
436
end
450
437
451
- zeta (x:: Integer ) = zeta (Float64 (x))
452
- zeta (x:: Real ) = oftype (float (x),zeta (Float64 (x)))
453
-
454
- """
455
- zeta(s)
456
-
457
- Riemann zeta function ``\\ zeta(s)``.
458
- """
459
- zeta (z:: Complex ) = oftype (float (z),zeta (Complex128 (z)))
460
-
461
438
function zeta (x:: BigFloat )
462
439
z = BigFloat ()
463
440
ccall ((:mpfr_zeta , :libmpfr ), Int32, (Ptr{BigFloat}, Ptr{BigFloat}, Int32), & z, & x, ROUNDING_MODE[])
464
441
return z
465
442
end
466
443
467
- function eta (z:: Union{Float64,Complex{Float64}} )
444
+ """
445
+ eta(x)
446
+
447
+ Dirichlet eta function ``\\ eta(s) = \\ sum^\\ infty_{n=1}(-1)^{n-1}/n^{s}``.
448
+ """
449
+ function eta (z:: ComplexOrReal{Float64} )
468
450
δz = 1 - z
469
451
if abs (real (δz)) + abs (imag (δz)) < 7e-3 # Taylor expand around z==1
470
452
return 0.6931471805599453094172321214581765 *
@@ -478,17 +460,82 @@ function eta(z::Union{Float64,Complex{Float64}})
478
460
return - zeta (z) * expm1 (0.6931471805599453094172321214581765 * δz)
479
461
end
480
462
end
481
- eta (x:: Integer ) = eta (Float64 (x))
482
- eta (x:: Real ) = oftype (float (x),eta (Float64 (x)))
483
-
484
- """
485
- eta(x)
486
-
487
- Dirichlet eta function ``\\ eta(s) = \\ sum^\\ infty_{n=1}(-1)^{n-1}/n^{s}``.
488
- """
489
- eta (z:: Complex ) = oftype (float (z),eta (Complex128 (z)))
490
463
491
464
function eta (x:: BigFloat )
492
465
x == 1 && return big_ln2 ()
493
466
return - zeta (x) * expm1 (big_ln2 ()* (1 - x))
494
467
end
468
+
469
+ # Converting types that we can convert, and not ones we can not
470
+ # Float16, and Float32 and their Complex equivalents can be converted to Float64
471
+ # and results converted back.
472
+ # Otherwise, we need to make things use their own `float` converting methods
473
+ # and in those cases, we do not convert back either as we assume
474
+ # they also implement their own versions of the functions, with the correct return types.
475
+ # This is the case for BitIntegers (which become `Float64` when `float`ed).
476
+ # Otherwise, if they do not implement their version of the functions we
477
+ # manually throw a `MethodError`.
478
+ # This case occurs, when calling `float` on a type does not change its type,
479
+ # as it is already a `float`, and would have hit own method, if one had existed.
480
+
481
+
482
+ # If we really cared about single precision, we could make a faster
483
+ # Float32 version by truncating the Stirling series at a smaller cutoff.
484
+ # and if we really cared about half precision, we could make a faster
485
+ # Float16 version, by using a precomputed table look-up.
486
+
487
+
488
+ for T in (Float16, Float32, Float64)
489
+ @eval f64 (x:: Complex{$T} ) = Complex128 (x)
490
+ @eval f64 (x:: $T ) = Float64 (x)
491
+ end
492
+
493
+
494
+ for f in (:digamma , :trigamma , :zeta , :eta , :invdigamma )
495
+ @eval begin
496
+ function $f (z:: Union{ComplexOrReal{Float16}, ComplexOrReal{Float32}} )
497
+ oftype (z, $ f (f64 (z)))
498
+ end
499
+
500
+ function $f (z:: Number )
501
+ x = float (z)
502
+ typeof (x) === typeof (z) && throw (MethodError ($ f, (z,)))
503
+ # There is nothing to fallback to, as this didn't change the argument types
504
+ $ f (x)
505
+ end
506
+ end
507
+ end
508
+
509
+
510
+ for T1 in (Float16, Float32, Float64), T2 in (Float16, Float32, Float64)
511
+ (T1 == T2 == Float64) && continue # Avoid redefining base definition
512
+
513
+ @eval function zeta (s:: ComplexOrReal{$T1} , z:: ComplexOrReal{$T2} )
514
+ ζ = zeta (f64 (s), f64 (z))
515
+ convert (promote_type (typeof (s), typeof (z)), ζ)
516
+ end
517
+ end
518
+
519
+
520
+ function zeta (s:: Number , z:: Number )
521
+ t = float (s)
522
+ x = float (z)
523
+ if typeof (t) === typeof (s) && typeof (x) === typeof (z)
524
+ # There is nothing to fallback to, since this didn't work
525
+ throw (MethodError (zeta,(s,z)))
526
+ end
527
+ zeta (t, x)
528
+ end
529
+
530
+
531
+ function polygamma (m:: Integer , z:: Union{ComplexOrReal{Float16}, ComplexOrReal{Float32}} )
532
+ oftype (z, polygamma (m, f64 (z)))
533
+ end
534
+
535
+
536
+ function polygamma (m:: Integer , z:: Number )
537
+ x = float (z)
538
+ typeof (x) === typeof (z) && throw (MethodError (polygamma, (m,z)))
539
+ # There is nothing to fallback to, since this didn't work
540
+ polygamma (m, x)
541
+ end
0 commit comments