amath  1.8.5
Simple command line calculator
exp.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2014-2018 Carsten Sonne Larsen <cs@innolan.net>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * Project homepage:
26  * https://amath.innolan.net
27  *
28  * The original source code can be obtained from:
29  * http://www.netlib.org/fdlibm/e_exp.c
30  *
31  * =================================================================
32  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
33  *
34  * Developed at SunSoft, a Sun Microsystems, Inc. business.
35  * Permission to use, copy, modify, and distribute this
36  * software is freely granted, provided that this notice
37  * is preserved.
38  * =================================================================
39  */
40 
41 #include "prim.h"
42 
43 static const double
44  one = 1.0,
45  halF[2] = {
46  0.5, -0.5,
47 },
48  huge = 1.0e+300, twom1000 = 9.33263618503218878990e-302, /* 2**-1000=0x01700000,0*/
49  o_threshold = 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */
50  u_threshold = -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */
51  ln2HI[2] = {
52  6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */
53  -6.93147180369123816490e-01, /* 0xbfe62e42, 0xfee00000 */
54 },
55  ln2LO[2] = {
56  1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */
57  -1.90821492927058770002e-10, /* 0xbdea39ef, 0x35793c76 */
58 },
59  invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */
60  P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
61  P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
62  P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
63  P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
64  P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */
65 
66 /**
67  * @brief Returns the exponential of x
68  * @details
69  * <pre>
70  * Method
71  *
72  * 1. Argument reduction:
73  * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
74  * Given x, find r and integer k such that
75  *
76  * x = k*ln2 + r, |r| <= 0.5*ln2.
77  *
78  * Here r will be represented as r = hi-lo for better
79  * accuracy.
80  *
81  * 2. Approximation of exp(r) by a special rational function on
82  * the interval [0,0.34658]:
83  *
84  * Write
85  * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
86  * We use a special Remes algorithm on [0,0.34658] to generate
87  * a polynomial of degree 5 to approximate R. The maximum error
88  * of this polynomial approximation is bounded by 2**-59. In
89  * other words,
90  * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
91  * (where z=r*r, and the values of P1 to P5 are listed below)
92  * and
93  *
94  * | 5 | -59
95  * | 2.0+P1*z+...+P5*z - R(z) | <= 2
96  * | |
97  *
98  * The computation of exp(r) thus becomes
99  * 2*r
100  * exp(r) = 1 + -------
101  * R - r
102  * r*R1(r)
103  * = 1 + r + ----------- (for better accuracy)
104  * 2 - R1(r)
105  * where
106  * 2 4 10
107  * R1(r) = r - (P1*r + P2*r + ... + P5*r ).
108  *
109  * 3. Scale back to obtain exp(x):
110  * From step 1, we have
111  * exp(x) = 2^k * exp(r)
112  *
113  * Special cases:
114  *
115  * exp(INF) is INF, exp(NaN) is NaN;
116  * exp(-INF) is 0, and
117  * for finite argument, only exp(0)=1 is exact.
118  *
119  * Accuracy:
120  *
121  * according to an error analysis, the error is always less than
122  * 1 ulp (unit in the last place).
123  *
124  * Misc. info:
125  *
126  * For IEEE double
127  * if x > 7.09782712893383973096e+02 then exp(x) overflow
128  * if x < -7.45133219101941108420e+02 then exp(x) underflow
129  *
130  * Constants:
131  *
132  * The hexadecimal values are the intended ones for the following
133  * constants. The decimal values may be used, provided that the
134  * compiler will convert from decimal to binary accurately enough
135  * to produce the hexadecimal values shown.
136  * </pre>
137  */
138 double exp(double x)
139 {
140  double y, hi, lo, c, t;
141  int32_t k, xsb;
142  uint32_t hx, hy;
143 
144  lo = 0.0;
145  hi = 0.0;
146 
147  GET_HIGH_WORD(hx, x); // high word of x
148  xsb = (hx >> 31) & 1; // sign bit of x
149  hx &= 0x7FFFFFFF; // high word of |x|
150 
151  // filter out non-finite argument
152  // if |x|>=709.78...
153  if (hx >= 0x40862E42)
154  {
155  if (hx >= 0x7FF00000)
156  {
157  uint32_t lx;
158  GET_LOW_WORD(lx, x);
159  if (((hx & 0xFFFFF) | lx) != 0)
160  {
161  return NAN;
162  }
163 
164  // exp(+-inf)={inf,0}
165  return (xsb == 0) ? x : 0.0;
166  }
167 
168  if (x > o_threshold)
169  {
170  // overflow
171  return huge * huge;
172  }
173 
174  if (x < u_threshold)
175  {
176  // underflow
177  return twom1000 * twom1000;
178  }
179  }
180 
181  // argument reduction
182  // |x| > 0.5 ln2
183  if (hx > 0x3FD62E42)
184  {
185  // |x| < 1.5 ln2
186  if (hx < 0x3FF0A2B2)
187  {
188  hi = x - ln2HI[xsb];
189  lo = ln2LO[xsb];
190  k = 1 - xsb - xsb;
191  }
192  else
193  {
194  k = (int32_t)(invln2 * x + halF[xsb]);
195  t = k;
196  hi = x - t * ln2HI[0]; // t*ln2HI is exact here
197  lo = t * ln2LO[0];
198  }
199  x = hi - lo;
200  }
201  // when |x|<2**-28
202  else if (hx < 0x3E300000)
203  {
204  if (huge + x > one)
205  {
206  return one + x; // trigger inexact
207  }
208  else
209  {
210  k = 0;
211  }
212  }
213  else
214  {
215  k = 0;
216  }
217 
218  // x is now in primary range
219  t = x * x;
220  c = x - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
221  if (k == 0)
222  {
223  return one - ((x * c) / (c - 2.0) - x);
224  }
225 
226  y = one - ((lo - (x * c) / (2.0 - c)) - hi);
227 
228  if (k >= -1021)
229  {
230  GET_HIGH_WORD(hy, y);
231  SET_HIGH_WORD(y, hy + (k << 20)); // add k to y's exponent
232  return y;
233  }
234 
235  GET_HIGH_WORD(hy, y);
236  SET_HIGH_WORD(y, hy + ((k + 1000) << 20)); // add k to y's exponent
237  return y * twom1000;
238 }
static const double halF[2]
Definition: exp.c:45
#define GET_HIGH_WORD(i, d)
Get the more significant 32 bit int from a double.
Definition: prim.h:167
static const double u_threshold
Definition: exp.c:50
static const double P2
Definition: exp.c:61
static const double P5
Definition: exp.c:64
#define GET_LOW_WORD(i, d)
Get the less significant 32 bit int from a double.
Definition: prim.h:177
static const double ln2LO[2]
Definition: exp.c:55
static const double ln2HI[2]
Definition: exp.c:51
static const double twom1000
Definition: exp.c:48
static const double one
Definition: exp.c:44
static const double huge
Definition: exp.c:48
static const double P3
Definition: exp.c:62
#define NAN
Definition: mathr.h:53
static const double P1
Definition: exp.c:60
static const double P4
Definition: exp.c:63
static const double o_threshold
Definition: exp.c:49
static const double invln2
Definition: exp.c:59
#define SET_HIGH_WORD(d, v)
Set the more significant 32 bits of a double from an int.
Definition: prim.h:198
double exp(double x)
Returns the exponential of x.
Definition: exp.c:138