bin/144306: [libm] [patch] Nasty bug in jn(3)
Steven G. Kargl
kargl at troutmask.apl.washington.edu
Fri Nov 12 18:10:12 UTC 2010
The following reply was made to PR bin/144306; it has been noted by GNATS.
From: "Steven G. Kargl" <kargl at troutmask.apl.washington.edu>
To: =?UTF-8?Q?Ulrich_Sp=C3=B6rlein?= <uqs at spoerlein.net>
Cc: bug-followup at FreeBSD.org
Subject: Re: bin/144306: [libm] [patch] Nasty bug in jn(3)
Date: Fri, 12 Nov 2010 10:01:54 -0800 (PST)
Ulrich Sp?rlein wrote:
> Hello Steve, I saw your updated patch for jnf(3) on the mailing list and
> was wondering what the correct values for your test case would look like?
> I'm asking because on Ubuntu I get slightly different values. Especially
> disturbing is, that for FreeBSD the jn/jnf values are identical in this
> case.
Apologies for a delayed response. It seems spamassasin decided
your email was junk mail and put your email into my junk mail
directory.
Bruce has already given you some answers towards
the correct values. You can also use MPFR to generate
a set of values for comparison.
Another way to look at the issue is to start near a
zero of j0f and compute say jnf(3,x) with x ranging
over a small set of values.
#include<stdio.h>
#include<math.h>
int
main(void)
{
float x;
x = 2.404820;
do {
x = nextafterf(x, 10.);
printf("%e %e %e\n", x, jnf(3,x), jn(3,(double)x));
} while(x < 2.404826);
return (0);
}
Without the patch, the 2nd column of the output is not
a smooth function, which is counter to the mathematical
properties of a bessel fcn. Note, the 3rd column is
jn(3,x) where I have applied the patch.
troutmask:kargl[202] cc -o z t.c -lm && ./z
2.404820e+00 1.989337e-01 1.989989e-01
2.404820e+00 1.977170e-01 1.989990e-01
2.404821e+00 1.997695e-01 1.989990e-01
2.404821e+00 1.977899e-01 1.989991e-01
2.404821e+00 2.007952e-01 1.989991e-01
2.404821e+00 1.986288e-01 1.989991e-01
2.404822e+00 1.970318e-01 1.989992e-01
2.404822e+00 1.999776e-01 1.989992e-01
2.404822e+00 1.976307e-01 1.989993e-01
2.404822e+00 2.017480e-01 1.989993e-01
2.404823e+00 1.987786e-01 1.989994e-01
2.404823e+00 1.961335e-01 1.989994e-01
2.404823e+00 1.999664e-01 1.989994e-01
2.404823e+00 2.053210e-01 1.989995e-01
(12 lines removed)
With the patch and with bde's correction for fabsf(), you get
troutmask:kargl[204] cc -o z t.c -lm && ./z
2.404820e+00 1.989989e-01 1.989989e-01
2.404820e+00 1.989990e-01 1.989990e-01
2.404821e+00 1.989990e-01 1.989990e-01
2.404821e+00 1.989991e-01 1.989991e-01
2.404821e+00 1.989991e-01 1.989991e-01
2.404821e+00 1.989991e-01 1.989991e-01
2.404822e+00 1.989992e-01 1.989992e-01
2.404822e+00 1.989992e-01 1.989992e-01
2.404822e+00 1.989993e-01 1.989993e-01
2.404822e+00 1.989994e-01 1.989993e-01
2.404823e+00 1.989994e-01 1.989994e-01
2.404823e+00 1.989994e-01 1.989994e-01
2.404823e+00 1.989995e-01 1.989994e-01
2.404823e+00 1.989995e-01 1.989995e-01
(12 lines removed)
>
> Ubuntu 10.04:
>
I could not find an on-line source code repository for Ubuntu.
I suspect that Ubuntu uses an algorithm for jn[f] based on the
code from fdlibm. This problem appears to date back to at
least 1995 or so.
Now to explain the problem and the solution. jn[f](n,x) for
certain ranges of x uses downward recursion to compute the
value of the function. The recursion sequence that is generated
is proportional to the actual desired value, so a normalization
step is taken. This normalization is j0[f](x) divided by
the the zeroth sequence member. As Bruce notes, near the
zeros of j0[f](x) the computed value can have giga-ULP inaccuracy.
I found for the 1st zero of j0f(x) only the leading decimal digit
is correct. The solution to the issue is fairly straight
forward. The zeros of j0(x) and j1(x) never coincide, so as
j0(x) approaches a zero, the normalization constant switches to
j1[f](x) divided by the 2nd sequence member. The expectation is
that j1[f](x) is an more accurately computed value.
--
Steve
http://troutmask.apl.washington.edu/~kargl/
More information about the freebsd-bugs
mailing list