n_jn.c revision 1.1 1 /* $NetBSD: n_jn.c,v 1.1 1995/10/10 23:36:54 ragge Exp $ */
2 /*-
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #ifndef lint
36 static char sccsid[] = "@(#)jn.c 8.2 (Berkeley) 11/30/93";
37 #endif /* not lint */
38
39 /*
40 * 16 December 1992
41 * Minor modifications by Peter McIlroy to adapt non-IEEE architecture.
42 */
43
44 /*
45 * ====================================================
46 * Copyright (C) 1992 by Sun Microsystems, Inc.
47 *
48 * Developed at SunPro, a Sun Microsystems, Inc. business.
49 * Permission to use, copy, modify, and distribute this
50 * software is freely granted, provided that this notice
51 * is preserved.
52 * ====================================================
53 *
54 * ******************* WARNING ********************
55 * This is an alpha version of SunPro's FDLIBM (Freely
56 * Distributable Math Library) for IEEE double precision
57 * arithmetic. FDLIBM is a basic math library written
58 * in C that runs on machines that conform to IEEE
59 * Standard 754/854. This alpha version is distributed
60 * for testing purpose. Those who use this software
61 * should report any bugs to
62 *
63 * fdlibm-comments (at) sunpro.eng.sun.com
64 *
65 * -- K.C. Ng, Oct 12, 1992
66 * ************************************************
67 */
68
69 /*
70 * jn(int n, double x), yn(int n, double x)
71 * floating point Bessel's function of the 1st and 2nd kind
72 * of order n
73 *
74 * Special cases:
75 * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal;
76 * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.
77 * Note 2. About jn(n,x), yn(n,x)
78 * For n=0, j0(x) is called,
79 * for n=1, j1(x) is called,
80 * for n<x, forward recursion us used starting
81 * from values of j0(x) and j1(x).
82 * for n>x, a continued fraction approximation to
83 * j(n,x)/j(n-1,x) is evaluated and then backward
84 * recursion is used starting from a supposed value
85 * for j(n,x). The resulting value of j(0,x) is
86 * compared with the actual value to correct the
87 * supposed value of j(n,x).
88 *
89 * yn(n,x) is similar in all respects, except
90 * that forward recursion is used for all
91 * values of n>1.
92 *
93 */
94
95 #include <math.h>
96 #include <float.h>
97 #include <errno.h>
98
99 #if defined(vax) || defined(tahoe)
100 #define _IEEE 0
101 #else
102 #define _IEEE 1
103 #define infnan(x) (0.0)
104 #endif
105
106 static double
107 invsqrtpi= 5.641895835477562869480794515607725858441e-0001,
108 two = 2.0,
109 zero = 0.0,
110 one = 1.0;
111
112 double jn(n,x)
113 int n; double x;
114 {
115 int i, sgn;
116 double a, b, temp;
117 double z, w;
118
119 /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
120 * Thus, J(-n,x) = J(n,-x)
121 */
122 /* if J(n,NaN) is NaN */
123 if (_IEEE && isnan(x)) return x+x;
124 if (n<0){
125 n = -n;
126 x = -x;
127 }
128 if (n==0) return(j0(x));
129 if (n==1) return(j1(x));
130 sgn = (n&1)&(x < zero); /* even n -- 0, odd n -- sign(x) */
131 x = fabs(x);
132 if (x == 0 || !finite (x)) /* if x is 0 or inf */
133 b = zero;
134 else if ((double) n <= x) {
135 /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
136 if (_IEEE && x >= 8.148143905337944345e+090) {
137 /* x >= 2**302 */
138 /* (x >> n**2)
139 * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
140 * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
141 * Let s=sin(x), c=cos(x),
142 * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
143 *
144 * n sin(xn)*sqt2 cos(xn)*sqt2
145 * ----------------------------------
146 * 0 s-c c+s
147 * 1 -s-c -c+s
148 * 2 -s+c -c-s
149 * 3 s+c c-s
150 */
151 switch(n&3) {
152 case 0: temp = cos(x)+sin(x); break;
153 case 1: temp = -cos(x)+sin(x); break;
154 case 2: temp = -cos(x)-sin(x); break;
155 case 3: temp = cos(x)-sin(x); break;
156 }
157 b = invsqrtpi*temp/sqrt(x);
158 } else {
159 a = j0(x);
160 b = j1(x);
161 for(i=1;i<n;i++){
162 temp = b;
163 b = b*((double)(i+i)/x) - a; /* avoid underflow */
164 a = temp;
165 }
166 }
167 } else {
168 if (x < 1.86264514923095703125e-009) { /* x < 2**-29 */
169 /* x is tiny, return the first Taylor expansion of J(n,x)
170 * J(n,x) = 1/n!*(x/2)^n - ...
171 */
172 if (n > 33) /* underflow */
173 b = zero;
174 else {
175 temp = x*0.5; b = temp;
176 for (a=one,i=2;i<=n;i++) {
177 a *= (double)i; /* a = n! */
178 b *= temp; /* b = (x/2)^n */
179 }
180 b = b/a;
181 }
182 } else {
183 /* use backward recurrence */
184 /* x x^2 x^2
185 * J(n,x)/J(n-1,x) = ---- ------ ------ .....
186 * 2n - 2(n+1) - 2(n+2)
187 *
188 * 1 1 1
189 * (for large x) = ---- ------ ------ .....
190 * 2n 2(n+1) 2(n+2)
191 * -- - ------ - ------ -
192 * x x x
193 *
194 * Let w = 2n/x and h=2/x, then the above quotient
195 * is equal to the continued fraction:
196 * 1
197 * = -----------------------
198 * 1
199 * w - -----------------
200 * 1
201 * w+h - ---------
202 * w+2h - ...
203 *
204 * To determine how many terms needed, let
205 * Q(0) = w, Q(1) = w(w+h) - 1,
206 * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
207 * When Q(k) > 1e4 good for single
208 * When Q(k) > 1e9 good for double
209 * When Q(k) > 1e17 good for quadruple
210 */
211 /* determine k */
212 double t,v;
213 double q0,q1,h,tmp; int k,m;
214 w = (n+n)/(double)x; h = 2.0/(double)x;
215 q0 = w; z = w+h; q1 = w*z - 1.0; k=1;
216 while (q1<1.0e9) {
217 k += 1; z += h;
218 tmp = z*q1 - q0;
219 q0 = q1;
220 q1 = tmp;
221 }
222 m = n+n;
223 for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
224 a = t;
225 b = one;
226 /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
227 * Hence, if n*(log(2n/x)) > ...
228 * single 8.8722839355e+01
229 * double 7.09782712893383973096e+02
230 * long double 1.1356523406294143949491931077970765006170e+04
231 * then recurrent value may overflow and the result will
232 * likely underflow to zero
233 */
234 tmp = n;
235 v = two/x;
236 tmp = tmp*log(fabs(v*tmp));
237 for (i=n-1;i>0;i--){
238 temp = b;
239 b = ((i+i)/x)*b - a;
240 a = temp;
241 /* scale b to avoid spurious overflow */
242 # if defined(vax) || defined(tahoe)
243 # define BMAX 1e13
244 # else
245 # define BMAX 1e100
246 # endif /* defined(vax) || defined(tahoe) */
247 if (b > BMAX) {
248 a /= b;
249 t /= b;
250 b = one;
251 }
252 }
253 b = (t*j0(x)/b);
254 }
255 }
256 return ((sgn == 1) ? -b : b);
257 }
258 double yn(n,x)
259 int n; double x;
260 {
261 int i, sign;
262 double a, b, temp;
263
264 /* Y(n,NaN), Y(n, x < 0) is NaN */
265 if (x <= 0 || (_IEEE && x != x))
266 if (_IEEE && x < 0) return zero/zero;
267 else if (x < 0) return (infnan(EDOM));
268 else if (_IEEE) return -one/zero;
269 else return(infnan(-ERANGE));
270 else if (!finite(x)) return(0);
271 sign = 1;
272 if (n<0){
273 n = -n;
274 sign = 1 - ((n&1)<<2);
275 }
276 if (n == 0) return(y0(x));
277 if (n == 1) return(sign*y1(x));
278 if(_IEEE && x >= 8.148143905337944345e+090) { /* x > 2**302 */
279 /* (x >> n**2)
280 * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
281 * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
282 * Let s=sin(x), c=cos(x),
283 * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
284 *
285 * n sin(xn)*sqt2 cos(xn)*sqt2
286 * ----------------------------------
287 * 0 s-c c+s
288 * 1 -s-c -c+s
289 * 2 -s+c -c-s
290 * 3 s+c c-s
291 */
292 switch (n&3) {
293 case 0: temp = sin(x)-cos(x); break;
294 case 1: temp = -sin(x)-cos(x); break;
295 case 2: temp = -sin(x)+cos(x); break;
296 case 3: temp = sin(x)+cos(x); break;
297 }
298 b = invsqrtpi*temp/sqrt(x);
299 } else {
300 a = y0(x);
301 b = y1(x);
302 /* quit if b is -inf */
303 for (i = 1; i < n && !finite(b); i++){
304 temp = b;
305 b = ((double)(i+i)/x)*b - a;
306 a = temp;
307 }
308 }
309 if (!_IEEE && !finite(b))
310 return (infnan(-sign * ERANGE));
311 return ((sign > 0) ? b : -b);
312 }
313