RiemannZeta.frink

Download or view RiemannZeta.frink in plain text format


/**
   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."

   Also see:
   "Numerical evaluation of the Riemann Zeta-function", Xavier Gourdon and
   Pascal Sebah
  http://numbers.computation.free.fr/Constants/Miscellaneous/zetaevaluations.pdf
  
   Also see: https://www.hpmuseum.org/cgi-bin/archv021.cgi?read=235199 which
   states: "It turns out that for 12 digits precision one needs about
   n=12-15. This is in accordance with n=1.3d+0.9t suggested by Gourdon and
   Sebah ("d" is the number of digits, "t" is the absolute value of the
   imaginary part of the argument)."  He, however, calculates an extra value
   in the loops of both RiemannD and RiemannZeta.
  
   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.
*/

class RiemannZeta
{
   // The last value of n we calculated for.
   class var lastN = -1

   // Contains d_k terms.  This is recalculated on demand by recalcRiemannD.
   class var d = new array
   
   // Calculate the value of the Riemann Zeta function at s
   // digits is the approximate number of digits of accuracy.
   class zeta[s, digits=getPrecision[]] :=
   {
      n = ceil[1.3 * digits + 0.9 abs[Im[s]]]
      
      sum = 0
      recalcRiemannD[n]
      
      dn = d@n
      //println["dn is $dn"]
      
      for k = 0 to n-1
      {
         dk = d@k
         sum = sum + (-1)^k (dk - dn)/(k+1)^s
      }

      return sum * (-1/(dn * (1 - 2^(1-s))))
   }

   // n is the approximate number of digits of precision in the result.
   class recalcRiemannD[n] :=
   {
      if n == lastN
         return
      
      sum = 0
      
      for i = 0 to n
      {
         sum = sum + ((n+i-1)! 4^i)/((n-i)! (2i)!)
         d@i = n sum
      }

      lastN = n
   }
}


Download or view RiemannZeta.frink in plain text format


This is a program written in the programming language Frink.
For more information, view the Frink Documentation or see More Sample Frink Programs.

Alan Eliasen, eliasen@mindspring.com