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

Go to the source code of this file.

Functions

double expm1 (double x)
 

Variables

static const double one = 1.0
 
static const double huge = 1.0e+300
 
static const double tiny = 1.0e-300
 
static const double o_threshold = 7.09782712893383973096e+02
 
static const double ln2_hi = 6.93147180369123816490e-01
 
static const double ln2_lo = 1.90821492927058770002e-10
 
static const double invln2 = 1.44269504088896338700e+00
 
static const double Q1 = -3.33333333333331316428e-02
 
static const double Q2 = 1.58730158725481460165e-03
 
static const double Q3 = -7.93650757867487942473e-05
 
static const double Q4 = 4.00821782732936239552e-06
 
static const double Q5 = -2.01099218183624371326e-07
 

Function Documentation

◆ expm1()

double expm1 ( double  x)

Definition at line 153 of file expm1.c.

References huge, invln2, ln2_hi, ln2_lo, o_threshold, one, Q1, Q2, Q3, Q4, Q5, and tiny.

Referenced by cosh(), sinh(), and tanh().

154 {
155  double y, hi, lo, c, t, e, hxs, hfx, r1;
156  int32_t k, xsb;
157  uint32_t hx;
158 
159  c = 0.0;
160 
161  GET_HIGH_WORD(hx, x); /* high word of x */
162  xsb = hx & 0x80000000; /* sign bit of x */
163  hx &= 0x7fffffff; /* high word of |x| */
164 
165  /* filter out huge and non-finite argument */
166  if (hx >= 0x4043687A)
167  { /* if |x|>=56*ln2 */
168  if (hx >= 0x40862E42)
169  { /* if |x|>=709.78... */
170  if (hx >= 0x7ff00000)
171  {
172  uint32_t low;
173  GET_LOW_WORD(low, x);
174  if (((hx & 0xfffff) | low) != 0)
175  return x + x; /* NaN */
176  else
177  return (xsb == 0) ? x : -1.0; /* exp(+-inf)={inf,-1} */
178  }
179  if (x > o_threshold)
180  return huge * huge; /* overflow */
181  }
182  if (xsb != 0)
183  { /* x < -56*ln2, return -1.0 with inexact */
184  if (x + tiny < 0.0) /* raise inexact */
185  return tiny - one; /* return -1 */
186  }
187  }
188 
189  /* argument reduction */
190  if (hx > 0x3fd62e42)
191  { /* if |x| > 0.5 ln2 */
192  if (hx < 0x3FF0A2B2)
193  { /* and |x| < 1.5 ln2 */
194  if (xsb == 0)
195  {
196  hi = x - ln2_hi;
197  lo = ln2_lo;
198  k = 1;
199  }
200  else
201  {
202  hi = x + ln2_hi;
203  lo = -ln2_lo;
204  k = -1;
205  }
206  }
207  else
208  {
209  k = (int32_t)(invln2 * x + ((xsb == 0) ? 0.5 : -0.5));
210  t = k;
211  hi = x - t * ln2_hi; /* t*ln2_hi is exact here */
212  lo = t * ln2_lo;
213  }
214  x = hi - lo;
215  c = (hi - x) - lo;
216  }
217  else if (hx < 0x3c900000)
218  { /* when |x|<2**-54, return x */
219  t = huge + x; /* return x with inexact flags when x!=0 */
220  return x - (t - (huge + x));
221  }
222  else
223  k = 0;
224 
225  /* x is now in primary range */
226  hfx = 0.5 * x;
227  hxs = x * hfx;
228  r1 = one + hxs * (Q1 + hxs * (Q2 + hxs * (Q3 + hxs * (Q4 + hxs * Q5))));
229  t = 3.0 - r1 * hfx;
230  e = hxs * ((r1 - t) / (6.0 - x * t));
231  if (k == 0)
232  return x - (x * e - hxs); /* c is 0 */
233  else
234  {
235  e = (x * (e - c) - c);
236  e -= hxs;
237  if (k == -1)
238  return 0.5 * (x - e) - 0.5;
239  if (k == 1)
240  {
241  if (x < -0.25)
242  return -2.0 * (e - (x + 0.5));
243  else
244  return one + 2.0 * (x - e);
245  }
246  if (k <= -2 || k > 56)
247  { /* suffice to return exp(x)-1 */
248  uint32_t hy;
249 
250  y = one - (e - x);
251  GET_HIGH_WORD(hy, y);
252  SET_HIGH_WORD(y, hy + (k << 20)); /* add k to y's exponent */
253  return y - one;
254  }
255  t = one;
256  if (k < 20)
257  {
258  uint32_t hy;
259 
260  SET_HIGH_WORD(t, 0x3ff00000 - (0x200000 >> k)); /* t=1-2^-k */
261  y = t - (e - x);
262  GET_HIGH_WORD(hy, y);
263  SET_HIGH_WORD(y, hy + (k << 20)); /* add k to y's exponent */
264  }
265  else
266  {
267  uint32_t hy;
268 
269  SET_HIGH_WORD(t, (0x3ff - k) << 20); /* 2^-k */
270  y = x - (e + t);
271  y += one;
272  GET_HIGH_WORD(hy, y);
273  SET_HIGH_WORD(y, hy + (k << 20)); /* add k to y's exponent */
274  }
275  }
276  return y;
277 }
#define GET_HIGH_WORD(i, d)
Get the more significant 32 bit int from a double.
Definition: prim.h:167
static const double tiny
Definition: expm1.c:141
static const double Q5
Definition: expm1.c:151
static const double Q1
Definition: expm1.c:147
#define GET_LOW_WORD(i, d)
Get the less significant 32 bit int from a double.
Definition: prim.h:177
static const double Q2
Definition: expm1.c:148
static const double one
Definition: expm1.c:139
static const double o_threshold
Definition: expm1.c:142
static const double ln2_hi
Definition: expm1.c:143
static const double huge
Definition: expm1.c:140
static const double invln2
Definition: expm1.c:145
static const double ln2_lo
Definition: expm1.c:144
static const double Q4
Definition: expm1.c:150
#define SET_HIGH_WORD(d, v)
Set the more significant 32 bits of a double from an int.
Definition: prim.h:198
static const double Q3
Definition: expm1.c:149
Here is the caller graph for this function:

Variable Documentation

◆ huge

const double huge = 1.0e+300
static

Definition at line 140 of file expm1.c.

Referenced by expm1().

◆ invln2

const double invln2 = 1.44269504088896338700e+00
static

Definition at line 145 of file expm1.c.

Referenced by expm1().

◆ ln2_hi

const double ln2_hi = 6.93147180369123816490e-01
static

Definition at line 143 of file expm1.c.

Referenced by expm1().

◆ ln2_lo

const double ln2_lo = 1.90821492927058770002e-10
static

Definition at line 144 of file expm1.c.

Referenced by expm1().

◆ o_threshold

const double o_threshold = 7.09782712893383973096e+02
static

Definition at line 142 of file expm1.c.

Referenced by expm1().

◆ one

const double one = 1.0
static

Definition at line 139 of file expm1.c.

Referenced by expm1().

◆ Q1

const double Q1 = -3.33333333333331316428e-02
static

Definition at line 147 of file expm1.c.

Referenced by expm1().

◆ Q2

const double Q2 = 1.58730158725481460165e-03
static

Definition at line 148 of file expm1.c.

Referenced by expm1().

◆ Q3

const double Q3 = -7.93650757867487942473e-05
static

Definition at line 149 of file expm1.c.

Referenced by expm1().

◆ Q4

const double Q4 = 4.00821782732936239552e-06
static

Definition at line 150 of file expm1.c.

Referenced by expm1().

◆ Q5

const double Q5 = -2.01099218183624371326e-07
static

Definition at line 151 of file expm1.c.

Referenced by expm1().

◆ tiny

const double tiny = 1.0e-300
static

Definition at line 141 of file expm1.c.

Referenced by expm1().