home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / perl-4.036.tar.gz / perl-4.036.tar / perl-4.036 / atarist / test / pi.pl < prev    next >
Text File  |  1993-02-08  |  4KB  |  175 lines

  1. # ---------------------------------------------------------------------------
  2. # pi.perl  computes pi (3.14...) about 5120 Digits
  3. #
  4. # W. Kebsch, July-1988  {uunet!mcvax}!unido!nixpbe!kebsch
  5.  
  6. $my_name = $0;
  7. $version = $my_name . "-1.2";
  8.  
  9. # some working parameter
  10.  
  11. $smax =  5120;          # max digits
  12. $lmax =     4;          # digits per one array element
  13. $hmax = 10000;          # one array element contains: 0..9999
  14. $smin = $lmax;          # min digits
  15. $mag  =     7;          # magic number
  16.  
  17. # subroutines
  18.  
  19. sub mul_tm              # multiply the tm array with a long value
  20. {
  21.     $cb = pop(@_);      # elements(array)
  22.     $x  = pop(@_);      # value
  23.  
  24.     $c = 0;
  25.     for($i = 1; $i <= $cb; $i++)
  26.     {
  27.     $z      = $tm[$i] * $x + $c;
  28.     $c      = int($z / $hmax);
  29.     $tm[$i] = $z - $c * $hmax;
  30.     }
  31. }
  32.  
  33. sub mul_pm              # multiply the pm array with a long value
  34. {
  35.     $cb = pop(@_);      # elements(array)
  36.     $x  = pop(@_);      # value
  37.  
  38.     $c = 0;
  39.     for($i = 1; $i <= $cb; $i++)
  40.     {
  41.     $z      = $pm[$i] * $x + $c;
  42.     $c      = int($z / $hmax);
  43.     $pm[$i] = $z - $c * $hmax;
  44.     }
  45. }
  46.  
  47. sub divide              # divide the tm array by a long value
  48. {
  49.     $cb = pop(@_);      # elements(array)
  50.     $x  = pop(@_);      # value
  51.  
  52.     $c = 0;
  53.     for($i = $cb; $i >= 1; $i--)
  54.     {
  55.     $z      = $tm[$i] + $c;
  56.     $q      = int($z / $x);
  57.     $tm[$i] = $q;
  58.     $c      = ($z - $q * $x) * $hmax;
  59.     }
  60. }
  61.  
  62. sub add                 # add tm array to pm array
  63. {
  64.     $cb = pop(@_);      # elements(array)
  65.  
  66.     $c = 0;
  67.     for($i = 1; $i <= $cb; $i++)
  68.     {
  69.     $z = $pm[$i] + $tm[$i] + $c;
  70.     if($z >= $hmax)
  71.     {
  72.         $pm[$i] = $z - $hmax;
  73.         $c      = 1;
  74.     }
  75.     else
  76.     {
  77.         $pm[$i] = $z;
  78.         $c      = 0;
  79.     }
  80.     }
  81. }
  82.  
  83. $m0 = 0; $m1 = 0; $m2 = 0;
  84.  
  85. sub check_xb            # reduce current no. of elements (speed up!)
  86. {
  87.     $cb = pop(@_);      # current no. of elements
  88.  
  89.     if(($pm[$cb] == $m0) && ($pm[$cb - 1] == $m1) && ($pm[$cb - 2] == $m2))
  90.     {
  91.     $cb--;
  92.     }
  93.     $m0 = $pm[$cb];
  94.     $m1 = $pm[$cb - 1];
  95.     $m2 = $pm[$cb - 2];
  96.     $cb;
  97. }
  98.  
  99. sub display             # show the result
  100. {
  101.     $cb = pop(@_);      # elements(array);
  102.  
  103.     printf("\n%3d.", $pm[$cb]);
  104.     $j = $mag - $lmax;
  105.     for($i = $cb - 1; $i >= $j; $i--)
  106.     {
  107.     printf(" %04d", $pm[$i]);
  108.     }
  109.     print "\n";
  110. }
  111.  
  112. sub the_job             # let's do the job
  113. {
  114.     $s = pop(@_);       # no. of digits
  115.  
  116.     $s  = int(($s + $lmax - 1) / $lmax) * $lmax;
  117.     $b  = int($s / $lmax) + $mag - $lmax;
  118.     $xb = $b;
  119.     $t  = int($s * 5 / 3);
  120.  
  121.     for($i = 1; $i <= $b; $i++)         # init arrays
  122.     {
  123.     $pm[$i] = 0;
  124.     $tm[$i] = 0;
  125.     }
  126.     $pm[$b - 1] = $hmax / 2;
  127.     $tm[$b - 1] = $hmax / 2;
  128.  
  129.     printf("digits:%5d, terms:%5d, elements:%5d\n", $s, $t, $b);
  130.     for($n = 1; $n <= $t; $n++)
  131.     {
  132.     printf("\r\t\t\t  term:%5d", $n);
  133.     if($n < 200)
  134.     {
  135.         do mul_tm((4 * ($n * $n - $n) + 1), $xb);
  136.     }
  137.     else
  138.     {
  139.         do mul_tm((2 * $n - 1), $xb);
  140.         do mul_tm((2 * $n - 1), $xb);
  141.     }
  142.     if($n < 100)
  143.     {
  144.         do divide(($n * (16 * $n + 8)), $xb);
  145.     }
  146.     else
  147.     {
  148.         do divide((8 * $n), $xb);
  149.         do divide((2 * $n + 1), $xb);
  150.     }
  151.     do add($xb);
  152.     if($xb > $mag)
  153.     {
  154.         $xb = do check_xb($xb);
  155.     }
  156.     }
  157.     do mul_pm(6, $b);
  158.     do display($b);
  159.     ($user,$sys,$cuser,$csys) = times;
  160.     printf("\n[u=%g  s=%g  cu=%g  cs=%g]\n",$user, $sys, $cuser, $csys);
  161. }
  162.  
  163. # main block ----------------------------------------------------------------
  164.  
  165. $no_of_args = $#ARGV + 1;
  166. print("$version, ");
  167. die("usage: $my_name <no. of digits>") unless($no_of_args == 1);
  168. $digits = int($ARGV[0]);
  169. die("no. of digits out of range [$smin\..$smax]")
  170.                 unless(($digits >= $smin) && ($digits <= $smax));
  171. do the_job($digits);
  172. exit 0;
  173.  
  174. # That's all ----------------------------------------------------------------
  175.