Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Sep 2018 08:21:04 -0700
From:      Steve Kargl <sgk@troutmask.apl.washington.edu>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        freebsd-numerics@freebsd.org
Subject:   Re: j0 (and y0) in the range 2 <= x < (p/2)*log(2)
Message-ID:  <20180905152104.GA26453@troutmask.apl.washington.edu>
In-Reply-To: <20180905201540.D1142@besplex.bde.org>
References:  <20180903235724.GA95333@troutmask.apl.washington.edu> <20180905201540.D1142@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, Sep 05, 2018 at 10:06:29PM +1000, Bruce Evans wrote:
> On Mon, 3 Sep 2018, Steve Kargl wrote:
> 
> > Anyone know where the approximations for j0 (and y0) come from?
> 
> I think they are ordinary minimax rational approximations for related
> functions.  As you noticed, the asymptotic expansion doesn't work below
> about x = 8 (it is off by about 10% for j0(2).  But we want to use the
> single formula given by the asymptotic expansion for all the subintervals:

I've scoured the literature and web for methods of computing 
Bessel functions.  These functions are important to my real
work.  I have not found any paper, webpage, documentation, etc.
that describes what "the related functions" are.

> XX 	/*
> XX 	 * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
> XX 	 * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
> XX 	 */
> XX 		if(ix>0x48000000) z = (invsqrtpi*cc)/sqrt(x);
> XX 		else {
> XX 		    u = pzero(x); v = qzero(x);
> XX 		    z = invsqrtpi*(u*cc-v*ss)/sqrt(x);
> XX 		}
> XX 		return z;
> XX 	}
> 
> where pzero(s) is nominally 1 - 9/128 s**2 + ... and qzero(s) is nominally
> -1/8 *s + ....
> 
> To work, pzero and qzero must not actually be these nominal functions.

If |x| > p/2*log(2) with p the precision of x, P0(x) and Q0(x) can be
used directly.  It is the 2 <= |x| < p/2*log(2) range that is the issue,
but your last paragraph below may be what I have been missing. 

> 
> A non-tricky implementation would use :
> 
>  	z = pzero(x) / qzero(x);
> 
> where pzero and qzero depend on the subinterval like now and have all the
> other terms folded into them.  We already do this for |x| < 2 (except we
> spell the rational function r/s and don't fold all of the terms directly
> into r and s).  This might be the best implementation, and I would also
> try using smaller intervals with polynomial approximations.
> 
> However, we use the asympotic formula for all cases above x = 2.  It is
> off by at least 10% unless pzero and qzero are adjusted.  But 10% is not
> much, and adjusting only pzero and qzero apparently works to compensate
> for this.  To use the same formula for all cases, the complicated factors
> cc, ss and sqrt(x) must not be folded into pzero and qzero; instead these
> factors supply some of the errors which must be compensated for.
> 
> To find the adjustments, I would try applying the same scale factor to
> the nominal pzero and qzero.  E.g., for j0, the error factor is
> invsqrtpi*(u*cc-v*ss)/sqrt(x) / j0(x).  Divide the nominal pzero and qzero
> by this.  Apply normal minimax methods to the modfided pzero and qzero.

Obviously, I had not thought about scaling P0(x) and Q0(x) with a
common factor to force agreement between j0(x) and its approximation.

-- 
Steve



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20180905152104.GA26453>