# pi2.frink

``` /**  Program to calculate pi using binary splitting.      This version has been updated to be fastest with      Frink: The Next Generation.  Due to limitations in Java's BigDecimal      class, this is limited to a little over 101 million digits.      You usually use this by calling Pi.getPi[digits] which will return pi      to the number of digits you specify.  You can also call Pi.get2Pi[digits]      to return 2 pi.      See http://numbers.computation.free.fr/Constants/Algorithms/splitting.html      This differs from the basic pi algorithm because when you ask for more      digits of pi than you previously had, this *resumes* the calculation      rather than starting from scratch.  It also contains a resumable      sqrt to extend the results. */ class Pi {    class var digitsPerIteration = 14.1816474627254776555    class var largestDigits = -1    class var cachePi = undef    /** These variables help us resume the state of the binary-splitting        algorithm. */    class var largestP = 1    class var largestQ = 1    class var largestK = 0    class var largestG = 1    /** The current best estimate of sqrt */    class var sqrt640320 = 800.199975006248    /** Current working precision of sqrt in digits */    class var sqrtPrecision = 14    /** This is the main public method to get the value of pi to a certain        number of digits, calculating it if need be.  If pi has already been        calculated to a sufficient number of digits, this returns it from the        cache.    */    class getPi[digits = getPrecision[]] :=    {       origPrec = getPrecision[]       try       {          setPrecision[digits]          if (largestDigits >= digits)             return 1. * cachePi          else             return 1. * calcPi[digits]       }       finally          setPrecision[origPrec]    }    /** This is the main public method to get the value of 2 * pi to a certain        number of digits, calculating it if need be.  If pi has already been        calculated to a sufficient number of digits, this returns it from the        cache.    */    class get2Pi[digits = getPrecision[]] :=    {       origPrec = getPrecision[]       try       {          setPrecision[digits]          if (largestDigits != undef) and (largestDigits-1 >= digits)             return 2 * cachePi          else             return 2 * calcPi[digits]       }       finally          setPrecision[origPrec]    }          /** This is an internal method that calculates the digits of pi if        necessary. */    class calcPi[digits] :=    {       oldPrec = getPrecision[]       // Find number of terms to calculate       k = max[floor[digits/digitsPerIteration], 1]       try       {          setPrecision[digits+5]          // println["Calculating [\$largestK, \$k]"]          if (largestK < k)  // We may have already calculated enough!          {             if (largestK == 0)   // This is the first iteration             {                p = p[0,k]                q = q[0,k]                g = g[0,k]             } else             {                // Continuing iterations                pmb = p[largestK, k]                // p[a,b] = p[a,m] p[m,b]                p = largestP * pmb                // We need to cache g[0,largestK]                g = largestG * g[largestK, k]                                // We need a special rule here                // q[a,m] p[m,b] + q[m,b] g[a,m]                q = largestQ * pmb + q[largestK, k] * largestG             }             // Store the biggest values back in the cache             largestP = p             largestQ = q             largestG = g             largestK = k          }          // Do a resumable square root of 640320 (it may not need to do any          // more work)          sqC = sqrt640320[digits+8]          // At this point, largestP contains p and largestQ contains q          // for this number.          piprime = largestP * 53360. / (largestQ + 13591409 * largestP)          piFull = piprime * sqC          // Truncate to the desired number of digits          setPrecision[digits]          pi = 1. *  piFull          largestDigits = digits          cachePi = pi          return pi       }       finally          setPrecision[oldPrec]    }    /** Internal method for binary splitting. */    class q[a,b] :=    {       if (b-a) == 1          return (-1)^b * g[a,b] * (13591409 + 545140134 b)       m = (a+b) div 2       return q[a,m] p[m,b] + q[m,b] g[a,m]    }    /** Internal method for binary splitting. */    class p[a,b] :=    {       if (b-a) == 1          return 10939058860032000 b^3       m = (a+b) div 2       return p[a,m] p[m,b]    }    /** Internal method for binary splitting. */    class g[a,b] :=    {       if (b-a) == 1          return (6b-5)(2b-1)(6b-1)       m = (a+b) div 2       return g[a,m] g[m,b]    }    /** Resumable sqrt of 640320.  If we have already calculated sqrt        to the required number of digits, this will return quickly, otherwise,        it will resume the calculation efficiently and provide more digits. */    class sqrt640320[digits] :=    {       t = sqrt640320       // println["Resuming sqrt with precision \$sqrtPrecision"]       origPrecision = getPrecision[]       try       {          while (sqrtPrecision <= 2 * digits)          {             setPrecision[1 + 2 * sqrtPrecision]             t = (640320/t + t) / 2.             sqrtPrecision = sqrtPrecision * 2          }          // println["Bailing with next precision at \$sqrtPrecision"]          sqrt640320 = t          setPrecision[digits]          return 1. * sqrt640320       }       finally          setPrecision[origPrecision]    } } ```

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 was born 19092 days, 8 hours, 15 minutes ago.