<?xml version="1.0" encoding="windows-1252"?>
<node id="992798" title="Re^2: Computing pi to multiple precision" created="2012-09-10 12:36:59" updated="2012-09-10 12:36:59">
<type id="11">
note</type>
<author id="968231">
Athanasius</author>
<data>
<field name="doctext">
&lt;p&gt;I found a nice Perl 5 implementation of a spigot algorithm to generate pi at [href://http://rosettacode.org/wiki/Pi#Perl]. With a bit of tweaking, I was able to convert this code into a true spigot: a function which returns a further sequence of digits on each successive call:&lt;/p&gt;

&lt;readmore&gt;
&lt;code&gt;
#! perl
use strict;
use warnings;
use Math::BigInt try =&gt; 'GMP';
use bigint;

{
    local $| = 1;

    my  $digits   = int($ARGV[0] // 0) || 60;
    my ($len, $d) = rosetta();

    printf "pi = %s.%s", substr($d, 0, 1), substr($d, 1);

    for (my $count = $len; $count &lt; $digits; $count += $len)
    {
        ($len, $d) = rosetta();
         print $d;
    }

    print ";\n";

    reset_rosetta();
   ($len, $d) = rosetta();
    printf "pi = %s.%s", substr($d, 0, 1), substr($d, 1);
}

BEGIN
{
    my ($ds, $ns, $n5, $d5, $n2, $d2, $p2, $pow, $x);

    reset_rosetta();

    sub reset_rosetta
    {
        $ds  =          1;
        $ns  =          0;
        $n5  =      1_184;
        $d5  =        375;
        $n2  =    685_448;
        $d2  = 40_955_757;
        $p2  =          5;
        $pow =          1;
        $x   =          5;
    }

    sub rosetta
    {
        my $out;

        for (my $ppow = 1; $ppow == 1; $x += 4)
        {
            $ns  = ($ns * $d5) + ($n5 * $pow * $ds);
            $ds *=  $d5;
            $n5  =  16 * (25 * ($x + 2) - $x);
            next_term($d5, 5, $x);

            while ($d5 &gt; $d2)
            {
                $ns  = ($ns * $d2) - ($n2 * $pow * $ds);
                $ds *=  $d2;
                $n2  =  4 * (57_121 * ($p2 + 2) - $p2);
                next_term($d2, 239, $p2);
                $p2 +=  4;
            }

            my $product1 = $n5 * 625;
            my $product2 = $n2 * $n2 * 3_262_808_641;
               $ppow     = 1;

            while ($pow * $product1 &lt; $d5 &amp;&amp;
                   $pow * $product2 &lt; $d2)
            {
                $pow  *= 10;
                $ppow *= 10;
            }

            if ($ppow &gt; 1)
            {
                $ns *=  $ppow;
                $out =  $ns / $ds;
                $ns %=  $ds;
                $out = ('0' x (length($ppow) - length($out) - 1)) . $out;
            }

            if ($p2 % 20 == 1)
            {
                my $g = Math::BigInt::bgcd($ds, $ns);
                $ds  /= $g;
                $ns  /= $g;
            }
        }

        return (length $out, $out);
    }
}

sub next_term
{
    my ($coef, $p) = @_[1, 2];

    $_[0] /= ($p - 4) * ($p - 2);
    $_[0] *=  $p * ($p + 2) * $coef ** 4;
}
&lt;/code&gt;
&lt;/readmore&gt;

&lt;p&gt;Some advantages of this approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The output is in decimal.&lt;/li&gt;
&lt;li&gt;The output can be displayed progressively, so that, for a large number of digits, the user can &amp;lsquo;see&amp;rsquo; that progress is being made.&lt;/li&gt;
&lt;li&gt;With use of the GMP library, performance is surprisingly fast (10,000 digits in under a minute).&lt;/li&gt;
&lt;li&gt;Flexibility: the caller is free to display or otherwise use the data returned as required.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me emphasize, the code is not mine, I have only massaged it into a (hopefully) more useful form. Perhaps it will prove interesting or helpful to others exploring this topic.&lt;/p&gt;

&lt;!-- Node text goes above. Div tags should contain sig only --&gt;
&lt;div class="pmsig"&gt;&lt;div class="pmsig-968231"&gt;
&lt;p&gt;Athanasius&amp;emsp;&lt;font color=#008000&gt;&amp;lt;&amp;deg;(((&amp;gt;&amp;lt;&lt;/font&gt;&amp;emsp;&lt;i&gt;contra mundum&lt;/i&gt;&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;</field>
<field name="root_node">
992580</field>
<field name="parent_node">
992590</field>
</data>
</node>
