amath  1.8.5
Simple command line calculator
exp.c File Reference
#include "prim.h"
Include dependency graph for exp.c:

Go to the source code of this file.

Functions

double exp (double x)
 Returns the exponential of x. More...
 

Variables

static const double one = 1.0
 
static const double halF [2]
 
static const double huge = 1.0e+300
 
static const double twom1000 = 9.33263618503218878990e-302
 
static const double o_threshold = 7.09782712893383973096e+02
 
static const double u_threshold = -7.45133219101941108420e+02
 
static const double ln2HI [2]
 
static const double ln2LO [2]
 
static const double invln2 = 1.44269504088896338700e+00
 
static const double P1 = 1.66666666666666019037e-01
 
static const double P2 = -2.77777777770155933842e-03
 
static const double P3 = 6.61375632143793436117e-05
 
static const double P4 = -1.65339022054652515390e-06
 
static const double P5 = 4.13813679705723846039e-08
 

Function Documentation

◆ exp()

double exp ( double  x)

Returns the exponential of x.

Method
1. Argument reduction:
   Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
   Given x, find r and integer k such that

           x = k*ln2 + r,  |r| <= 0.5*ln2.

   Here r will be represented as r = hi-lo for better
   accuracy.

2. Approximation of exp(r) by a special rational function on
   the interval [0,0.34658]:

   Write
       R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
   We use a special Remes algorithm on [0,0.34658] to generate
   a polynomial of degree 5 to approximate R. The maximum error
   of this polynomial approximation is bounded by 2**-59. In
   other words,
       R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
       (where z=r*r, and the values of P1 to P5 are listed below)
   and

       |                  5          |     -59
       | 2.0+P1*z+...+P5*z   -  R(z) | <= 2
       |                             |

   The computation of exp(r) thus becomes
                      2*r
       exp(r) = 1 + -------
                     R - r
                          r*R1(r)
              = 1 + r + ----------- (for better accuracy)
                         2 - R1(r)
   where
                2       4                     10
       R1(r) = r - (P1*r  + P2*r  + ... + P5*r   ).

3. Scale back to obtain exp(x):
   From step 1, we have
   exp(x) = 2^k * exp(r)
Special cases:
exp(INF) is INF, exp(NaN) is NaN;
exp(-INF) is 0, and
for finite argument, only exp(0)=1 is exact.
Accuracy:
according to an error analysis, the error is always less than
1 ulp (unit in the last place).
Misc. info:
For IEEE double
    if x >  7.09782712893383973096e+02 then exp(x) overflow
    if x < -7.45133219101941108420e+02 then exp(x) underflow
Constants:
The hexadecimal values are the intended ones for the following
constants. The decimal values may be used, provided that the
compiler will convert from decimal to binary accurately enough
to produce the hexadecimal values shown.

Definition at line 138 of file exp.c.

References halF, huge, invln2, ln2HI, ln2LO, o_threshold, one, P1, P2, P3, P4, P5, twom1000, and u_threshold.

Referenced by cchsh(), cexp(), cosh(), cpow(), and sinh().

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
Here is the caller graph for this function:

Variable Documentation

◆ halF

const double halF[2]
static
Initial value:
= {
0.5, -0.5,
}

Definition at line 45 of file exp.c.

Referenced by exp().

◆ huge

const double huge = 1.0e+300
static

Definition at line 48 of file exp.c.

Referenced by exp().

◆ invln2

const double invln2 = 1.44269504088896338700e+00
static

Definition at line 59 of file exp.c.

Referenced by exp().

◆ ln2HI

const double ln2HI[2]
static
Initial value:
= {
6.93147180369123816490e-01,
-6.93147180369123816490e-01,
}

Definition at line 51 of file exp.c.

Referenced by exp().

◆ ln2LO

const double ln2LO[2]
static
Initial value:
= {
1.90821492927058770002e-10,
-1.90821492927058770002e-10,
}

Definition at line 55 of file exp.c.

Referenced by exp().

◆ o_threshold

const double o_threshold = 7.09782712893383973096e+02
static

Definition at line 49 of file exp.c.

Referenced by exp().

◆ one

const double one = 1.0
static

Definition at line 44 of file exp.c.

Referenced by exp().

◆ P1

const double P1 = 1.66666666666666019037e-01
static

Definition at line 60 of file exp.c.

Referenced by exp().

◆ P2

const double P2 = -2.77777777770155933842e-03
static

Definition at line 61 of file exp.c.

Referenced by exp().

◆ P3

const double P3 = 6.61375632143793436117e-05
static

Definition at line 62 of file exp.c.

Referenced by exp().

◆ P4

const double P4 = -1.65339022054652515390e-06
static

Definition at line 63 of file exp.c.

Referenced by exp().

◆ P5

const double P5 = 4.13813679705723846039e-08
static

Definition at line 64 of file exp.c.

Referenced by exp().

◆ twom1000

const double twom1000 = 9.33263618503218878990e-302
static

Definition at line 48 of file exp.c.

Referenced by exp().

◆ u_threshold

const double u_threshold = -7.45133219101941108420e+02
static

Definition at line 50 of file exp.c.

Referenced by exp().