/*
 * pi - various routines to calculate pi
 *
 * Copyright (C) 1999  David I. Bell
 *
 * Calc is open software; you can redistribute it and/or modify it under
 * the terms of the version 2.1 of the GNU Lesser General Public License
 * as published by the Free Software Foundation.
 *
 * Calc is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU Lesser General
 * Public License for more details.
 *
 * A copy of version 2.1 of the GNU Lesser General Public License is
 * distributed with calc under the filename COPYING-LGPL.  You should have
 * received a copy with calc; if not, write to Free Software Foundation, Inc.
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
 *
 * @(#) $Revision: 29.2 $
 * @(#) $Id: pi.cal,v 29.2 2000/06/07 14:02:25 chongo Exp $
 * @(#) $Source: /usr/local/src/cmd/calc/cal/RCS/pi.cal,v $
 *
 * Under source code control:	1991/05/22 21:56:37
 * File existed as early as:	1991
 *
 * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/
 */

/*
 * Calculate pi within the specified epsilon using the quartic convergence
 * iteration.
 */


define qpi(epsilon)
{
	local niter, yn, ym, tm, an, am, t, tn, sqrt2, epsilon2, count, digits;
	local bits, bits2;

	if (isnull(epsilon))
		epsilon = epsilon();
	digits = digits(1/epsilon);
	if	(digits <=  8) { niter = 1; epsilon =	1e-8; }
	else if (digits <= 40) { niter = 2; epsilon =  1e-40; }
	else if (digits <= 170) { niter = 3; epsilon = 1e-170; }
	else if (digits <= 693) { niter = 4; epsilon = 1e-693; }
	else {
		niter = 4;
		t = 693;
		while (t < digits) {
			++niter;
			t *= 4;
		}
	}
	epsilon2 = epsilon/(digits/10 + 1);
	digits = digits(1/epsilon2);
	sqrt2 = sqrt(2, epsilon2);
	bits = abs(ilog2(epsilon)) + 1;
	bits2 = abs(ilog2(epsilon2)) + 1;
	yn = sqrt2 - 1;
	an = 6 - 4 * sqrt2;
	tn = 2;
	for (count = 0; count < niter; count++) {
		ym = yn;
		am = an;
		tn *= 4;
		t = sqrt(sqrt(1-ym^4, epsilon2), epsilon2);
		yn = (1-t)/(1+t);
		an = (1+yn)^4*am-tn*yn*(1+yn+yn^2);
		yn = bround(yn, bits2);
		an = bround(an, bits2);
	}
	return (bround(1/an, bits));
}


/*
 * Print digits of PI forever, neatly formatted, using calc.
 *
 * Written by Klaus Alexander Seistrup <klaus@seistrup.dk>
 * on a dull Friday evening in November 1999.
 *
 * Inspired by an algorithm conceived by Lambert Meertens.
 *
 * See also the ABC Programmer's Handbook, by Geurts, Meertens & Pemberton,
 * published by Prentice-Hall (UK) Ltd., 1990.
 *
 */

define piforever()
{
	local k = 2;
	local a = 4;
	local b = 1;
	local a1 = 12;
	local b1 = 4;
	local a2, b2, p, q, d, d1;
	local stdout = files(1);
	local first = 1, row = -1, col = 0;

	while (1) {
		/*
		* Next approximation
		*/
		p = k * k;
		q = k + k++;

		a2 = a;
		b2 = b;

		a = a1;
		a1 = p * a2 + q * a1;
		b = b1;
		b1 = p * b2 + q * b1;

		/*
		* Print common digits
		*/
		d = a // b;
		d1 = a1 // b1;

		while (d == d1) {
			if (first) {
				printf("%d.", d);
				first = 0;
			} else {
				if (!(col % 50)) {
					printf("\n");
					col = 0;
					if (!(++row % 20)) {
						printf("\n");
						row = 0;
					}
				}
				printf("%d", d);
				if (!(++col % 10))
					printf(" ");
			}
			a = 10 * (a % b);
			a1 = 10 * (a1 % b1);
			d = a // b;
			d1 = a1 // b1;
		}
		fflush(stdout);
	}
}
