// Formula for calculating the Riemann Zeta function.
//
// This follows the very efficient algorithm set out by P. Borwein in
// "An Efficient Algorithm for the Riemann Zeta Function", Jan. 20, 1995.
//
// http://eprints.cecm.sfu.ca/archive/00000107/
//
// or
// https://vdoc.pub/download/an-efficient-algorithm-for-the-riemann-zeta-function-6p64dg2ligs0
//
// This implements Algorithm 2 of the paper.
//
// As noted by Borwein, "These algorithms do not compete with the
// Riemann-Siegel formula for computations concerning zeros on the critical
// line (Im[s] = 1/2) where multiple low precision evaluations are required."
//
// This means that it'll work around the critical line, but there are known
// faster algorithms if you just need low precision and only work around the
// critical line.
//
// This is the prototype of the (not-yet-implemented) Riemann Zeta function
// in Frink.
// Calculate the value of the Riemann Zeta function at s
// n is the approximate number of digits of accuracy. This automatically
// sets n to a minimum of 30 because the algorithm does not converge accurately
// with fewer terms.
RiemannZeta[s, n=30] :=
{
if n<30
n = 30
rnn = RiemannD[n]
sum = 0
for k = 0 to n-1
sum = sum + (-1)^k (rnn@k - rnn@n)/(k+1)^s
return sum * (-1/(rnn@n * (1 - 2^(1-s))))
}
// Calculate an array of values for d_0 ... d_n
// n is the approximate number of digits of precision in the result.
// This array should be stored and re-used across calculations.
RiemannD[n] :=
{
ret = new array[n+1]
sum = 0
for i = 0 to n
{
sum = sum + ((n+i-1)! 4^i)/((n-i)! (2i)!)
ret@i = n * sum
}
return ret
}