Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /* ef_jn.c -- float version of e_jn.c.
  2.  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
  3.  */
  4.  
  5. /*
  6.  * ====================================================
  7.  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  8.  *
  9.  * Developed at SunPro, a Sun Microsystems, Inc. business.
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software is freely granted, provided that this notice
  12.  * is preserved.
  13.  * ====================================================
  14.  */
  15.  
  16. #include "fdlibm.h"
  17.  
  18. #ifdef __STDC__
  19. static const float
  20. #else
  21. static float
  22. #endif
  23. invsqrtpi=  5.6418961287e-01, /* 0x3f106ebb */
  24. two   =  2.0000000000e+00, /* 0x40000000 */
  25. one   =  1.0000000000e+00; /* 0x3F800000 */
  26.  
  27. #ifdef __STDC__
  28. static const float zero  =  0.0000000000e+00;
  29. #else
  30. static float zero  =  0.0000000000e+00;
  31. #endif
  32.  
  33. #ifdef __STDC__
  34.         float __ieee754_jnf(int n, float x)
  35. #else
  36.         float __ieee754_jnf(n,x)
  37.         int n; float x;
  38. #endif
  39. {
  40.         __int32_t i,hx,ix, sgn;
  41.         float a, b, temp, di;
  42.         float z, w;
  43.  
  44.     /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
  45.      * Thus, J(-n,x) = J(n,-x)
  46.      */
  47.         GET_FLOAT_WORD(hx,x);
  48.         ix = 0x7fffffff&hx;
  49.     /* if J(n,NaN) is NaN */
  50.         if(FLT_UWORD_IS_NAN(ix)) return x+x;
  51.         if(n<0){               
  52.                 n = -n;
  53.                 x = -x;
  54.                 hx ^= 0x80000000;
  55.         }
  56.         if(n==0) return(__ieee754_j0f(x));
  57.         if(n==1) return(__ieee754_j1f(x));
  58.         sgn = (n&1)&(hx>>31);   /* even n -- 0, odd n -- sign(x) */
  59.         x = fabsf(x);
  60.         if(FLT_UWORD_IS_ZERO(ix)||FLT_UWORD_IS_INFINITE(ix))
  61.             b = zero;
  62.         else if((float)n<=x) {  
  63.                 /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
  64.             a = __ieee754_j0f(x);
  65.             b = __ieee754_j1f(x);
  66.             for(i=1;i<n;i++){
  67.                 temp = b;
  68.                 b = b*((float)(i+i)/x) - a; /* avoid underflow */
  69.                 a = temp;
  70.             }
  71.         } else {
  72.             if(ix<0x30800000) { /* x < 2**-29 */
  73.     /* x is tiny, return the first Taylor expansion of J(n,x)
  74.      * J(n,x) = 1/n!*(x/2)^n  - ...
  75.      */
  76.                 if(n>33)        /* underflow */
  77.                     b = zero;
  78.                 else {
  79.                     temp = x*(float)0.5; b = temp;
  80.                     for (a=one,i=2;i<=n;i++) {
  81.                         a *= (float)i;          /* a = n! */
  82.                         b *= temp;              /* b = (x/2)^n */
  83.                     }
  84.                     b = b/a;
  85.                 }
  86.             } else {
  87.                 /* use backward recurrence */
  88.                 /*                      x      x^2      x^2      
  89.                  *  J(n,x)/J(n-1,x) =  ----   ------   ------   .....
  90.                  *                      2n  - 2(n+1) - 2(n+2)
  91.                  *
  92.                  *                      1      1        1      
  93.                  *  (for large x)   =  ----  ------   ------   .....
  94.                  *                      2n   2(n+1)   2(n+2)
  95.                  *                      -- - ------ - ------ -
  96.                  *                       x     x         x
  97.                  *
  98.                  * Let w = 2n/x and h=2/x, then the above quotient
  99.                  * is equal to the continued fraction:
  100.                  *                  1
  101.                  *      = -----------------------
  102.                  *                     1
  103.                  *         w - -----------------
  104.                  *                        1
  105.                  *              w+h - ---------
  106.                  *                     w+2h - ...
  107.                  *
  108.                  * To determine how many terms needed, let
  109.                  * Q(0) = w, Q(1) = w(w+h) - 1,
  110.                  * Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
  111.                  * When Q(k) > 1e4      good for single
  112.                  * When Q(k) > 1e9      good for double
  113.                  * When Q(k) > 1e17     good for quadruple
  114.                  */
  115.             /* determine k */
  116.                 float t,v;
  117.                 float q0,q1,h,tmp; __int32_t k,m;
  118.                 w  = (n+n)/(float)x; h = (float)2.0/(float)x;
  119.                 q0 = w;  z = w+h; q1 = w*z - (float)1.0; k=1;
  120.                 while(q1<(float)1.0e9) {
  121.                         k += 1; z += h;
  122.                         tmp = z*q1 - q0;
  123.                         q0 = q1;
  124.                         q1 = tmp;
  125.                 }
  126.                 m = n+n;
  127.                 for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
  128.                 a = t;
  129.                 b = one;
  130.                 /*  estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
  131.                  *  Hence, if n*(log(2n/x)) > ...
  132.                  *  single 8.8722839355e+01
  133.                  *  double 7.09782712893383973096e+02
  134.                  *  long double 1.1356523406294143949491931077970765006170e+04
  135.                  *  then recurrent value may overflow and the result is
  136.                  *  likely underflow to zero
  137.                  */
  138.                 tmp = n;
  139.                 v = two/x;
  140.                 tmp = tmp*__ieee754_logf(fabsf(v*tmp));
  141.                 if(tmp<(float)8.8721679688e+01) {
  142.                     for(i=n-1,di=(float)(i+i);i>0;i--){
  143.                         temp = b;
  144.                         b *= di;
  145.                         b  = b/x - a;
  146.                         a = temp;
  147.                         di -= two;
  148.                     }
  149.                 } else {
  150.                     for(i=n-1,di=(float)(i+i);i>0;i--){
  151.                         temp = b;
  152.                         b *= di;
  153.                         b  = b/x - a;
  154.                         a = temp;
  155.                         di -= two;
  156.                     /* scale b to avoid spurious overflow */
  157.                         if(b>(float)1e10) {
  158.                             a /= b;
  159.                             t /= b;
  160.                             b  = one;
  161.                         }
  162.                     }
  163.                 }
  164.                 b = (t*__ieee754_j0f(x)/b);
  165.             }
  166.         }
  167.         if(sgn==1) return -b; else return b;
  168. }
  169.  
  170. #ifdef __STDC__
  171.         float __ieee754_ynf(int n, float x)
  172. #else
  173.         float __ieee754_ynf(n,x)
  174.         int n; float x;
  175. #endif
  176. {
  177.         __int32_t i,hx,ix,ib;
  178.         __int32_t sign;
  179.         float a, b, temp;
  180.  
  181.         GET_FLOAT_WORD(hx,x);
  182.         ix = 0x7fffffff&hx;
  183.     /* if Y(n,NaN) is NaN */
  184.         if(FLT_UWORD_IS_NAN(ix)) return x+x;
  185.         if(FLT_UWORD_IS_ZERO(ix)) return -one/zero;
  186.         if(hx<0) return zero/zero;
  187.         sign = 1;
  188.         if(n<0){
  189.                 n = -n;
  190.                 sign = 1 - ((n&1)<<1);
  191.         }
  192.         if(n==0) return(__ieee754_y0f(x));
  193.         if(n==1) return(sign*__ieee754_y1f(x));
  194.         if(FLT_UWORD_IS_INFINITE(ix)) return zero;
  195.  
  196.         a = __ieee754_y0f(x);
  197.         b = __ieee754_y1f(x);
  198.         /* quit if b is -inf */
  199.         GET_FLOAT_WORD(ib,b);
  200.         for(i=1;i<n&&ib!=0xff800000;i++){
  201.             temp = b;
  202.             b = ((float)(i+i)/x)*b - a;
  203.             GET_FLOAT_WORD(ib,b);
  204.             a = temp;
  205.         }
  206.         if(sign>0) return b; else return -b;
  207. }
  208.