

Ad piatan:

This C-program shows a possible implementation of arctan formulas.
It allows for coputing pi to some 100000 decimals on a
usual PC.

The program needs no high-precision library.  
Rather than it implements (and shows) a high-precision division 
via normal C-integer arithmetic.

 

Calling sequence:
-----------------

The program is called by

      piatan.exe [no_of_digits [formula]]
e.g:  piatan     20000 2


The first argument (optional) is the no of pi-digits that the program 
will compute. The upper limit depends on the compiler used. 
32 Bit-compilers allow theoretically for more than 2 billion digits 
but the arctan method is not suited for such large values; 
a practical upper limit is probably 200000.  
16 Bit compilers allow for up to 32760 digits.

The default value is 1001.

The second argument (optional) determines the arctan formula used.
The program contains a list (AtanTab) of 6 such formulas, 
enumerated from 0 to 5. No 0 is the good old Machin formula 
(pi/4 = 4arctan(1/5) - arctan(1/239), no 1 is the Euler formula and so on.
See the program listing for details.  

The default value is 0, i.e. Machin's formula.


 
Internal working
----------------

An arctan formula is the sum of two ore more sums of this kind:

       k\sum_{i=0}^\infty (-1)^{2i+1}/((2i+1)a^{2i+1})

The signs of the terms are alternatively + or -. The first term has the
sign of k.

The value of the first term is k/a. Each succeeding term will be computed
from the the preceding term by the 2 divisions thru a^2 and 2i+1. 
The sign alternates.

The program uses two arrays Result[] and S[]. The have same length and this
length is somewhat longer then the requested precision. 
Both arrays contain decimal fractions with the assumed decimalpoint after 
the first element. Every element is a word of type short of 4 decimals. 
For instance, if 1000 decimals must be computed then the lengths of both the 
arrays Result[] and S[] are (1000/4 = 250) +1+1 words. 
The first +1 is for the digit preceding the decimal point, 
the second +1 is to assure the requested precision.

The array Result[] is the container for the resulting pi. 
The terms of all (inner and outer) sums will there be added-in.

The array S[] is a temporary. It takes over the values of 
k/a^{2i+1}$, i.s. the positive terms before their division by
(2i+1).  

At the beginning of the computation of each inner sum the array S[] 
is set to k/a and added to the array Result[]. For every sum term, 
the array S[] will be divided by a^2; the result will be
saved to array S[]. 
Then, S[] will be alternatively divided by +(2i+1) or  
-(2i+1) and added to Result[].

Per term there are two divisions necessary. 
In all cases, the nominator is the long decimal number in S[];
but, in all cases, the denominator is a short number, namely either 
a^2 or +(2i+1) or -(2i+1). 
After each division by by a^2, the quotient will be saved into S[], 
whereas after each division by (2i+1) the quotient will be added 
to Result[]. The program therefore has two functions for these tasks: 
DivideAndStore() and DivideAndAdd().

When dividing by a^2 it must be taken care that the remainder does not
become greater than ULONG_MAX/10^4, otherwise it cannot be used
without loss of accuracy further on. In such cases of a, is must not be
divided by a^2 in one step rather than first by a and secondly by a again.

During the additions to Result[] there can occur over and 
underflows. They will be handeld this way: The words of array  
Result[] are large enough to take-over not only a 4 digit number
but also the sum or difference of two such numbers. 
(a short fits for the range from +19999$ to -9999). 
Therefore, one can perform all the additions into Result[] without
considering the carries.
Only after the addition of all words there must be done a pass over 
Result[] (from the right); from every word greater than 9999 or less than
0, the overflow or underflow must be carried into the preceding word. 
If, for instance, 3 adjacent words of Result[] happen to contain the
values 100, 15000 and -4000, then they must be transformed to 
101, 4999 and +6000 resp..     

A small trick to increase the performance is the variable 
imeat. It takes care that no unnecessary leading zeroes of the terms of
the sums will be used in computations.
These terms will obviously become ever smaller, thus they will get ever more
leading zeroes. imeat is then an index into array S[] to the leftmost word
that is not zero.

The remainder of the program is pure overhead, e.g. to read-in the user
arguments from the command line or to print-out the resulting digits of pi.

