Files
calc/cal/pi.cal
Landon Curt Noll db77e29a23 convert ASCII TABs to ASCII SPACEs
Converted all ASCII tabs to ASCII spaces using a 8 character
tab stop, for all files, except for all Makefiles (plus rpm.mk).
The `git diff -w` reports no changes.
2024-07-11 22:03:52 -07:00

144 lines
4.4 KiB
Plaintext

/*
* pi - various routines to calculate pi
*
* Copyright (C) 1999-2004,2021 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.
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* 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 at seistrup dot 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);
}
}