standards/142803: j0 Bessel function inaccurate near zeros of the function

Steven G. Kargl kargl at
Fri Jan 15 02:00:04 UTC 2010

The following reply was made to PR standards/142803; it has been noted by GNATS.

From: "Steven G. Kargl" <kargl at>
To: Bruce Evans <brde at>
Cc: FreeBSD-gnats-submit at, freebsd-standards at
Subject: Re: standards/142803: j0 Bessel function inaccurate near
 zeros of the function
Date: Thu, 14 Jan 2010 17:53:17 -0800 (PST)

 Bruce Evans wrote:
 > On Thu, 14 Jan 2010, Steven G. Kargl wrote:
 > > Bruce Evans wrote:
 > >> Anyway, if you can get anywhere near < 10 ulp error near all zeros using
 > >> only an asymptotic method, then that would be good.  Then the asymptotic
 > >> method would also be capable of locating the zeros very accurately.  But
 > >> I would be very surprised if this worked.  I know of nothing similar for
 > >> reducing mod Pi for trigonometric functions, which seems a simpler problem.
 > >> I would expect it to at best involve thousands of binary digits in the
 > >> tables for the asymptotic method, and corresponding thousands of digits
 > >> of precision in the calculation (4000 as for mfpr enough for the 2**100th
 > >> zero?).
 > >
 > > The 4000-bit setting for mpfr was a hold over from testing mpfr_j0
 > > against my ascending series implementation of j0 with mpfr
 > > primitives.  As few as 128-bits is sufficient to achieve the
 > > following:
 > >
 > >>>    x        my j0f(x)     libm j0f(x)    MPFR j0        my err  libm err
 > >    2.404825  5.6434398E-08  5.9634296E-08  5.6434400E-08      0.05 152824.59
 > >    5.520078  2.4476657E-08  2.4153294E-08  2.4476659E-08      0.10  18878.52
 > >    8.653728  1.0355303E-07  1.0359805E-07  1.0355306E-07      0.86   1694.47
 > >   11.791534 -3.5291243E-09 -3.5193941E-09 -3.5301714E-09     75.93    781.53
 > Wonder why this jumps.
 Below x=10, I use the ascending series.  Above x=0, I use an asymptotic
 approximation (AA).   x = 11.79... is the first zero I hit with the AA.
 > >   14.930918 -6.4815082E-09 -6.3911618E-09 -6.4815052E-09      0.23   6722.88
 > >   18.071064  5.1532352E-09  5.3149818E-09  5.1532318E-09      0.23  10910.50
 > >   21.211637 -1.5023349E-07 -1.5002509E-07 -1.5023348E-07      2.70  56347.01
 > > ...
 > >
 > > As I suspected by adding additional terms to the asymptotic
 > > approximation and performing all computations with double
 > > precision, reduces 'my err' (5th column).  The value at
 > > x=11.7... is the best I can get.  The asymptotic approximations
 > > contain divergent series and additional terms do not help.
 > The extra precision is almost certainly necessary.  Whether double
 > precision is nearly enough is unclear, but the error near 11.7 suggests
 > that it is nearly enough except there.  The large error might be caused
 > by that zero alone (among small zeros) being very close to a representable
 > value.
 The AA is j0(x) = (P(x) * cos(x+pi/4) + Q(x) * sin(x+pi/4)) where 
 P(x) and Q(x) are infinite, divergent sums.  I use the first 11 
 terms in P(x) and Q(x) to achieve the 'my err' = 75.9.  Additional
 terms cause an increase in 'my err' as does fewer terms.  This is
 probably the limit of double precision.
 I haven't investigated the intervals around the values I listed.  So,
 there may be larger errors that are yet to be found.
 BTW, the MPFR website has a document that describes all their algorithms.
 They claim that the AA can be used for |x| > p*log(2)/2 where p is
 the precision of x; however, in the mpfr code the criterion is |x| > p/2.
 > I forgot the mention that the error table in my previous mail is on amd64
 > for comparing float precision functions with double precision ones, assuming
 > that the latter are correct, which they aren't, but they are hopefully
 > correct enough for this comparision.  The errors on i386 are much larger,
 > due to i386 still using i387 hardware trigonometric which are extremely
 > inaccurate near zeros, starting at the first zero.  Here are both tables:
 My values are also computed on amd64.  I seldomly use i386 for numerical
 work.  A quick change to my test code to use the double precision j0()
 suggests that it has sufficient precision for the comparison you've

More information about the freebsd-standards mailing list