123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- #if defined(LIBM_SCCS) && !defined(lint)
- static char rcsid[] = "$NetBSD: s_expm1.c,v 1.8 1995/05/10 20:47:09 jtc Exp $";
- #endif
- #include "math.h"
- #include "math_private.h"
- #ifdef __STDC__
- static const double
- #else
- static double
- #endif
- one = 1.0,
- huge = 1.0e+300,
- tiny = 1.0e-300,
- o_threshold = 7.09782712893383973096e+02,
- ln2_hi = 6.93147180369123816490e-01,
- ln2_lo = 1.90821492927058770002e-10,
- invln2 = 1.44269504088896338700e+00,
-
- Q1 = -3.33333333333331316428e-02,
- Q2 = 1.58730158725481460165e-03,
- Q3 = -7.93650757867487942473e-05,
- Q4 = 4.00821782732936239552e-06,
- Q5 = -2.01099218183624371326e-07;
- libm_hidden_proto(expm1)
- #ifdef __STDC__
- double expm1(double x)
- #else
- double expm1(x)
- double x;
- #endif
- {
- double y,hi,lo,c=0.0,t,e,hxs,hfx,r1;
- int32_t k,xsb;
- u_int32_t hx;
- GET_HIGH_WORD(hx,x);
- xsb = hx&0x80000000;
- if(xsb==0) y=x; else y= -x;
- hx &= 0x7fffffff;
-
- if(hx >= 0x4043687A) {
- if(hx >= 0x40862E42) {
- if(hx>=0x7ff00000) {
- u_int32_t low;
- GET_LOW_WORD(low,x);
- if(((hx&0xfffff)|low)!=0)
- return x+x;
- else return (xsb==0)? x:-1.0;
- }
- if(x > o_threshold) return huge*huge;
- }
- if(xsb!=0) {
- if(x+tiny<0.0)
- return tiny-one;
- }
- }
-
- if(hx > 0x3fd62e42) {
- if(hx < 0x3FF0A2B2) {
- if(xsb==0)
- {hi = x - ln2_hi; lo = ln2_lo; k = 1;}
- else
- {hi = x + ln2_hi; lo = -ln2_lo; k = -1;}
- } else {
- k = invln2*x+((xsb==0)?0.5:-0.5);
- t = k;
- hi = x - t*ln2_hi;
- lo = t*ln2_lo;
- }
- x = hi - lo;
- c = (hi-x)-lo;
- }
- else if(hx < 0x3c900000) {
- t = huge+x;
- return x - (t-(huge+x));
- }
- else k = 0;
-
- hfx = 0.5*x;
- hxs = x*hfx;
- r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
- t = 3.0-r1*hfx;
- e = hxs*((r1-t)/(6.0 - x*t));
- if(k==0) return x - (x*e-hxs);
- else {
- e = (x*(e-c)-c);
- e -= hxs;
- if(k== -1) return 0.5*(x-e)-0.5;
- if(k==1) {
- if(x < -0.25) return -2.0*(e-(x+0.5));
- else return one+2.0*(x-e);
- }
- if (k <= -2 || k>56) {
- u_int32_t high;
- y = one-(e-x);
- GET_HIGH_WORD(high,y);
- SET_HIGH_WORD(y,high+(k<<20));
- return y-one;
- }
- t = one;
- if(k<20) {
- u_int32_t high;
- SET_HIGH_WORD(t,0x3ff00000 - (0x200000>>k));
- y = t-(e-x);
- GET_HIGH_WORD(high,y);
- SET_HIGH_WORD(y,high+(k<<20));
- } else {
- u_int32_t high;
- SET_HIGH_WORD(t,((0x3ff-k)<<20));
- y = x-(e+t);
- y += one;
- GET_HIGH_WORD(high,y);
- SET_HIGH_WORD(y,high+(k<<20));
- }
- }
- return y;
- }
- libm_hidden_def(expm1)
|