[libmath-prime-util-perl] 02/16: Accuracy for math functions
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:44:33 UTC 2015
This is an automated email from the git hooks/post-receive script.
ppm-guest pushed a commit to annotated tag v0.08
in repository libmath-prime-util-perl.
commit fd61c4c7f6f06c4d37ac263952e2f32da5c5364a
Author: Dana Jacobsen <dana at acm.org>
Date: Mon Jun 18 16:54:19 2012 -0600
Accuracy for math functions
---
Changes | 1 +
TODO | 2 --
lib/Math/Prime/Util.pm | 10 ++++++++++
util.c | 21 +++++++++++----------
4 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/Changes b/Changes
index aa4f9da..2eeaf46 100644
--- a/Changes
+++ b/Changes
@@ -2,6 +2,7 @@ Revision history for Perl extension Math::Prime::Util.
0.08 20 June 2012
- Added thread scaffolding.
+ - Accuracy improvement and measurements for math functions.
0.07 17 June 2012
- Fixed a bug in next_prime found by Lou Godio (thank you VERY much!).
diff --git a/TODO b/TODO
index 303f8c6..93c3a6a 100644
--- a/TODO
+++ b/TODO
@@ -37,5 +37,3 @@
- Iterator or tie?
- Get rid of erat_simple and bitarray.h. They're only there for comparison.
-
-- Need to be more aware of precision for the math operations.
diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm
index e225335..fa0c2c6 100644
--- a/lib/Math/Prime/Util.pm
+++ b/lib/Math/Prime/Util.pm
@@ -672,6 +672,9 @@ is calculated using continued fractions (negative C<x>), a convergent series
(small positive C<x>), or an asymptotic divergent series (large positive C<x>).
This function only considers the real part.
+Accuracy is typically 15 digits unless between C<-.1> and C<0>, where
+accuracy is degraded.
+
=head2 LogarithmicIntegral
my $li = LogarithmicIntegral($x)
@@ -688,6 +691,11 @@ may be defined as C<Li(x) = li(x) - li(2)>.
This function is implemented as C<li(x) = Ei(ln x)> after handling special
values.
+Accuracy is typically 15 digits unless between C<0.9> and C<1>, where
+accuracy is degraded. These are not typically values one would use for
+prime number functionality, so should have little impact.
+
+
=head2 RiemannR
my $r = RiemannR($x);
@@ -696,6 +704,8 @@ Given a positive non-zero floating point input, returns the floating
point value of Riemann's R function. Riemann's R function gives a very close
approximation to the prime counting function.
+Accuracy should be at least 14 digits.
+
=head1 LIMITATIONS
diff --git a/util.c b/util.c
index 30c4c8d..8e49e1b 100644
--- a/util.c
+++ b/util.c
@@ -806,7 +806,7 @@ static double const euler_mascheroni = 0.577215664901532860606512090082402431042
static double const li2 = 1.045163780117492784844588889194613136522615578151;
double ExponentialIntegral(double x) {
- double const tol = 0.0000000001;
+ double const tol = 1e-16;
double val, term, fact_n;
double y, t;
double sum = 0.0;
@@ -817,11 +817,12 @@ double ExponentialIntegral(double x) {
if (x < 0) {
/* continued fraction */
+ /* This loses accuracy very quickly below -0.001 or so */
double old;
double lc = 0;
double ld = 1 / (1 - x);
val = ld * (-exp(x));
- for (n = 1; n <= 2000; n++) {
+ for (n = 1; n <= 100000; n++) {
lc = 1 / (2*n + 1 - x - n*n*lc);
ld = 1 / (2*n + 1 - x - n*n*ld);
old = val;
@@ -836,7 +837,7 @@ double ExponentialIntegral(double x) {
y = euler_mascheroni-c; t = sum+y; c = (t-sum)-y; sum = t;
y = log(x)-c; t = sum+y; c = (t-sum)-y; sum = t;
- for (n = 1; n <= 100; n++) {
+ for (n = 1; n <= 200; n++) {
fact_n *= x/n;
term = fact_n/n;
y = term-c; t = sum+y; c = (t-sum)-y; sum = t;
@@ -852,10 +853,10 @@ double ExponentialIntegral(double x) {
term = 1.0;
y = 1.0-c; t = sum+y; c = (t-sum)-y; sum = t;
- for (n = 1; n <= 100; n++) {
+ for (n = 1; n <= 200; n++) {
last_term = term;
term *= n/x;
- if (term < (tol/val)) break;
+ if (term < tol) break;
if (term < last_term) {
y = term-c; t = sum+y; c = (t-sum)-y; sum = t;
/* printf("A after adding %.8lf, sum = %.8lf\n", term, sum); */
@@ -927,7 +928,7 @@ static const double riemann_zeta_table[] = {
#define NPRECALC_ZETA (sizeof(riemann_zeta_table)/sizeof(riemann_zeta_table[0]))
static double evaluate_zeta(double x) {
- double const tol = 1e-14;
+ double const tol = 1e-16;
double y, t;
double sum = 0.0;
double c = 0.0;
@@ -942,7 +943,7 @@ static double evaluate_zeta(double x) {
term = 1.0/exp2(x); y = term-c; t = sum+y; c = (t-sum)-y; sum = t;
for (k = 3; k <= 100000; k++) {
- if (term < tol) break;
+ if (fabs(term) < tol) break;
if (k == 4) term = 1.0 / exp2(2*x);
else if (k == 8) term = 1.0 / exp2(4*x);
else if (k == 16) term = 1.0 / exp2(8*x);
@@ -953,7 +954,7 @@ static double evaluate_zeta(double x) {
}
double RiemannR(double x) {
- double const tol = 1e-14;
+ double const tol = 1e-16;
double y, t, part_term, term, flogx, zeta;
double sum = 0.0;
double c = 0.0;
@@ -972,12 +973,12 @@ double RiemannR(double x) {
part_term *= flogx / k;
term = part_term / (k * zeta);
y = term-c; t = sum+y; c = (t-sum)-y; sum = t;
- if (term < tol) break;
+ if (fabs(term) < tol) break;
/* printf("R after adding %.8lf, sum = %.8lf\n", term, sum); */
}
/* Finish with function */
for (; k <= 10000; k++) {
- if (term < tol) break;
+ if (fabs(term) < tol) break;
zeta = evaluate_zeta(k+1);
part_term *= flogx / k;
term = part_term / (k * zeta);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libmath-prime-util-perl.git
More information about the Pkg-perl-cvs-commits
mailing list