base/math/e_jn.c

Go to the documentation of this file.
00001 /* @(#)e_jn.c 5.1 93/09/24 */
00002 /*
00003  * ====================================================
00004  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
00005  *
00006  * Developed at SunPro, a Sun Microsystems, Inc. business.
00007  * Permission to use, copy, modify, and distribute this
00008  * software is freely granted, provided that this notice 
00009  * is preserved.
00010  * ====================================================
00011  */
00012 
00013 #if defined(LIBM_SCCS) && !defined(lint)
00014 static char rcsid[] = "$NetBSD: e_jn.c,v 1.9 1995/05/10 20:45:34 jtc Exp $";
00015 #endif
00016 
00017 /*
00018  * __ieee754_jn(n, x), __ieee754_yn(n, x)
00019  * floating point Bessel's function of the 1st and 2nd kind
00020  * of order n
00021  *          
00022  * Special cases:
00023  *  y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal;
00024  *  y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.
00025  * Note 2. About jn(n,x), yn(n,x)
00026  *  For n=0, j0(x) is called,
00027  *  for n=1, j1(x) is called,
00028  *  for n<x, forward recursion us used starting
00029  *  from values of j0(x) and j1(x).
00030  *  for n>x, a continued fraction approximation to
00031  *  j(n,x)/j(n-1,x) is evaluated and then backward
00032  *  recursion is used starting from a supposed value
00033  *  for j(n,x). The resulting value of j(0,x) is
00034  *  compared with the actual value to correct the
00035  *  supposed value of j(n,x).
00036  *
00037  *  yn(n,x) is similar in all respects, except
00038  *  that forward recursion is used for all
00039  *  values of n>1.
00040  *  
00041  */
00042 
00043 #include "math.h"
00044 #include "mathP.h"
00045 
00046 #ifdef __STDC__
00047 static const double
00048 #else
00049 static double
00050 #endif
00051 invsqrtpi=  5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
00052 two   =  2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
00053 one   =  1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */
00054 
00055 #ifdef __STDC__
00056 static const double zero  =  0.00000000000000000000e+00;
00057 #else
00058 static double zero  =  0.00000000000000000000e+00;
00059 #endif
00060 
00061 #ifdef __STDC__
00062     double __ieee754_jn(int n, double x)
00063 #else
00064     double __ieee754_jn(n,x)
00065     int n; double x;
00066 #endif
00067 {
00068     int32_t i,hx,ix,lx, sgn;
00069     double a, b, temp, di;
00070     double z, w;
00071 
00072     /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
00073      * Thus, J(-n,x) = J(n,-x)
00074      */
00075     EXTRACT_WORDS(hx,lx,x);
00076     ix = 0x7fffffff&hx;
00077     /* if J(n,NaN) is NaN */
00078     if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x;
00079     if(n<0){        
00080         n = -n;
00081         x = -x;
00082         hx ^= 0x80000000;
00083     }
00084     if(n==0) return(__ieee754_j0(x));
00085     if(n==1) return(__ieee754_j1(x));
00086     sgn = (n&1)&(hx>>31);   /* even n -- 0, odd n -- sign(x) */
00087     x = fabs(x);
00088     if((ix|lx)==0||ix>=0x7ff00000)  /* if x is 0 or inf */
00089         b = zero;
00090     else if((double)n<=x) {   
00091         /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
00092         if(ix>=0x52D00000) { /* x > 2**302 */
00093     /* (x >> n**2) 
00094      *      Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
00095      *      Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
00096      *      Let s=sin(x), c=cos(x), 
00097      *      xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
00098      *
00099      *         n    sin(xn)*sqt2    cos(xn)*sqt2
00100      *      ----------------------------------
00101      *         0     s-c         c+s
00102      *         1    -s-c        -c+s
00103      *         2    -s+c        -c-s
00104      *         3     s+c         c-s
00105      */
00106         switch(n&3) {
00107             case 0: temp =  cos(x)+sin(x); break;
00108             case 1: temp = -cos(x)+sin(x); break;
00109             case 2: temp = -cos(x)-sin(x); break;
00110             case 3: temp =  cos(x)-sin(x); break;
00111             default: temp = 0.0;
00112         }
00113         b = invsqrtpi*temp/sqrt(x);
00114         } else {    
00115             a = __ieee754_j0(x);
00116             b = __ieee754_j1(x);
00117             for(i=1;i<n;i++){
00118             temp = b;
00119             b = b*((double)(i+i)/x) - a; /* avoid underflow */
00120             a = temp;
00121             }
00122         }
00123     } else {
00124         if(ix<0x3e100000) { /* x < 2**-29 */
00125     /* x is tiny, return the first Taylor expansion of J(n,x) 
00126      * J(n,x) = 1/n!*(x/2)^n  - ...
00127      */
00128         if(n>33)    /* underflow */
00129             b = zero;
00130         else {
00131             temp = x*0.5; b = temp;
00132             for (a=one,i=2;i<=n;i++) {
00133             a *= (double)i;     /* a = n! */
00134             b *= temp;      /* b = (x/2)^n */
00135             }
00136             b = b/a;
00137         }
00138         } else {
00139         /* use backward recurrence */
00140         /*          x      x^2      x^2       
00141          *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
00142          *          2n  - 2(n+1) - 2(n+2)
00143          *
00144          *          1      1        1       
00145          *  (for large x)   =  ----  ------   ------   .....
00146          *          2n   2(n+1)   2(n+2)
00147          *          -- - ------ - ------ - 
00148          *           x     x         x
00149          *
00150          * Let w = 2n/x and h=2/x, then the above quotient
00151          * is equal to the continued fraction:
00152          *          1
00153          *  = -----------------------
00154          *             1
00155          *     w - -----------------
00156          *            1
00157          *          w+h - ---------
00158          *             w+2h - ...
00159          *
00160          * To determine how many terms needed, let
00161          * Q(0) = w, Q(1) = w(w+h) - 1,
00162          * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
00163          * When Q(k) > 1e4  good for single 
00164          * When Q(k) > 1e9  good for double 
00165          * When Q(k) > 1e17 good for quadruple 
00166          */
00167         /* determine k */
00168         double t,v;
00169         double q0,q1,h,tmp; int32_t k,m;
00170         w  = (n+n)/(double)x; h = 2.0/(double)x;
00171         q0 = w;  z = w+h; q1 = w*z - 1.0; k=1;
00172         while(q1<1.0e9) {
00173             k += 1; z += h;
00174             tmp = z*q1 - q0;
00175             q0 = q1;
00176             q1 = tmp;
00177         }
00178         m = n+n;
00179         for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
00180         a = t;
00181         b = one;
00182         /*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
00183          *  Hence, if n*(log(2n/x)) > ...
00184          *  single 8.8722839355e+01
00185          *  double 7.09782712893383973096e+02
00186          *  long double 1.1356523406294143949491931077970765006170e+04
00187          *  then recurrent value may overflow and the result is 
00188          *  likely underflow to zero
00189          */
00190         tmp = n;
00191         v = two/x;
00192         tmp = tmp*__ieee754_log(fabs(v*tmp));
00193         if(tmp<7.09782712893383973096e+02) {
00194                 for(i=n-1,di=(double)(i+i);i>0;i--){
00195                 temp = b;
00196             b *= di;
00197             b  = b/x - a;
00198                 a = temp;
00199             di -= two;
00200                 }
00201         } else {
00202                 for(i=n-1,di=(double)(i+i);i>0;i--){
00203                 temp = b;
00204             b *= di;
00205             b  = b/x - a;
00206                 a = temp;
00207             di -= two;
00208             /* scale b to avoid spurious overflow */
00209             if(b>1e100) {
00210                 a /= b;
00211                 t /= b;
00212                 b  = one;
00213             }
00214                 }
00215         }
00216             b = (t*__ieee754_j0(x)/b);
00217         }
00218     }
00219     if(sgn==1) return -b; else return b;
00220 }
00221 
00222 #ifdef __STDC__
00223     double __ieee754_yn(int n, double x) 
00224 #else
00225     double __ieee754_yn(n,x) 
00226     int n; double x;
00227 #endif
00228 {
00229     int32_t i,hx,ix,lx;
00230     int32_t sign;
00231     double a, b, temp;
00232 
00233     EXTRACT_WORDS(hx,lx,x);
00234     ix = 0x7fffffff&hx;
00235     /* if Y(n,NaN) is NaN */
00236     if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x;
00237     if((ix|lx)==0) return -one/zero;
00238     if(hx<0) return zero/zero;
00239     sign = 1;
00240     if(n<0){
00241         n = -n;
00242         sign = 1 - ((n&1)<<1);
00243     }
00244     if(n==0) return(__ieee754_y0(x));
00245     if(n==1) return(sign*__ieee754_y1(x));
00246     if(ix==0x7ff00000) return zero;
00247     if(ix>=0x52D00000) { /* x > 2**302 */
00248     /* (x >> n**2) 
00249      *      Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
00250      *      Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
00251      *      Let s=sin(x), c=cos(x), 
00252      *      xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
00253      *
00254      *         n    sin(xn)*sqt2    cos(xn)*sqt2
00255      *      ----------------------------------
00256      *         0     s-c         c+s
00257      *         1    -s-c        -c+s
00258      *         2    -s+c        -c-s
00259      *         3     s+c         c-s
00260      */
00261         switch(n&3) {
00262             case 0: temp =  sin(x)-cos(x); break;
00263             case 1: temp = -sin(x)-cos(x); break;
00264             case 2: temp = -sin(x)+cos(x); break;
00265             case 3: temp =  sin(x)+cos(x); break;
00266             default: temp = 0.0;
00267         }
00268         b = invsqrtpi*temp/sqrt(x);
00269     } else {
00270         u_int32_t high;
00271         a = __ieee754_y0(x);
00272         b = __ieee754_y1(x);
00273     /* quit if b is -inf */
00274         GET_HIGH_WORD(high,b);
00275         for(i=1;i<n&&high!=0xfff00000;i++){ 
00276         temp = b;
00277         b = ((double)(i+i)/x)*b - a;
00278         GET_HIGH_WORD(high,b);
00279         a = temp;
00280         }
00281     }
00282     if(sign>0) return b; else return -b;
00283 }

Generated on Tue Feb 2 17:46:05 2010 for RTAI API by  doxygen 1.4.7