[431c9e0] | 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 | } |
---|