Subversion Repositories Kolibri OS

Rev

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

  1. /* sf_expm1.c -- float version of s_expm1.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 __v810__
  19. #define const
  20. #endif
  21.  
  22. #ifdef __STDC__
  23. static const float
  24. #else
  25. static float
  26. #endif
  27. one             = 1.0,
  28. huge            = 1.0e+30,
  29. tiny            = 1.0e-30,
  30. ln2_hi          = 6.9313812256e-01,/* 0x3f317180 */
  31. ln2_lo          = 9.0580006145e-06,/* 0x3717f7d1 */
  32. invln2          = 1.4426950216e+00,/* 0x3fb8aa3b */
  33.         /* scaled coefficients related to expm1 */
  34. Q1  =  -3.3333335072e-02, /* 0xbd088889 */
  35. Q2  =   1.5873016091e-03, /* 0x3ad00d01 */
  36. Q3  =  -7.9365076090e-05, /* 0xb8a670cd */
  37. Q4  =   4.0082177293e-06, /* 0x36867e54 */
  38. Q5  =  -2.0109921195e-07; /* 0xb457edbb */
  39.  
  40. #ifdef __STDC__
  41.         float expm1f(float x)
  42. #else
  43.         float expm1f(x)
  44.         float x;
  45. #endif
  46. {
  47.         float y,hi,lo,c,t,e,hxs,hfx,r1;
  48.         __int32_t k,xsb;
  49.         __uint32_t hx;
  50.  
  51.         GET_FLOAT_WORD(hx,x);
  52.         xsb = hx&0x80000000;            /* sign bit of x */
  53.         if(xsb==0) y=x; else y= -x;     /* y = |x| */
  54.         hx &= 0x7fffffff;               /* high word of |x| */
  55.  
  56.     /* filter out huge and non-finite argument */
  57.         if(hx >= 0x4195b844) {                  /* if |x|>=27*ln2 */
  58.             if(FLT_UWORD_IS_NAN(hx))
  59.                 return x+x;
  60.             if(FLT_UWORD_IS_INFINITE(hx))
  61.                 return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */
  62.             if(xsb == 0 && hx > FLT_UWORD_LOG_MAX) /* if x>=o_threshold */
  63.                 return huge*huge; /* overflow */
  64.             if(xsb!=0) { /* x < -27*ln2, return -1.0 with inexact */
  65.                 if(x+tiny<(float)0.0)   /* raise inexact */
  66.                 return tiny-one;        /* return -1 */
  67.             }
  68.         }
  69.  
  70.     /* argument reduction */
  71.         if(hx > 0x3eb17218) {           /* if  |x| > 0.5 ln2 */
  72.             if(hx < 0x3F851592) {       /* and |x| < 1.5 ln2 */
  73.                 if(xsb==0)
  74.                     {hi = x - ln2_hi; lo =  ln2_lo;  k =  1;}
  75.                 else
  76.                     {hi = x + ln2_hi; lo = -ln2_lo;  k = -1;}
  77.             } else {
  78.                 k  = invln2*x+((xsb==0)?(float)0.5:(float)-0.5);
  79.                 t  = k;
  80.                 hi = x - t*ln2_hi;      /* t*ln2_hi is exact here */
  81.                 lo = t*ln2_lo;
  82.             }
  83.             x  = hi - lo;
  84.             c  = (hi-x)-lo;
  85.         }
  86.         else if(hx < 0x33000000) {      /* when |x|<2**-25, return x */
  87.             t = huge+x; /* return x with inexact flags when x!=0 */
  88.             return x - (t-(huge+x));   
  89.         }
  90.         else k = 0;
  91.  
  92.     /* x is now in primary range */
  93.         hfx = (float)0.5*x;
  94.         hxs = x*hfx;
  95.         r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
  96.         t  = (float)3.0-r1*hfx;
  97.         e  = hxs*((r1-t)/((float)6.0 - x*t));
  98.         if(k==0) return x - (x*e-hxs);          /* c is 0 */
  99.         else {
  100.             e  = (x*(e-c)-c);
  101.             e -= hxs;
  102.             if(k== -1) return (float)0.5*(x-e)-(float)0.5;
  103.            if(k==1) {
  104.                 if(x < (float)-0.25) return -(float)2.0*(e-(x+(float)0.5));
  105.                 else          return  one+(float)2.0*(x-e);
  106.            }
  107.             if (k <= -2 || k>56) {   /* suffice to return exp(x)-1 */
  108.                 __int32_t i;
  109.                 y = one-(e-x);
  110.                 GET_FLOAT_WORD(i,y);
  111.                 SET_FLOAT_WORD(y,i+(k<<23));    /* add k to y's exponent */
  112.                 return y-one;
  113.             }
  114.             t = one;
  115.             if(k<23) {
  116.                 __int32_t i;
  117.                 SET_FLOAT_WORD(t,0x3f800000 - (0x1000000>>k)); /* t=1-2^-k */
  118.                 y = t-(e-x);
  119.                 GET_FLOAT_WORD(i,y);
  120.                 SET_FLOAT_WORD(y,i+(k<<23));    /* add k to y's exponent */
  121.            } else {
  122.                 __int32_t i;
  123.                 SET_FLOAT_WORD(t,((0x7f-k)<<23));       /* 2^-k */
  124.                 y = x-(e+t);
  125.                 y += one;
  126.                 GET_FLOAT_WORD(i,y);
  127.                 SET_FLOAT_WORD(y,i+(k<<23));    /* add k to y's exponent */
  128.             }
  129.         }
  130.         return y;
  131. }
  132.  
  133. #ifdef _DOUBLE_IS_32BITS
  134.  
  135. #ifdef __STDC__
  136.         double expm1(double x)
  137. #else
  138.         double expm1(x)
  139.         double x;
  140. #endif
  141. {
  142.         return (double) expm1f((float) x);
  143. }
  144.  
  145. #endif /* defined(_DOUBLE_IS_32BITS) */
  146.