source: trunk/libs/newlib/src/newlib/libm/common/sf_expm1.c @ 503

Last change on this file since 503 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 3.7 KB
Line 
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__
23static const float
24#else
25static float
26#endif
27one             = 1.0,
28huge            = 1.0e+30,
29tiny            = 1.0e-30,
30ln2_hi          = 6.9313812256e-01,/* 0x3f317180 */
31ln2_lo          = 9.0580006145e-06,/* 0x3717f7d1 */
32invln2          = 1.4426950216e+00,/* 0x3fb8aa3b */
33        /* scaled coefficients related to expm1 */
34Q1  =  -3.3333335072e-02, /* 0xbd088889 */
35Q2  =   1.5873016091e-03, /* 0x3ad00d01 */
36Q3  =  -7.9365076090e-05, /* 0xb8a670cd */
37Q4  =   4.0082177293e-06, /* 0x36867e54 */
38Q5  =  -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) */
Note: See TracBrowser for help on using the repository browser.