// various ways of calculating pi
// ultimately limited by the resolution of the double precision type
// use MIRACL or another equivalent library to fix that

#include <iostream>
#include <math.h>

main() {

	double current;
	double result = 1;

	cout.precision(16);
	cout.width(16);
	cout.setf(ios::fixed);

	// Continued Square Root approach
	
	current = sqrt(0.5);

	while(current < 1) {

		result = result * current;
		current = sqrt(0.5 + current/2);

		cout << 2/result << "\t" << result << "\t" << current << "\n";
	}
	
	cout << " ----------------------------------------------------------\n";
	cout << "\n";

	// Sine approach

	double initial = 1;
	
	double f = 3 * initial; // must be 3*x

	double sinf = 1;	// to prevent loop from falling through

	while (sinf > 0.0000000000000002 ) {
		
		sinf = sin(f);
		f = f + sinf;
		
		cout << f/initial << "\t" << f << "\t" << sinf << "\n";
	}

	cout << " ----------------------------------------------------------\n";
        cout << "\n";
	
	// extremely accurate approximation 
	// apparently correct to 10^-82 (D. Shanks 1982)

	double A = 0.5 * (1071 + (double)184*sqrt(34));
	double B = 0.5 * (1553 + (double)266*sqrt(34));
	double D = 0.5 * ( 627 + (double)442*sqrt( 2));
	double C =         429 + (double)304*sqrt( 2);
	
	double a = A + sqrt( (A*A)-1 );
	double b = B + sqrt( (B*B)-1 );
	double c = C + sqrt( (C*C)-1 );
	double d = D + sqrt( (D*D)-1 );

	double approx = 6/sqrt(3502) * log(2*a*b*c*d);

	cout << approx << "\n";

	cout << " ----------------------------------------------------------\n";
        cout << "\n";

	// each iteration of this gives 5x the number of digits of the previous
	// you can use this on the previous approximation to get pi with an
	// error of about 10^-400
	
	f = 3;
	double next_seq;

	for (int counter = 0; counter < 3; counter++) {
		
		next_seq = ( 2 * sin(f) - tan(f) ) / 3;

		cout << f << "\t" << next_seq << "\n";

		f += next_seq;
	}
	
}
