http://www.ballandclaw.com/upi/pi.txt

/****************************************/
/* Compute pi to arbitrary precision    */
/* Author Roy Williams February 1994    */
/* Uses Machin's formula...             */
/* pi/4 = 4 arctan(1/5) - arctan(1/239) */
/****************************************/
/* compile with cc -O -o pi pi.c        */
/* run as "pi 1000"                     */
/****************************************/
/* The last few digits may be wrong.......... */

#include <stdio.h>

#define BASE	10000
int nblock;
int *tot;
int *t1;
int *t2;
int *t3;

main(argc, argv)
int argc;
char **argv;
{
	int ndigit = 60;
	if(argc == 2)
		ndigit = atoi(argv[1]);
	else {
		fprintf(stderr, "Usage: %s ndigit\n", argv[0]);
		fprintf(stderr, "(Assuming 60 digits)\n");
	}
	if(ndigit < 20) ndigit = 20;
	nblock = ndigit/4;
	tot = (int *)malloc(nblock*sizeof(int));
	t1 = (int *)malloc(nblock*sizeof(int));
	t2 = (int *)malloc(nblock*sizeof(int));
	t3 = (int *)malloc(nblock*sizeof(int));
	if(!tot || !t1 || !t2 || !t3){
		fprintf(stderr, "Not enough memory\n");
		exit(1);
	}

	arctan(tot, t1, t2, 5, 1);
	mult(tot, 4);
	arctan(t3, t1, t2, 239, 2);
	sub(tot, t3);
	mult(tot, 4);
	print(tot);
}

arctan(result, w1, w2, denom, onestep)
int *result, *w1, *w2, denom, onestep;
{
	int denom2 = denom*denom;
	int k = 1;

	set(result, 1);
	div(result, denom);
	copy(w1, result);

	do{
		if(onestep)
			div(w1, denom2);
		else {
			div(w1, denom);
			div(w1, denom);
		}
		copy(w2, w1);
		div(w2, 2*k+1);
		if(k%2)
			sub(result, w2);
		else
			add(result, w2);
		k++;
	} while(!zero(w2));
}

copy(result, from)
int *result, *from;
{
	int i;
	for(i=0; i<nblock; i++)
		result[i] = from[i];
}

zero(result)
int *result;
{
	int i;
	for(i=0; i<nblock; i++)
		if(result[i])
			return 0;
	return 1;
}

add(result, increm)
int *result, *increm;
{
	int i;
	for(i=nblock-1; i>=0; i--){
		result[i] += increm[i];
		if(result[i] >= BASE){
			result[i] -= BASE;
			result[i-1]++;
		}
	}
}

sub(result, decrem)
int *result, *decrem;
{
	int i;
	for(i=nblock-1; i>=0; i--){
		result[i] -= decrem[i];
		if(result[i] < 0){
			result[i] += BASE;
			result[i-1]--;
		}
	}
}

mult(result, factor)
int *result, factor;
{
	int i, carry = 0;
	for(i=nblock-1; i>=0; i--){
		result[i] *= factor;
		result[i] += carry;
		carry = result[i]/BASE;
		result[i] %= BASE;
	}
}

div(result, denom)
int *result, denom;
{
	int i, carry = 0;

	for(i=0; i<nblock; i++){
		result[i] += carry*BASE;
		carry = result[i] % denom;
		result[i] /= denom;
	}
}

set(result, rhs)
int *result, rhs;
{
	int i;
	for(i=0; i<nblock; i++)
		result[i] = 0;
	result[0] = rhs;
}

print(result)
int *result;
{
	int i, k;
	char s[10];
	printf("%1d.\n", result[0]);
	for(i=1; i<nblock; i++){
		sprintf(s, "%4d ", result[i]);
		for(k=0; k<5; k++)
			if(s[k] == ' ') s[k] = '0';
		printf("%c%c%c%c", s[0], s[1], s[2], s[3]);
		if(i%15 == 0) printf("\n");
	}
	printf("\n");
}