Files
gonum/internal/cephes/zeta.go
Kent English a94452c8c8 Closes #32
2017-02-22 23:18:01 -05:00

146 lines
3.1 KiB
Go

// Copyright ©2016 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
* Cephes Math Library Release 2.1: January, 1989
* Copyright 1984, 1987, 1989 by Stephen L. Moshier
* Direct inquiries to 30 Frost Street, Cambridge, MA 02140
*/
package cephes
import "math"
/*
* Adapted from scipy's cephes zeta.c
*/
/*
* Riemann zeta function of two arguments
*
*
* DESCRIPTION:
*
* inf.
* - -x
* zeta(x,q) = > (k+q)
* -
* k=0
*
* where x > 1 and q is not a negative integer or zero.
* The Euler-Maclaurin summation formula is used to obtain
* the expansion
*
* n
* - -x
* zeta(x,q) = > (k+q)
* -
* k=1
*
* 1-x inf. B x(x+1)...(x+2j)
* (n+q) 1 - 2j
* + --------- - ------- + > --------------------
* x-1 x - x+2j+1
* 2(n+q) j=1 (2j)! (n+q)
*
* where the B2j are Bernoulli numbers. Note that (see zetac.c)
* zeta(x,1) = zetac(x) + 1.
*
*
* REFERENCE:
*
* Gradshteyn, I. S., and I. M. Ryzhik, Tables of Integrals,
* Series, and Products, p. 1073; Academic Press, 1980.
*
*/
/* Expansion coefficients
* for Euler-Maclaurin summation formula
* (2k)! / B2k
* where B2k are Bernoulli numbers
*/
var zetaCoefs = []float64{
12.0,
-720.0,
30240.0,
-1209600.0,
47900160.0,
-1.8924375803183791606e9, /*1.307674368e12/691 */
7.47242496e10,
-2.950130727918164224e12, /*1.067062284288e16/3617 */
1.1646782814350067249e14, /*5.109094217170944e18/43867 */
-4.5979787224074726105e15, /*8.028576626982912e20/174611 */
1.8152105401943546773e17, /*1.5511210043330985984e23/854513 */
-7.1661652561756670113e18, /*1.6938241367317436694528e27/236364091 */
}
// Zeta calculates the Riemann zeta function of two arguments
func Zeta(x, q float64) float64 {
if x == 1 {
return math.MaxFloat64
}
if x < 1 {
panic(paramOutOfBounds)
}
if q <= 0 {
if q == math.Floor(q) {
panic(badParamFunctionSingularity)
}
if x != math.Floor(x) {
panic(paramOutOfBounds) // because q^-x not defined
}
}
/* Asymptotic expansion
* http://dlmf.nist.gov/25.11#E43
*/
if q > 1e8 {
return (1/(x-1) + 1/(2*q)) * math.Pow(q, 1-x)
}
// Euler-Maclaurin summation formula
/* Permit negative q but continue sum until n+q > +9 .
* This case should be handled by a reflection formula.
* If q<0 and x is an integer, there is a relation to
* the polyGamma function.
*/
s := math.Pow(q, -x)
a := q
i := 0
b := 0.0
for i < 9 || a <= 9 {
i++
a += 1.0
b = math.Pow(a, -x)
s += b
if math.Abs(b/s) < machEp {
return s
}
}
w := a
s += b * w / (x - 1)
s -= 0.5 * b
a = 1.0
k := 0.0
for i = 0; i < 12; i++ {
a *= x + k
b /= w
t := a * b / zetaCoefs[i]
s = s + t
t = math.Abs(t / s)
if t < machEp {
return s
}
k += 1.0
a *= x + k
b /= w
k += 1.0
}
return s
}