1*37da2899SCharles.Forsyth /* derived from /netlib/fdlibm */ 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsyth /* @(#)e_jn.c 1.4 95/01/18 */ 4*37da2899SCharles.Forsyth /* 5*37da2899SCharles.Forsyth * ==================================================== 6*37da2899SCharles.Forsyth * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 7*37da2899SCharles.Forsyth * 8*37da2899SCharles.Forsyth * Developed at SunSoft, a Sun Microsystems, Inc. business. 9*37da2899SCharles.Forsyth * Permission to use, copy, modify, and distribute this 10*37da2899SCharles.Forsyth * software is freely granted, provided that this notice 11*37da2899SCharles.Forsyth * is preserved. 12*37da2899SCharles.Forsyth * ==================================================== 13*37da2899SCharles.Forsyth */ 14*37da2899SCharles.Forsyth 15*37da2899SCharles.Forsyth /* 16*37da2899SCharles.Forsyth * __ieee754_jn(n, x), __ieee754_yn(n, x) 17*37da2899SCharles.Forsyth * floating point Bessel's function of the 1st and 2nd kind 18*37da2899SCharles.Forsyth * of order n 19*37da2899SCharles.Forsyth * 20*37da2899SCharles.Forsyth * Special cases: 21*37da2899SCharles.Forsyth * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; 22*37da2899SCharles.Forsyth * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. 23*37da2899SCharles.Forsyth * Note 2. About jn(n,x), yn(n,x) 24*37da2899SCharles.Forsyth * For n=0, j0(x) is called, 25*37da2899SCharles.Forsyth * for n=1, j1(x) is called, 26*37da2899SCharles.Forsyth * for n<x, forward recursion us used starting 27*37da2899SCharles.Forsyth * from values of j0(x) and j1(x). 28*37da2899SCharles.Forsyth * for n>x, a continued fraction approximation to 29*37da2899SCharles.Forsyth * j(n,x)/j(n-1,x) is evaluated and then backward 30*37da2899SCharles.Forsyth * recursion is used starting from a supposed value 31*37da2899SCharles.Forsyth * for j(n,x). The resulting value of j(0,x) is 32*37da2899SCharles.Forsyth * compared with the actual value to correct the 33*37da2899SCharles.Forsyth * supposed value of j(n,x). 34*37da2899SCharles.Forsyth * 35*37da2899SCharles.Forsyth * yn(n,x) is similar in all respects, except 36*37da2899SCharles.Forsyth * that forward recursion is used for all 37*37da2899SCharles.Forsyth * values of n>1. 38*37da2899SCharles.Forsyth * 39*37da2899SCharles.Forsyth */ 40*37da2899SCharles.Forsyth 41*37da2899SCharles.Forsyth #include "fdlibm.h" 42*37da2899SCharles.Forsyth 43*37da2899SCharles.Forsyth static const double 44*37da2899SCharles.Forsyth invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ 45*37da2899SCharles.Forsyth two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ 46*37da2899SCharles.Forsyth one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */ 47*37da2899SCharles.Forsyth 48*37da2899SCharles.Forsyth static double zero = 0.00000000000000000000e+00; 49*37da2899SCharles.Forsyth __ieee754_jn(int n,double x)50*37da2899SCharles.Forsyth double __ieee754_jn(int n, double x) 51*37da2899SCharles.Forsyth { 52*37da2899SCharles.Forsyth int i,hx,ix,lx, sgn; 53*37da2899SCharles.Forsyth double a, b, temp, di; 54*37da2899SCharles.Forsyth double z, w; 55*37da2899SCharles.Forsyth 56*37da2899SCharles.Forsyth /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) 57*37da2899SCharles.Forsyth * Thus, J(-n,x) = J(n,-x) 58*37da2899SCharles.Forsyth */ 59*37da2899SCharles.Forsyth hx = __HI(x); 60*37da2899SCharles.Forsyth ix = 0x7fffffff&hx; 61*37da2899SCharles.Forsyth lx = __LO(x); 62*37da2899SCharles.Forsyth /* if J(n,NaN) is NaN */ 63*37da2899SCharles.Forsyth if((ix|((unsigned)(lx|-lx))>>31)>0x7ff00000) return x+x; 64*37da2899SCharles.Forsyth if(n<0){ 65*37da2899SCharles.Forsyth n = -n; 66*37da2899SCharles.Forsyth x = -x; 67*37da2899SCharles.Forsyth hx ^= 0x80000000; 68*37da2899SCharles.Forsyth } 69*37da2899SCharles.Forsyth if(n==0) return(__ieee754_j0(x)); 70*37da2899SCharles.Forsyth if(n==1) return(__ieee754_j1(x)); 71*37da2899SCharles.Forsyth sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */ 72*37da2899SCharles.Forsyth x = fabs(x); 73*37da2899SCharles.Forsyth if((ix|lx)==0||ix>=0x7ff00000) /* if x is 0 or inf */ 74*37da2899SCharles.Forsyth b = zero; 75*37da2899SCharles.Forsyth else if((double)n<=x) { 76*37da2899SCharles.Forsyth /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ 77*37da2899SCharles.Forsyth if(ix>=0x52D00000) { /* x > 2**302 */ 78*37da2899SCharles.Forsyth /* (x >> n**2) 79*37da2899SCharles.Forsyth * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) 80*37da2899SCharles.Forsyth * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) 81*37da2899SCharles.Forsyth * Let s=sin(x), c=cos(x), 82*37da2899SCharles.Forsyth * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then 83*37da2899SCharles.Forsyth * 84*37da2899SCharles.Forsyth * n sin(xn)*sqt2 cos(xn)*sqt2 85*37da2899SCharles.Forsyth * ---------------------------------- 86*37da2899SCharles.Forsyth * 0 s-c c+s 87*37da2899SCharles.Forsyth * 1 -s-c -c+s 88*37da2899SCharles.Forsyth * 2 -s+c -c-s 89*37da2899SCharles.Forsyth * 3 s+c c-s 90*37da2899SCharles.Forsyth */ 91*37da2899SCharles.Forsyth switch(n&3) { 92*37da2899SCharles.Forsyth case 0: temp = cos(x)+sin(x); break; 93*37da2899SCharles.Forsyth case 1: temp = -cos(x)+sin(x); break; 94*37da2899SCharles.Forsyth case 2: temp = -cos(x)-sin(x); break; 95*37da2899SCharles.Forsyth case 3: temp = cos(x)-sin(x); break; 96*37da2899SCharles.Forsyth } 97*37da2899SCharles.Forsyth b = invsqrtpi*temp/sqrt(x); 98*37da2899SCharles.Forsyth } else { 99*37da2899SCharles.Forsyth a = __ieee754_j0(x); 100*37da2899SCharles.Forsyth b = __ieee754_j1(x); 101*37da2899SCharles.Forsyth for(i=1;i<n;i++){ 102*37da2899SCharles.Forsyth temp = b; 103*37da2899SCharles.Forsyth b = b*((double)(i+i)/x) - a; /* avoid underflow */ 104*37da2899SCharles.Forsyth a = temp; 105*37da2899SCharles.Forsyth } 106*37da2899SCharles.Forsyth } 107*37da2899SCharles.Forsyth } else { 108*37da2899SCharles.Forsyth if(ix<0x3e100000) { /* x < 2**-29 */ 109*37da2899SCharles.Forsyth /* x is tiny, return the first Taylor expansion of J(n,x) 110*37da2899SCharles.Forsyth * J(n,x) = 1/n!*(x/2)^n - ... 111*37da2899SCharles.Forsyth */ 112*37da2899SCharles.Forsyth if(n>33) /* underflow */ 113*37da2899SCharles.Forsyth b = zero; 114*37da2899SCharles.Forsyth else { 115*37da2899SCharles.Forsyth temp = x*0.5; b = temp; 116*37da2899SCharles.Forsyth for (a=one,i=2;i<=n;i++) { 117*37da2899SCharles.Forsyth a *= (double)i; /* a = n! */ 118*37da2899SCharles.Forsyth b *= temp; /* b = (x/2)^n */ 119*37da2899SCharles.Forsyth } 120*37da2899SCharles.Forsyth b = b/a; 121*37da2899SCharles.Forsyth } 122*37da2899SCharles.Forsyth } else { 123*37da2899SCharles.Forsyth /* use backward recurrence */ 124*37da2899SCharles.Forsyth /* x x^2 x^2 125*37da2899SCharles.Forsyth * J(n,x)/J(n-1,x) = ---- ------ ------ ..... 126*37da2899SCharles.Forsyth * 2n - 2(n+1) - 2(n+2) 127*37da2899SCharles.Forsyth * 128*37da2899SCharles.Forsyth * 1 1 1 129*37da2899SCharles.Forsyth * (for large x) = ---- ------ ------ ..... 130*37da2899SCharles.Forsyth * 2n 2(n+1) 2(n+2) 131*37da2899SCharles.Forsyth * -- - ------ - ------ - 132*37da2899SCharles.Forsyth * x x x 133*37da2899SCharles.Forsyth * 134*37da2899SCharles.Forsyth * Let w = 2n/x and h=2/x, then the above quotient 135*37da2899SCharles.Forsyth * is equal to the continued fraction: 136*37da2899SCharles.Forsyth * 1 137*37da2899SCharles.Forsyth * = ----------------------- 138*37da2899SCharles.Forsyth * 1 139*37da2899SCharles.Forsyth * w - ----------------- 140*37da2899SCharles.Forsyth * 1 141*37da2899SCharles.Forsyth * w+h - --------- 142*37da2899SCharles.Forsyth * w+2h - ... 143*37da2899SCharles.Forsyth * 144*37da2899SCharles.Forsyth * To determine how many terms needed, let 145*37da2899SCharles.Forsyth * Q(0) = w, Q(1) = w(w+h) - 1, 146*37da2899SCharles.Forsyth * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), 147*37da2899SCharles.Forsyth * When Q(k) > 1e4 good for single 148*37da2899SCharles.Forsyth * When Q(k) > 1e9 good for double 149*37da2899SCharles.Forsyth * When Q(k) > 1e17 good for quadruple 150*37da2899SCharles.Forsyth */ 151*37da2899SCharles.Forsyth /* determine k */ 152*37da2899SCharles.Forsyth double t,v; 153*37da2899SCharles.Forsyth double q0,q1,h,tmp; int k,m; 154*37da2899SCharles.Forsyth w = (n+n)/(double)x; h = 2.0/(double)x; 155*37da2899SCharles.Forsyth q0 = w; z = w+h; q1 = w*z - 1.0; k=1; 156*37da2899SCharles.Forsyth while(q1<1.0e9) { 157*37da2899SCharles.Forsyth k += 1; z += h; 158*37da2899SCharles.Forsyth tmp = z*q1 - q0; 159*37da2899SCharles.Forsyth q0 = q1; 160*37da2899SCharles.Forsyth q1 = tmp; 161*37da2899SCharles.Forsyth } 162*37da2899SCharles.Forsyth m = n+n; 163*37da2899SCharles.Forsyth for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t); 164*37da2899SCharles.Forsyth a = t; 165*37da2899SCharles.Forsyth b = one; 166*37da2899SCharles.Forsyth /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) 167*37da2899SCharles.Forsyth * Hence, if n*(log(2n/x)) > ... 168*37da2899SCharles.Forsyth * single 8.8722839355e+01 169*37da2899SCharles.Forsyth * double 7.09782712893383973096e+02 170*37da2899SCharles.Forsyth * long double 1.1356523406294143949491931077970765006170e+04 171*37da2899SCharles.Forsyth * then recurrent value may overflow and the result is 172*37da2899SCharles.Forsyth * likely underflow to zero 173*37da2899SCharles.Forsyth */ 174*37da2899SCharles.Forsyth tmp = n; 175*37da2899SCharles.Forsyth v = two/x; 176*37da2899SCharles.Forsyth tmp = tmp*__ieee754_log(fabs(v*tmp)); 177*37da2899SCharles.Forsyth if(tmp<7.09782712893383973096e+02) { 178*37da2899SCharles.Forsyth for(i=n-1,di=(double)(i+i);i>0;i--){ 179*37da2899SCharles.Forsyth temp = b; 180*37da2899SCharles.Forsyth b *= di; 181*37da2899SCharles.Forsyth b = b/x - a; 182*37da2899SCharles.Forsyth a = temp; 183*37da2899SCharles.Forsyth di -= two; 184*37da2899SCharles.Forsyth } 185*37da2899SCharles.Forsyth } else { 186*37da2899SCharles.Forsyth for(i=n-1,di=(double)(i+i);i>0;i--){ 187*37da2899SCharles.Forsyth temp = b; 188*37da2899SCharles.Forsyth b *= di; 189*37da2899SCharles.Forsyth b = b/x - a; 190*37da2899SCharles.Forsyth a = temp; 191*37da2899SCharles.Forsyth di -= two; 192*37da2899SCharles.Forsyth /* scale b to avoid spurious overflow */ 193*37da2899SCharles.Forsyth if(b>1e100) { 194*37da2899SCharles.Forsyth a /= b; 195*37da2899SCharles.Forsyth t /= b; 196*37da2899SCharles.Forsyth b = one; 197*37da2899SCharles.Forsyth } 198*37da2899SCharles.Forsyth } 199*37da2899SCharles.Forsyth } 200*37da2899SCharles.Forsyth b = (t*__ieee754_j0(x)/b); 201*37da2899SCharles.Forsyth } 202*37da2899SCharles.Forsyth } 203*37da2899SCharles.Forsyth if(sgn==1) return -b; else return b; 204*37da2899SCharles.Forsyth } 205*37da2899SCharles.Forsyth __ieee754_yn(int n,double x)206*37da2899SCharles.Forsyth double __ieee754_yn(int n, double x) 207*37da2899SCharles.Forsyth { 208*37da2899SCharles.Forsyth int i,hx,ix,lx; 209*37da2899SCharles.Forsyth int sign; 210*37da2899SCharles.Forsyth double a, b, temp; 211*37da2899SCharles.Forsyth 212*37da2899SCharles.Forsyth hx = __HI(x); 213*37da2899SCharles.Forsyth ix = 0x7fffffff&hx; 214*37da2899SCharles.Forsyth lx = __LO(x); 215*37da2899SCharles.Forsyth /* if Y(n,NaN) is NaN */ 216*37da2899SCharles.Forsyth if((ix|((unsigned)(lx|-lx))>>31)>0x7ff00000) return x+x; 217*37da2899SCharles.Forsyth if((ix|lx)==0) return -one/zero; 218*37da2899SCharles.Forsyth if(hx<0) return zero/zero; 219*37da2899SCharles.Forsyth sign = 1; 220*37da2899SCharles.Forsyth if(n<0){ 221*37da2899SCharles.Forsyth n = -n; 222*37da2899SCharles.Forsyth sign = 1 - ((n&1)<<1); 223*37da2899SCharles.Forsyth } 224*37da2899SCharles.Forsyth if(n==0) return(__ieee754_y0(x)); 225*37da2899SCharles.Forsyth if(n==1) return(sign*__ieee754_y1(x)); 226*37da2899SCharles.Forsyth if(ix==0x7ff00000) return zero; 227*37da2899SCharles.Forsyth if(ix>=0x52D00000) { /* x > 2**302 */ 228*37da2899SCharles.Forsyth /* (x >> n**2) 229*37da2899SCharles.Forsyth * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) 230*37da2899SCharles.Forsyth * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) 231*37da2899SCharles.Forsyth * Let s=sin(x), c=cos(x), 232*37da2899SCharles.Forsyth * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then 233*37da2899SCharles.Forsyth * 234*37da2899SCharles.Forsyth * n sin(xn)*sqt2 cos(xn)*sqt2 235*37da2899SCharles.Forsyth * ---------------------------------- 236*37da2899SCharles.Forsyth * 0 s-c c+s 237*37da2899SCharles.Forsyth * 1 -s-c -c+s 238*37da2899SCharles.Forsyth * 2 -s+c -c-s 239*37da2899SCharles.Forsyth * 3 s+c c-s 240*37da2899SCharles.Forsyth */ 241*37da2899SCharles.Forsyth switch(n&3) { 242*37da2899SCharles.Forsyth case 0: temp = sin(x)-cos(x); break; 243*37da2899SCharles.Forsyth case 1: temp = -sin(x)-cos(x); break; 244*37da2899SCharles.Forsyth case 2: temp = -sin(x)+cos(x); break; 245*37da2899SCharles.Forsyth case 3: temp = sin(x)+cos(x); break; 246*37da2899SCharles.Forsyth } 247*37da2899SCharles.Forsyth b = invsqrtpi*temp/sqrt(x); 248*37da2899SCharles.Forsyth } else { 249*37da2899SCharles.Forsyth a = __ieee754_y0(x); 250*37da2899SCharles.Forsyth b = __ieee754_y1(x); 251*37da2899SCharles.Forsyth /* quit if b is -inf */ 252*37da2899SCharles.Forsyth for(i=1;i<n&&(__HI(b) != 0xfff00000);i++){ 253*37da2899SCharles.Forsyth temp = b; 254*37da2899SCharles.Forsyth b = ((double)(i+i)/x)*b - a; 255*37da2899SCharles.Forsyth a = temp; 256*37da2899SCharles.Forsyth } 257*37da2899SCharles.Forsyth } 258*37da2899SCharles.Forsyth if(sign>0) return b; else return -b; 259*37da2899SCharles.Forsyth } 260