1 | /* jv.c |
---|
2 | * |
---|
3 | * Bessel function of noninteger order |
---|
4 | * |
---|
5 | * |
---|
6 | * |
---|
7 | * SYNOPSIS: |
---|
8 | * |
---|
9 | * double v, x, y, jv(); |
---|
10 | * |
---|
11 | * y = jv( v, x ); |
---|
12 | * |
---|
13 | * |
---|
14 | * |
---|
15 | * DESCRIPTION: |
---|
16 | * |
---|
17 | * Returns Bessel function of order v of the argument, |
---|
18 | * where v is real. Negative x is allowed if v is an integer. |
---|
19 | * |
---|
20 | * Several expansions are included: the ascending power |
---|
21 | * series, the Hankel expansion, and two transitional |
---|
22 | * expansions for large v. If v is not too large, it |
---|
23 | * is reduced by recurrence to a region of best accuracy. |
---|
24 | * The transitional expansions give 12D accuracy for v > 500. |
---|
25 | * |
---|
26 | * |
---|
27 | * |
---|
28 | * ACCURACY: |
---|
29 | * Results for integer v are indicated by *, where x and v |
---|
30 | * both vary from -125 to +125. Otherwise, |
---|
31 | * x ranges from 0 to 125, v ranges as indicated by "domain." |
---|
32 | * Error criterion is absolute, except relative when |jv()| > 1. |
---|
33 | * |
---|
34 | * arithmetic v domain x domain # trials peak rms |
---|
35 | * IEEE 0,125 0,125 100000 4.6e-15 2.2e-16 |
---|
36 | * IEEE -125,0 0,125 40000 5.4e-11 3.7e-13 |
---|
37 | * IEEE 0,500 0,500 20000 4.4e-15 4.0e-16 |
---|
38 | * Integer v: |
---|
39 | * IEEE -125,125 -125,125 50000 3.5e-15* 1.9e-16* |
---|
40 | * |
---|
41 | */ |
---|
42 | |
---|
43 | |
---|
44 | /* |
---|
45 | Cephes Math Library Release 2.8: June, 2000 |
---|
46 | Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier |
---|
47 | */ |
---|
48 | |
---|
49 | |
---|
50 | #include "mconf.h" |
---|
51 | #define DEBUG 0 |
---|
52 | |
---|
53 | #ifdef DEC |
---|
54 | #define MAXGAM 34.84425627277176174 |
---|
55 | #else |
---|
56 | #define MAXGAM 171.624376956302725 |
---|
57 | #endif |
---|
58 | |
---|
59 | #ifdef ANSIPROT |
---|
60 | extern int airy ( double, double *, double *, double *, double * ); |
---|
61 | extern double fabs ( double ); |
---|
62 | extern double floor ( double ); |
---|
63 | extern double frexp ( double, int * ); |
---|
64 | extern double polevl ( double, void *, int ); |
---|
65 | extern double j0 ( double ); |
---|
66 | extern double j1 ( double ); |
---|
67 | extern double sqrt ( double ); |
---|
68 | extern double cbrt ( double ); |
---|
69 | extern double exp ( double ); |
---|
70 | extern double log ( double ); |
---|
71 | extern double sin ( double ); |
---|
72 | extern double cos ( double ); |
---|
73 | extern double acos ( double ); |
---|
74 | extern double pow ( double, double ); |
---|
75 | extern double gamma ( double ); |
---|
76 | extern double lgam ( double ); |
---|
77 | static double recur(double *, double, double *, int); |
---|
78 | static double jvs(double, double); |
---|
79 | static double hankel(double, double); |
---|
80 | static double jnx(double, double); |
---|
81 | static double jnt(double, double); |
---|
82 | #else |
---|
83 | int airy(); |
---|
84 | double fabs(), floor(), frexp(), polevl(), j0(), j1(), sqrt(), cbrt(); |
---|
85 | double exp(), log(), sin(), cos(), acos(), pow(), gamma(), lgam(); |
---|
86 | static double recur(), jvs(), hankel(), jnx(), jnt(); |
---|
87 | #endif |
---|
88 | |
---|
89 | extern double MAXNUM, MACHEP, MINLOG, MAXLOG; |
---|
90 | #define BIG 1.44115188075855872E+17 |
---|
91 | |
---|
92 | double jv( n, x ) |
---|
93 | double n, x; |
---|
94 | { |
---|
95 | double k, q, t, y, an; |
---|
96 | int i, sign, nint; |
---|
97 | |
---|
98 | nint = 0; /* Flag for integer n */ |
---|
99 | sign = 1; /* Flag for sign inversion */ |
---|
100 | an = fabs( n ); |
---|
101 | y = floor( an ); |
---|
102 | if( y == an ) |
---|
103 | { |
---|
104 | nint = 1; |
---|
105 | i = an - 16384.0 * floor( an/16384.0 ); |
---|
106 | if( n < 0.0 ) |
---|
107 | { |
---|
108 | if( i & 1 ) |
---|
109 | sign = -sign; |
---|
110 | n = an; |
---|
111 | } |
---|
112 | if( x < 0.0 ) |
---|
113 | { |
---|
114 | if( i & 1 ) |
---|
115 | sign = -sign; |
---|
116 | x = -x; |
---|
117 | } |
---|
118 | if( n == 0.0 ) |
---|
119 | return( j0(x) ); |
---|
120 | if( n == 1.0 ) |
---|
121 | return( sign * j1(x) ); |
---|
122 | } |
---|
123 | |
---|
124 | if( (x < 0.0) && (y != an) ) |
---|
125 | { |
---|
126 | mtherr( "Jv", DOMAIN ); |
---|
127 | y = 0.0; |
---|
128 | goto done; |
---|
129 | } |
---|
130 | |
---|
131 | y = fabs(x); |
---|
132 | |
---|
133 | if( y < MACHEP ) |
---|
134 | goto underf; |
---|
135 | |
---|
136 | k = 3.6 * sqrt(y); |
---|
137 | t = 3.6 * sqrt(an); |
---|
138 | if( (y < t) && (an > 21.0) ) |
---|
139 | return( sign * jvs(n,x) ); |
---|
140 | if( (an < k) && (y > 21.0) ) |
---|
141 | return( sign * hankel(n,x) ); |
---|
142 | |
---|
143 | if( an < 500.0 ) |
---|
144 | { |
---|
145 | /* Note: if x is too large, the continued |
---|
146 | * fraction will fail; but then the |
---|
147 | * Hankel expansion can be used. |
---|
148 | */ |
---|
149 | if( nint != 0 ) |
---|
150 | { |
---|
151 | k = 0.0; |
---|
152 | q = recur( &n, x, &k, 1 ); |
---|
153 | if( k == 0.0 ) |
---|
154 | { |
---|
155 | y = j0(x)/q; |
---|
156 | goto done; |
---|
157 | } |
---|
158 | if( k == 1.0 ) |
---|
159 | { |
---|
160 | y = j1(x)/q; |
---|
161 | goto done; |
---|
162 | } |
---|
163 | } |
---|
164 | |
---|
165 | if( an > 2.0 * y ) |
---|
166 | goto rlarger; |
---|
167 | |
---|
168 | if( (n >= 0.0) && (n < 20.0) |
---|
169 | && (y > 6.0) && (y < 20.0) ) |
---|
170 | { |
---|
171 | /* Recur backwards from a larger value of n |
---|
172 | */ |
---|
173 | rlarger: |
---|
174 | k = n; |
---|
175 | |
---|
176 | y = y + an + 1.0; |
---|
177 | if( y < 30.0 ) |
---|
178 | y = 30.0; |
---|
179 | y = n + floor(y-n); |
---|
180 | q = recur( &y, x, &k, 0 ); |
---|
181 | y = jvs(y,x) * q; |
---|
182 | goto done; |
---|
183 | } |
---|
184 | |
---|
185 | if( k <= 30.0 ) |
---|
186 | { |
---|
187 | k = 2.0; |
---|
188 | } |
---|
189 | else if( k < 90.0 ) |
---|
190 | { |
---|
191 | k = (3*k)/4; |
---|
192 | } |
---|
193 | if( an > (k + 3.0) ) |
---|
194 | { |
---|
195 | if( n < 0.0 ) |
---|
196 | k = -k; |
---|
197 | q = n - floor(n); |
---|
198 | k = floor(k) + q; |
---|
199 | if( n > 0.0 ) |
---|
200 | q = recur( &n, x, &k, 1 ); |
---|
201 | else |
---|
202 | { |
---|
203 | t = k; |
---|
204 | k = n; |
---|
205 | q = recur( &t, x, &k, 1 ); |
---|
206 | k = t; |
---|
207 | } |
---|
208 | if( q == 0.0 ) |
---|
209 | { |
---|
210 | underf: |
---|
211 | y = 0.0; |
---|
212 | goto done; |
---|
213 | } |
---|
214 | } |
---|
215 | else |
---|
216 | { |
---|
217 | k = n; |
---|
218 | q = 1.0; |
---|
219 | } |
---|
220 | |
---|
221 | /* boundary between convergence of |
---|
222 | * power series and Hankel expansion |
---|
223 | */ |
---|
224 | y = fabs(k); |
---|
225 | if( y < 26.0 ) |
---|
226 | t = (0.0083*y + 0.09)*y + 12.9; |
---|
227 | else |
---|
228 | t = 0.9 * y; |
---|
229 | |
---|
230 | if( x > t ) |
---|
231 | y = hankel(k,x); |
---|
232 | else |
---|
233 | y = jvs(k,x); |
---|
234 | #if DEBUG |
---|
235 | printf( "y = %.16e, recur q = %.16e\n", y, q ); |
---|
236 | #endif |
---|
237 | if( n > 0.0 ) |
---|
238 | y /= q; |
---|
239 | else |
---|
240 | y *= q; |
---|
241 | } |
---|
242 | |
---|
243 | else |
---|
244 | { |
---|
245 | /* For large n, use the uniform expansion |
---|
246 | * or the transitional expansion. |
---|
247 | * But if x is of the order of n**2, |
---|
248 | * these may blow up, whereas the |
---|
249 | * Hankel expansion will then work. |
---|
250 | */ |
---|
251 | if( n < 0.0 ) |
---|
252 | { |
---|
253 | mtherr( "Jv", TLOSS ); |
---|
254 | y = 0.0; |
---|
255 | goto done; |
---|
256 | } |
---|
257 | t = x/n; |
---|
258 | t /= n; |
---|
259 | if( t > 0.3 ) |
---|
260 | y = hankel(n,x); |
---|
261 | else |
---|
262 | y = jnx(n,x); |
---|
263 | } |
---|
264 | |
---|
265 | done: return( sign * y); |
---|
266 | } |
---|
267 | |
---|
268 | /* Reduce the order by backward recurrence. |
---|
269 | * AMS55 #9.1.27 and 9.1.73. |
---|
270 | */ |
---|
271 | |
---|
272 | static double recur( n, x, newn, cancel ) |
---|
273 | double *n; |
---|
274 | double x; |
---|
275 | double *newn; |
---|
276 | int cancel; |
---|
277 | { |
---|
278 | double pkm2, pkm1, pk, qkm2, qkm1; |
---|
279 | /* double pkp1; */ |
---|
280 | double k, ans, qk, xk, yk, r, t, kf; |
---|
281 | static double big = BIG; |
---|
282 | int nflag, ctr; |
---|
283 | |
---|
284 | /* continued fraction for Jn(x)/Jn-1(x) */ |
---|
285 | if( *n < 0.0 ) |
---|
286 | nflag = 1; |
---|
287 | else |
---|
288 | nflag = 0; |
---|
289 | |
---|
290 | fstart: |
---|
291 | |
---|
292 | #if DEBUG |
---|
293 | printf( "recur: n = %.6e, newn = %.6e, cfrac = ", *n, *newn ); |
---|
294 | #endif |
---|
295 | |
---|
296 | pkm2 = 0.0; |
---|
297 | qkm2 = 1.0; |
---|
298 | pkm1 = x; |
---|
299 | qkm1 = *n + *n; |
---|
300 | xk = -x * x; |
---|
301 | yk = qkm1; |
---|
302 | ans = 1.0; |
---|
303 | ctr = 0; |
---|
304 | do |
---|
305 | { |
---|
306 | yk += 2.0; |
---|
307 | pk = pkm1 * yk + pkm2 * xk; |
---|
308 | qk = qkm1 * yk + qkm2 * xk; |
---|
309 | pkm2 = pkm1; |
---|
310 | pkm1 = pk; |
---|
311 | qkm2 = qkm1; |
---|
312 | qkm1 = qk; |
---|
313 | if( qk != 0 ) |
---|
314 | r = pk/qk; |
---|
315 | else |
---|
316 | r = 0.0; |
---|
317 | if( r != 0 ) |
---|
318 | { |
---|
319 | t = fabs( (ans - r)/r ); |
---|
320 | ans = r; |
---|
321 | } |
---|
322 | else |
---|
323 | t = 1.0; |
---|
324 | |
---|
325 | if( ++ctr > 1000 ) |
---|
326 | { |
---|
327 | mtherr( "jv", UNDERFLOW ); |
---|
328 | goto done; |
---|
329 | } |
---|
330 | if( t < MACHEP ) |
---|
331 | goto done; |
---|
332 | |
---|
333 | if( fabs(pk) > big ) |
---|
334 | { |
---|
335 | pkm2 /= big; |
---|
336 | pkm1 /= big; |
---|
337 | qkm2 /= big; |
---|
338 | qkm1 /= big; |
---|
339 | } |
---|
340 | } |
---|
341 | while( t > MACHEP ); |
---|
342 | |
---|
343 | done: |
---|
344 | |
---|
345 | #if DEBUG |
---|
346 | printf( "%.6e\n", ans ); |
---|
347 | #endif |
---|
348 | |
---|
349 | /* Change n to n-1 if n < 0 and the continued fraction is small |
---|
350 | */ |
---|
351 | if( nflag > 0 ) |
---|
352 | { |
---|
353 | if( fabs(ans) < 0.125 ) |
---|
354 | { |
---|
355 | nflag = -1; |
---|
356 | *n = *n - 1.0; |
---|
357 | goto fstart; |
---|
358 | } |
---|
359 | } |
---|
360 | |
---|
361 | |
---|
362 | kf = *newn; |
---|
363 | |
---|
364 | /* backward recurrence |
---|
365 | * 2k |
---|
366 | * J (x) = --- J (x) - J (x) |
---|
367 | * k-1 x k k+1 |
---|
368 | */ |
---|
369 | |
---|
370 | pk = 1.0; |
---|
371 | pkm1 = 1.0/ans; |
---|
372 | k = *n - 1.0; |
---|
373 | r = 2 * k; |
---|
374 | do |
---|
375 | { |
---|
376 | pkm2 = (pkm1 * r - pk * x) / x; |
---|
377 | /* pkp1 = pk; */ |
---|
378 | pk = pkm1; |
---|
379 | pkm1 = pkm2; |
---|
380 | r -= 2.0; |
---|
381 | /* |
---|
382 | t = fabs(pkp1) + fabs(pk); |
---|
383 | if( (k > (kf + 2.5)) && (fabs(pkm1) < 0.25*t) ) |
---|
384 | { |
---|
385 | k -= 1.0; |
---|
386 | t = x*x; |
---|
387 | pkm2 = ( (r*(r+2.0)-t)*pk - r*x*pkp1 )/t; |
---|
388 | pkp1 = pk; |
---|
389 | pk = pkm1; |
---|
390 | pkm1 = pkm2; |
---|
391 | r -= 2.0; |
---|
392 | } |
---|
393 | */ |
---|
394 | k -= 1.0; |
---|
395 | } |
---|
396 | while( k > (kf + 0.5) ); |
---|
397 | |
---|
398 | /* Take the larger of the last two iterates |
---|
399 | * on the theory that it may have less cancellation error. |
---|
400 | */ |
---|
401 | |
---|
402 | if( cancel ) |
---|
403 | { |
---|
404 | if( (kf >= 0.0) && (fabs(pk) > fabs(pkm1)) ) |
---|
405 | { |
---|
406 | k += 1.0; |
---|
407 | pkm2 = pk; |
---|
408 | } |
---|
409 | } |
---|
410 | *newn = k; |
---|
411 | #if DEBUG |
---|
412 | printf( "newn %.6e rans %.6e\n", k, pkm2 ); |
---|
413 | #endif |
---|
414 | return( pkm2 ); |
---|
415 | } |
---|
416 | |
---|
417 | |
---|
418 | |
---|
419 | /* Ascending power series for Jv(x). |
---|
420 | * AMS55 #9.1.10. |
---|
421 | */ |
---|
422 | |
---|
423 | extern double PI; |
---|
424 | extern int sgngam; |
---|
425 | |
---|
426 | static double jvs( n, x ) |
---|
427 | double n, x; |
---|
428 | { |
---|
429 | double t, u, y, z, k; |
---|
430 | int ex; |
---|
431 | |
---|
432 | z = -x * x / 4.0; |
---|
433 | u = 1.0; |
---|
434 | y = u; |
---|
435 | k = 1.0; |
---|
436 | t = 1.0; |
---|
437 | |
---|
438 | while( t > MACHEP ) |
---|
439 | { |
---|
440 | u *= z / (k * (n+k)); |
---|
441 | y += u; |
---|
442 | k += 1.0; |
---|
443 | if( y != 0 ) |
---|
444 | t = fabs( u/y ); |
---|
445 | } |
---|
446 | #if DEBUG |
---|
447 | printf( "power series=%.5e ", y ); |
---|
448 | #endif |
---|
449 | t = frexp( 0.5*x, &ex ); |
---|
450 | ex = ex * n; |
---|
451 | if( (ex > -1023) |
---|
452 | && (ex < 1023) |
---|
453 | && (n > 0.0) |
---|
454 | && (n < (MAXGAM-1.0)) ) |
---|
455 | { |
---|
456 | t = pow( 0.5*x, n ) / gamma( n + 1.0 ); |
---|
457 | #if DEBUG |
---|
458 | printf( "pow(.5*x, %.4e)/gamma(n+1)=%.5e\n", n, t ); |
---|
459 | #endif |
---|
460 | y *= t; |
---|
461 | } |
---|
462 | else |
---|
463 | { |
---|
464 | #if DEBUG |
---|
465 | z = n * log(0.5*x); |
---|
466 | k = lgam( n+1.0 ); |
---|
467 | t = z - k; |
---|
468 | printf( "log pow=%.5e, lgam(%.4e)=%.5e\n", z, n+1.0, k ); |
---|
469 | #else |
---|
470 | t = n * log(0.5*x) - lgam(n + 1.0); |
---|
471 | #endif |
---|
472 | if( y < 0 ) |
---|
473 | { |
---|
474 | sgngam = -sgngam; |
---|
475 | y = -y; |
---|
476 | } |
---|
477 | t += log(y); |
---|
478 | #if DEBUG |
---|
479 | printf( "log y=%.5e\n", log(y) ); |
---|
480 | #endif |
---|
481 | if( t < -MAXLOG ) |
---|
482 | { |
---|
483 | return( 0.0 ); |
---|
484 | } |
---|
485 | if( t > MAXLOG ) |
---|
486 | { |
---|
487 | mtherr( "Jv", OVERFLOW ); |
---|
488 | return( MAXNUM ); |
---|
489 | } |
---|
490 | y = sgngam * exp( t ); |
---|
491 | } |
---|
492 | return(y); |
---|
493 | } |
---|
494 | |
---|
495 | /* Hankel's asymptotic expansion |
---|
496 | * for large x. |
---|
497 | * AMS55 #9.2.5. |
---|
498 | */ |
---|
499 | |
---|
500 | static double hankel( n, x ) |
---|
501 | double n, x; |
---|
502 | { |
---|
503 | double t, u, z, k, sign, conv; |
---|
504 | double p, q, j, m, pp, qq; |
---|
505 | int flag; |
---|
506 | |
---|
507 | m = 4.0*n*n; |
---|
508 | j = 1.0; |
---|
509 | z = 8.0 * x; |
---|
510 | k = 1.0; |
---|
511 | p = 1.0; |
---|
512 | u = (m - 1.0)/z; |
---|
513 | q = u; |
---|
514 | sign = 1.0; |
---|
515 | conv = 1.0; |
---|
516 | flag = 0; |
---|
517 | t = 1.0; |
---|
518 | pp = 1.0e38; |
---|
519 | qq = 1.0e38; |
---|
520 | |
---|
521 | while( t > MACHEP ) |
---|
522 | { |
---|
523 | k += 2.0; |
---|
524 | j += 1.0; |
---|
525 | sign = -sign; |
---|
526 | u *= (m - k * k)/(j * z); |
---|
527 | p += sign * u; |
---|
528 | k += 2.0; |
---|
529 | j += 1.0; |
---|
530 | u *= (m - k * k)/(j * z); |
---|
531 | q += sign * u; |
---|
532 | t = fabs(u/p); |
---|
533 | if( t < conv ) |
---|
534 | { |
---|
535 | conv = t; |
---|
536 | qq = q; |
---|
537 | pp = p; |
---|
538 | flag = 1; |
---|
539 | } |
---|
540 | /* stop if the terms start getting larger */ |
---|
541 | if( (flag != 0) && (t > conv) ) |
---|
542 | { |
---|
543 | #if DEBUG |
---|
544 | printf( "Hankel: convergence to %.4E\n", conv ); |
---|
545 | #endif |
---|
546 | goto hank1; |
---|
547 | } |
---|
548 | } |
---|
549 | |
---|
550 | hank1: |
---|
551 | u = x - (0.5*n + 0.25) * PI; |
---|
552 | t = sqrt( 2.0/(PI*x) ) * ( pp * cos(u) - qq * sin(u) ); |
---|
553 | #if DEBUG |
---|
554 | printf( "hank: %.6e\n", t ); |
---|
555 | #endif |
---|
556 | return( t ); |
---|
557 | } |
---|
558 | |
---|
559 | |
---|
560 | /* Asymptotic expansion for large n. |
---|
561 | * AMS55 #9.3.35. |
---|
562 | */ |
---|
563 | |
---|
564 | static double lambda[] = { |
---|
565 | 1.0, |
---|
566 | 1.041666666666666666666667E-1, |
---|
567 | 8.355034722222222222222222E-2, |
---|
568 | 1.282265745563271604938272E-1, |
---|
569 | 2.918490264641404642489712E-1, |
---|
570 | 8.816272674437576524187671E-1, |
---|
571 | 3.321408281862767544702647E+0, |
---|
572 | 1.499576298686255465867237E+1, |
---|
573 | 7.892301301158651813848139E+1, |
---|
574 | 4.744515388682643231611949E+2, |
---|
575 | 3.207490090890661934704328E+3 |
---|
576 | }; |
---|
577 | static double mu[] = { |
---|
578 | 1.0, |
---|
579 | -1.458333333333333333333333E-1, |
---|
580 | -9.874131944444444444444444E-2, |
---|
581 | -1.433120539158950617283951E-1, |
---|
582 | -3.172272026784135480967078E-1, |
---|
583 | -9.424291479571202491373028E-1, |
---|
584 | -3.511203040826354261542798E+0, |
---|
585 | -1.572726362036804512982712E+1, |
---|
586 | -8.228143909718594444224656E+1, |
---|
587 | -4.923553705236705240352022E+2, |
---|
588 | -3.316218568547972508762102E+3 |
---|
589 | }; |
---|
590 | static double P1[] = { |
---|
591 | -2.083333333333333333333333E-1, |
---|
592 | 1.250000000000000000000000E-1 |
---|
593 | }; |
---|
594 | static double P2[] = { |
---|
595 | 3.342013888888888888888889E-1, |
---|
596 | -4.010416666666666666666667E-1, |
---|
597 | 7.031250000000000000000000E-2 |
---|
598 | }; |
---|
599 | static double P3[] = { |
---|
600 | -1.025812596450617283950617E+0, |
---|
601 | 1.846462673611111111111111E+0, |
---|
602 | -8.912109375000000000000000E-1, |
---|
603 | 7.324218750000000000000000E-2 |
---|
604 | }; |
---|
605 | static double P4[] = { |
---|
606 | 4.669584423426247427983539E+0, |
---|
607 | -1.120700261622299382716049E+1, |
---|
608 | 8.789123535156250000000000E+0, |
---|
609 | -2.364086914062500000000000E+0, |
---|
610 | 1.121520996093750000000000E-1 |
---|
611 | }; |
---|
612 | static double P5[] = { |
---|
613 | -2.8212072558200244877E1, |
---|
614 | 8.4636217674600734632E1, |
---|
615 | -9.1818241543240017361E1, |
---|
616 | 4.2534998745388454861E1, |
---|
617 | -7.3687943594796316964E0, |
---|
618 | 2.27108001708984375E-1 |
---|
619 | }; |
---|
620 | static double P6[] = { |
---|
621 | 2.1257013003921712286E2, |
---|
622 | -7.6525246814118164230E2, |
---|
623 | 1.0599904525279998779E3, |
---|
624 | -6.9957962737613254123E2, |
---|
625 | 2.1819051174421159048E2, |
---|
626 | -2.6491430486951555525E1, |
---|
627 | 5.7250142097473144531E-1 |
---|
628 | }; |
---|
629 | static double P7[] = { |
---|
630 | -1.9194576623184069963E3, |
---|
631 | 8.0617221817373093845E3, |
---|
632 | -1.3586550006434137439E4, |
---|
633 | 1.1655393336864533248E4, |
---|
634 | -5.3056469786134031084E3, |
---|
635 | 1.2009029132163524628E3, |
---|
636 | -1.0809091978839465550E2, |
---|
637 | 1.7277275025844573975E0 |
---|
638 | }; |
---|
639 | |
---|
640 | |
---|
641 | static double jnx( n, x ) |
---|
642 | double n, x; |
---|
643 | { |
---|
644 | double zeta, sqz, zz, zp, np; |
---|
645 | double cbn, n23, t, z, sz; |
---|
646 | double pp, qq, z32i, zzi; |
---|
647 | double ak, bk, akl, bkl; |
---|
648 | int sign, doa, dob, nflg, k, s, tk, tkp1, m; |
---|
649 | static double u[8]; |
---|
650 | static double ai, aip, bi, bip; |
---|
651 | |
---|
652 | /* Test for x very close to n. |
---|
653 | * Use expansion for transition region if so. |
---|
654 | */ |
---|
655 | cbn = cbrt(n); |
---|
656 | z = (x - n)/cbn; |
---|
657 | if( fabs(z) <= 0.7 ) |
---|
658 | return( jnt(n,x) ); |
---|
659 | |
---|
660 | z = x/n; |
---|
661 | zz = 1.0 - z*z; |
---|
662 | if( zz == 0.0 ) |
---|
663 | return(0.0); |
---|
664 | |
---|
665 | if( zz > 0.0 ) |
---|
666 | { |
---|
667 | sz = sqrt( zz ); |
---|
668 | t = 1.5 * (log( (1.0+sz)/z ) - sz ); /* zeta ** 3/2 */ |
---|
669 | zeta = cbrt( t * t ); |
---|
670 | nflg = 1; |
---|
671 | } |
---|
672 | else |
---|
673 | { |
---|
674 | sz = sqrt(-zz); |
---|
675 | t = 1.5 * (sz - acos(1.0/z)); |
---|
676 | zeta = -cbrt( t * t ); |
---|
677 | nflg = -1; |
---|
678 | } |
---|
679 | z32i = fabs(1.0/t); |
---|
680 | sqz = cbrt(t); |
---|
681 | |
---|
682 | /* Airy function */ |
---|
683 | n23 = cbrt( n * n ); |
---|
684 | t = n23 * zeta; |
---|
685 | |
---|
686 | #if DEBUG |
---|
687 | printf("zeta %.5E, Airy(%.5E)\n", zeta, t ); |
---|
688 | #endif |
---|
689 | airy( t, &ai, &aip, &bi, &bip ); |
---|
690 | |
---|
691 | /* polynomials in expansion */ |
---|
692 | u[0] = 1.0; |
---|
693 | zzi = 1.0/zz; |
---|
694 | u[1] = polevl( zzi, P1, 1 )/sz; |
---|
695 | u[2] = polevl( zzi, P2, 2 )/zz; |
---|
696 | u[3] = polevl( zzi, P3, 3 )/(sz*zz); |
---|
697 | pp = zz*zz; |
---|
698 | u[4] = polevl( zzi, P4, 4 )/pp; |
---|
699 | u[5] = polevl( zzi, P5, 5 )/(pp*sz); |
---|
700 | pp *= zz; |
---|
701 | u[6] = polevl( zzi, P6, 6 )/pp; |
---|
702 | u[7] = polevl( zzi, P7, 7 )/(pp*sz); |
---|
703 | |
---|
704 | #if DEBUG |
---|
705 | for( k=0; k<=7; k++ ) |
---|
706 | printf( "u[%d] = %.5E\n", k, u[k] ); |
---|
707 | #endif |
---|
708 | |
---|
709 | pp = 0.0; |
---|
710 | qq = 0.0; |
---|
711 | np = 1.0; |
---|
712 | /* flags to stop when terms get larger */ |
---|
713 | doa = 1; |
---|
714 | dob = 1; |
---|
715 | akl = MAXNUM; |
---|
716 | bkl = MAXNUM; |
---|
717 | |
---|
718 | for( k=0; k<=3; k++ ) |
---|
719 | { |
---|
720 | tk = 2 * k; |
---|
721 | tkp1 = tk + 1; |
---|
722 | zp = 1.0; |
---|
723 | ak = 0.0; |
---|
724 | bk = 0.0; |
---|
725 | for( s=0; s<=tk; s++ ) |
---|
726 | { |
---|
727 | if( doa ) |
---|
728 | { |
---|
729 | if( (s & 3) > 1 ) |
---|
730 | sign = nflg; |
---|
731 | else |
---|
732 | sign = 1; |
---|
733 | ak += sign * mu[s] * zp * u[tk-s]; |
---|
734 | } |
---|
735 | |
---|
736 | if( dob ) |
---|
737 | { |
---|
738 | m = tkp1 - s; |
---|
739 | if( ((m+1) & 3) > 1 ) |
---|
740 | sign = nflg; |
---|
741 | else |
---|
742 | sign = 1; |
---|
743 | bk += sign * lambda[s] * zp * u[m]; |
---|
744 | } |
---|
745 | zp *= z32i; |
---|
746 | } |
---|
747 | |
---|
748 | if( doa ) |
---|
749 | { |
---|
750 | ak *= np; |
---|
751 | t = fabs(ak); |
---|
752 | if( t < akl ) |
---|
753 | { |
---|
754 | akl = t; |
---|
755 | pp += ak; |
---|
756 | } |
---|
757 | else |
---|
758 | doa = 0; |
---|
759 | } |
---|
760 | |
---|
761 | if( dob ) |
---|
762 | { |
---|
763 | bk += lambda[tkp1] * zp * u[0]; |
---|
764 | bk *= -np/sqz; |
---|
765 | t = fabs(bk); |
---|
766 | if( t < bkl ) |
---|
767 | { |
---|
768 | bkl = t; |
---|
769 | qq += bk; |
---|
770 | } |
---|
771 | else |
---|
772 | dob = 0; |
---|
773 | } |
---|
774 | #if DEBUG |
---|
775 | printf("a[%d] %.5E, b[%d] %.5E\n", k, ak, k, bk ); |
---|
776 | #endif |
---|
777 | if( np < MACHEP ) |
---|
778 | break; |
---|
779 | np /= n*n; |
---|
780 | } |
---|
781 | |
---|
782 | /* normalizing factor ( 4*zeta/(1 - z**2) )**1/4 */ |
---|
783 | t = 4.0 * zeta/zz; |
---|
784 | t = sqrt( sqrt(t) ); |
---|
785 | |
---|
786 | t *= ai*pp/cbrt(n) + aip*qq/(n23*n); |
---|
787 | return(t); |
---|
788 | } |
---|
789 | |
---|
790 | /* Asymptotic expansion for transition region, |
---|
791 | * n large and x close to n. |
---|
792 | * AMS55 #9.3.23. |
---|
793 | */ |
---|
794 | |
---|
795 | static double PF2[] = { |
---|
796 | -9.0000000000000000000e-2, |
---|
797 | 8.5714285714285714286e-2 |
---|
798 | }; |
---|
799 | static double PF3[] = { |
---|
800 | 1.3671428571428571429e-1, |
---|
801 | -5.4920634920634920635e-2, |
---|
802 | -4.4444444444444444444e-3 |
---|
803 | }; |
---|
804 | static double PF4[] = { |
---|
805 | 1.3500000000000000000e-3, |
---|
806 | -1.6036054421768707483e-1, |
---|
807 | 4.2590187590187590188e-2, |
---|
808 | 2.7330447330447330447e-3 |
---|
809 | }; |
---|
810 | static double PG1[] = { |
---|
811 | -2.4285714285714285714e-1, |
---|
812 | 1.4285714285714285714e-2 |
---|
813 | }; |
---|
814 | static double PG2[] = { |
---|
815 | -9.0000000000000000000e-3, |
---|
816 | 1.9396825396825396825e-1, |
---|
817 | -1.1746031746031746032e-2 |
---|
818 | }; |
---|
819 | static double PG3[] = { |
---|
820 | 1.9607142857142857143e-2, |
---|
821 | -1.5983694083694083694e-1, |
---|
822 | 6.3838383838383838384e-3 |
---|
823 | }; |
---|
824 | |
---|
825 | |
---|
826 | static double jnt( n, x ) |
---|
827 | double n, x; |
---|
828 | { |
---|
829 | double z, zz, z3; |
---|
830 | double cbn, n23, cbtwo; |
---|
831 | double ai, aip, bi, bip; /* Airy functions */ |
---|
832 | double nk, fk, gk, pp, qq; |
---|
833 | double F[5], G[4]; |
---|
834 | int k; |
---|
835 | |
---|
836 | cbn = cbrt(n); |
---|
837 | z = (x - n)/cbn; |
---|
838 | cbtwo = cbrt( 2.0 ); |
---|
839 | |
---|
840 | /* Airy function */ |
---|
841 | zz = -cbtwo * z; |
---|
842 | airy( zz, &ai, &aip, &bi, &bip ); |
---|
843 | |
---|
844 | /* polynomials in expansion */ |
---|
845 | zz = z * z; |
---|
846 | z3 = zz * z; |
---|
847 | F[0] = 1.0; |
---|
848 | F[1] = -z/5.0; |
---|
849 | F[2] = polevl( z3, PF2, 1 ) * zz; |
---|
850 | F[3] = polevl( z3, PF3, 2 ); |
---|
851 | F[4] = polevl( z3, PF4, 3 ) * z; |
---|
852 | G[0] = 0.3 * zz; |
---|
853 | G[1] = polevl( z3, PG1, 1 ); |
---|
854 | G[2] = polevl( z3, PG2, 2 ) * z; |
---|
855 | G[3] = polevl( z3, PG3, 2 ) * zz; |
---|
856 | #if DEBUG |
---|
857 | for( k=0; k<=4; k++ ) |
---|
858 | printf( "F[%d] = %.5E\n", k, F[k] ); |
---|
859 | for( k=0; k<=3; k++ ) |
---|
860 | printf( "G[%d] = %.5E\n", k, G[k] ); |
---|
861 | #endif |
---|
862 | pp = 0.0; |
---|
863 | qq = 0.0; |
---|
864 | nk = 1.0; |
---|
865 | n23 = cbrt( n * n ); |
---|
866 | |
---|
867 | for( k=0; k<=4; k++ ) |
---|
868 | { |
---|
869 | fk = F[k]*nk; |
---|
870 | pp += fk; |
---|
871 | if( k != 4 ) |
---|
872 | { |
---|
873 | gk = G[k]*nk; |
---|
874 | qq += gk; |
---|
875 | } |
---|
876 | #if DEBUG |
---|
877 | printf("fk[%d] %.5E, gk[%d] %.5E\n", k, fk, k, gk ); |
---|
878 | #endif |
---|
879 | nk /= n23; |
---|
880 | } |
---|
881 | |
---|
882 | fk = cbtwo * ai * pp/cbn + cbrt(4.0) * aip * qq/n; |
---|
883 | return(fk); |
---|
884 | } |
---|