mirror of
https://github.com/lcn2/calc.git
synced 2025-08-19 01:13:27 +03:00
50 lines
1.2 KiB
Plaintext
50 lines
1.2 KiB
Plaintext
/*
|
|
* Copyright (c) 1995 David I. Bell
|
|
* Permission is granted to use, distribute, or modify this source,
|
|
* provided that this copyright notice remains intact.
|
|
*
|
|
* 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));
|
|
}
|