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 <d...@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 _______________________________________________ Pkg-perl-cvs-commits mailing list Pkg-perl-cvs-commits@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-perl-cvs-commits