added math libs of Jesus Calvino-Fraga
[fw/sdcc] / device / lib / expf.c
1 /*  expf.c: Computes e**x of a 32-bit float as outlined in [1]
2
3     Copyright (C) 2001, 2002  Jesus Calvino-Fraga, jesusc@ieee.org 
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Lesser General Public
7     License as published by the Free Software Foundation; either
8     version 2.1 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Lesser General Public License for more details.
14
15     You should have received a copy of the GNU Lesser General Public
16     License along with this library; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */
18
19 /* [1] William James Cody and W.  M.  Waite.  _Software manual for the
20    elementary functions_, Englewood Cliffs, N.J.:Prentice-Hall, 1980. */
21
22 /* Version 1.0 - Initial release */
23
24 #include <math.h>
25 #include <errno.h>
26
27 #define P0      0.2499999995E+0
28 #define P1      0.4160288626E-2
29 #define Q0      0.5000000000E+0
30 #define Q1      0.4998717877E-1
31
32 #define P(z) ((P1*z)+P0)
33 #define Q(z) ((Q1*z)+Q0)
34
35 #define C1       0.693359375
36 #define C2      -2.1219444005469058277e-4
37
38 #define BIGX    88.72283911  /* ln(XMAX) */
39 #define EXPEPS  1.0E-7       /* exp(1.0E-7)=0.0000001 */
40 #define K1      1.4426950409 /* 1/ln(2) */
41
42 float expf(const float x)
43 {
44     int n;
45     float xn, g, r, z, y;
46     int sign;
47
48     if(x>=0.0)
49         { y=x;  sign=0; }
50     else
51         { y=-x; sign=1; }
52
53     if(y<EXPEPS) return 1.0;
54
55     if(y>BIGX)
56     {
57         if(sign)
58         {
59             errno=ERANGE;
60             return XMAX;
61         }
62         else
63         {
64             return 0.0;
65         }
66     }
67
68     z=y*K1;
69     n=z;
70
71     if(n<0) --n;
72     if(z-n>=0.5) ++n;
73     xn=n;
74     g=((y-xn*C1))-xn*C2;
75     z=g*g;
76     r=P(z)*g;
77     r=0.5+(r/(Q(z)-r));
78
79     n++;
80     z=ldexpf(r, n);
81     if(sign)
82         return 1.0/z;
83     else
84         return z;
85 }
86