amath  1.8.5
Simple command line calculator
pow.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_pow.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 /**
42  * @file pow.c
43  * @brief Expontation function
44  */
45 
46 #include "prim.h"
47 
48 #ifdef __clang__
49 #pragma clang diagnostic ignored "-Wunused-variable"
50 #pragma clang diagnostic ignored "-Wstrict-aliasing"
51 #elif defined(__GNUC__) && __GNUC__ > 2
52 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
53 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
54 #endif
55 
56 static const double
57  bp[] = {
58  1.0, 1.5,
59 },
60  dp_h[] = {
61  0.0, 5.84962487220764160156e-01,
62 }, /* 0x3FE2B803, 0x40000000 */
63  dp_l[] = {
64  0.0, 1.35003920212974897128e-08,
65 }, /* 0x3E4CFDEB, 0x43CFD006 */
66  zero = 0.0,
67  one = 1.0, two = 2.0, two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */
68  huge = 1.0e300, tiny = 1.0e-300,
69  /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
70  L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
71  L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
72  L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
73  L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
74  L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
75  L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
76  P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
77  P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
78  P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
79  P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
80  P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
81  lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
82  lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
83  lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
84  ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
85  cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
86  cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
87  cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
88  ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
89  ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
90  ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
91 
92 /**
93  * @brief Expontation function
94  * @details
95  * <pre>
96  * Method: Let x = 2 * (1+f)
97  * 1. Compute and return log2(x) in two pieces:
98  * log2(x) = w1 + w2,
99  * where w1 has 53-24 = 29 bit trailing zeros.
100  * 2. Perform y*log2(x) = n+y' by simulating muti-precision
101  * arithmetic, where |y'|<=0.5.
102  * 3. Return x**y = 2**n*exp(y'*log2)
103  *
104  * Special cases:
105  * 1. (anything) ** 0 is 1
106  * 2. (anything) ** 1 is itself
107  * 3. (anything) ** NAN is NAN
108  * 4. NAN ** (anything except 0) is NAN
109  * 5. +-(|x| > 1) ** +INF is +INF
110  * 6. +-(|x| > 1) ** -INF is +0
111  * 7. +-(|x| < 1) ** +INF is +0
112  * 8. +-(|x| < 1) ** -INF is +INF
113  * 9. +-1 ** +-INF is NAN
114  * 10. +0 ** (+anything except 0, NAN) is +0
115  * 11. -0 ** (+anything except 0, NAN, odd integer) is +0
116  * 12. +0 ** (-anything except 0, NAN) is +INF
117  * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF
118  * 14. -0 ** (odd integer) = -( +0 ** (odd integer) )
119  * 15. +INF ** (+anything except 0,NAN) is +INF
120  * 16. +INF ** (-anything except 0,NAN) is +0
121  * 17. -INF ** (anything) = -0 ** (-anything)
122  * 18. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer)
123  * 19. (-anything except 0 and inf) ** (non-integer) is NAN
124  *
125  * Accuracy:
126  * pow(x,y) returns x**y nearly rounded. In particular
127  * pow(integer,integer)
128  * always returns the correct integer provided it is
129  * representable.
130  *
131  * Constants :
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 pow(double x, double y)
139 {
140  double z, ax, z_h, z_l, p_h, p_l;
141  double y1, t1, t2, r, s, t, u, v, w;
142  int32_t i, j, k, yisint, n;
143  int32_t hx, hy, ix, iy;
144  uint32_t lx, ly;
145 
146  EXTRACT_WORDS(hx, lx, x);
147  EXTRACT_WORDS(hy, ly, y);
148  ix = hx & 0x7fffffff;
149  iy = hy & 0x7fffffff;
150 
151  /* y==zero: x**0 = 1 */
152  if ((iy | ly) == 0)
153  return one;
154 
155  /* +-NaN return x+y */
156  if (ix > 0x7ff00000 || ((ix == 0x7ff00000) && (lx != 0)) ||
157  iy > 0x7ff00000 || ((iy == 0x7ff00000) && (ly != 0)))
158  return x + y;
159 
160  /* determine if y is an odd int when x < 0
161  * yisint = 0 ... y is not an integer
162  * yisint = 1 ... y is an odd int
163  * yisint = 2 ... y is an even int
164  */
165  yisint = 0;
166  if (hx < 0)
167  {
168  if (iy >= 0x43400000)
169  yisint = 2; /* even integer y */
170  else if (iy >= 0x3ff00000)
171  {
172  k = (iy >> 20) - 0x3ff; /* exponent */
173  if (k > 20)
174  {
175  j = ly >> (52 - k);
176  if ((uint32_t)(j << (52 - k)) == ly)
177  yisint = 2 - (j & 1);
178  }
179  else if (ly == 0)
180  {
181  j = iy >> (20 - k);
182  if ((j << (20 - k)) == iy)
183  yisint = 2 - (j & 1);
184  }
185  }
186  }
187 
188  /* special value of y */
189  if (ly == 0)
190  {
191  if (iy == 0x7ff00000)
192  { /* y is +-inf */
193  if (((ix - 0x3ff00000) | lx) == 0)
194  return y - y; /* inf**+-1 is NaN */
195  else if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */
196  return (hy >= 0) ? y : zero;
197  else /* (|x|<1)**-,+inf = inf,0 */
198  return (hy < 0) ? -y : zero;
199  }
200  if (iy == 0x3ff00000)
201  { /* y is +-1 */
202  if (hy < 0)
203  return one / x;
204  else
205  return x;
206  }
207  if (hy == 0x40000000)
208  return x * x; /* y is 2 */
209  if (hy == 0x3fe00000)
210  { /* y is 0.5 */
211  if (hx >= 0) /* x >= +0 */
212  return sqrt(x);
213  }
214  }
215 
216  ax = fabs(x);
217  /* special value of x */
218  if (lx == 0)
219  {
220  if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000)
221  {
222  z = ax; /*x is +-0,+-inf,+-1*/
223  if (hy < 0)
224  z = one / z; /* z = (1/|x|) */
225  if (hx < 0)
226  {
227  if (((ix - 0x3ff00000) | yisint) == 0)
228  {
229  z = (z - z) / (z - z); /* (-1)**non-int is NaN */
230  }
231  else if (yisint == 1)
232  z = -z; /* (x<0)**odd = -(|x|**odd) */
233  }
234  return z;
235  }
236  }
237 
238  n = (hx >> 31) + 1;
239 
240  /* (x<0)**(non-int) is NaN */
241  if ((n | yisint) == 0)
242  return (x - x) / (x - x);
243 
244  s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
245  if ((n | (yisint - 1)) == 0)
246  s = -one; /* (-ve)**(odd int) */
247 
248  /* |y| is huge */
249  if (iy > 0x41e00000)
250  { /* if |y| > 2**31 */
251  if (iy > 0x43f00000)
252  { /* if |y| > 2**64, must o/uflow */
253  if (ix <= 0x3fefffff)
254  return (hy < 0) ? huge * huge : tiny * tiny;
255  if (ix >= 0x3ff00000)
256  return (hy > 0) ? huge * huge : tiny * tiny;
257  }
258  /* over/underflow if x is not close to one */
259  if (ix < 0x3fefffff)
260  return (hy < 0) ? s * huge * huge : s * tiny * tiny;
261  if (ix > 0x3ff00000)
262  return (hy > 0) ? s * huge * huge : s * tiny * tiny;
263  /* now |1-x| is tiny <= 2**-20, suffice to compute
264  log(x) by x-x^2/2+x^3/3-x^4/4 */
265  t = ax - one; /* t has 20 trailing zeros */
266  w = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25));
267  u = ivln2_h * t; /* ivln2_h has 21 sig. bits */
268  v = t * ivln2_l - w * ivln2;
269  t1 = u + v;
270  SET_LOW_WORD(t1, 0);
271  t2 = v - (t1 - u);
272  }
273  else
274  {
275  double ss, s2, s_h, s_l, t_h, t_l;
276  n = 0;
277  /* take care subnormal number */
278  if (ix < 0x00100000)
279  {
280  ax *= two53;
281  n -= 53;
282  GET_HIGH_WORD(ix, ax);
283  }
284  n += ((ix) >> 20) - 0x3ff;
285  j = ix & 0x000fffff;
286  /* determine interval */
287  ix = j | 0x3ff00000; /* normalize ix */
288  if (j <= 0x3988E)
289  k = 0; /* |x|<sqrt(3/2) */
290  else if (j < 0xBB67A)
291  k = 1; /* |x|<sqrt(3) */
292  else
293  {
294  k = 0;
295  n += 1;
296  ix -= 0x00100000;
297  }
298  SET_HIGH_WORD(ax, ix);
299 
300  /* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
301  u = ax - bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
302  v = one / (ax + bp[k]);
303  ss = u * v;
304  s_h = ss;
305  SET_LOW_WORD(s_h, 0);
306  /* t_h=ax+bp[k] High */
307  t_h = zero;
308  SET_HIGH_WORD(t_h, ((ix >> 1) | 0x20000000) + 0x00080000 + (k << 18));
309  t_l = ax - (t_h - bp[k]);
310  s_l = v * ((u - s_h * t_h) - s_h * t_l);
311  /* compute log(ax) */
312  s2 = ss * ss;
313  r = s2 * s2 * (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6)))));
314  r += s_l * (s_h + ss);
315  s2 = s_h * s_h;
316  t_h = 3.0 + s2 + r;
317  SET_LOW_WORD(t_h, 0);
318  t_l = r - ((t_h - 3.0) - s2);
319  /* u+v = ss*(1+...) */
320  u = s_h * t_h;
321  v = s_l * t_h + t_l * ss;
322  /* 2/(3log2)*(ss+...) */
323  p_h = u + v;
324  SET_LOW_WORD(p_h, 0);
325  p_l = v - (p_h - u);
326  z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */
327  z_l = cp_l * p_h + p_l * cp + dp_l[k];
328  /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */
329  t = (double)n;
330  t1 = (((z_h + z_l) + dp_h[k]) + t);
331  SET_LOW_WORD(t1, 0);
332  t2 = z_l - (((t1 - t) - dp_h[k]) - z_h);
333  }
334 
335  /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
336  y1 = y;
337  SET_LOW_WORD(y1, 0);
338  p_l = (y - y1) * t1 + y * t2;
339  p_h = y1 * t1;
340  z = p_l + p_h;
341  EXTRACT_WORDS(j, i, z);
342  if (j >= 0x40900000)
343  { /* z >= 1024 */
344  if (((j - 0x40900000) | i) != 0) /* if z > 1024 */
345  return s * huge * huge; /* overflow */
346  else
347  {
348  if (p_l + ovt > z - p_h)
349  return s * huge * huge; /* overflow */
350  }
351  }
352  else if ((j & 0x7fffffff) >= 0x4090cc00)
353  { /* z <= -1075 */
354  if (((j - 0xc090cc00) | i) != 0) /* z < -1075 */
355  return s * tiny * tiny; /* underflow */
356  else
357  {
358  if (p_l <= z - p_h)
359  return s * tiny * tiny; /* underflow */
360  }
361  }
362  /*
363  * compute 2**(p_h+p_l)
364  */
365  i = j & 0x7fffffff;
366  k = (i >> 20) - 0x3ff;
367  n = 0;
368  if (i > 0x3fe00000)
369  { /* if |z| > 0.5, set n = [z+0.5] */
370  n = j + (0x00100000 >> (k + 1));
371  k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */
372  t = zero;
373  SET_HIGH_WORD(t, (n & ~(0x000fffff >> k)));
374  n = ((n & 0x000fffff) | 0x00100000) >> (20 - k);
375  if (j < 0)
376  n = -n;
377  p_h -= t;
378  }
379  t = p_l + p_h;
380  SET_LOW_WORD(t, 0);
381  u = t * lg2_h;
382  v = (p_l - (t - p_h)) * lg2 + t * lg2_l;
383  z = u + v;
384  w = v - (z - u);
385  t = z * z;
386  t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5))));
387  r = (z * t1) / (t1 - two) - (w + z * w);
388  z = one - (r - z);
389  GET_HIGH_WORD(j, z);
390  j += (n << 20);
391  if ((j >> 20) <= 0)
392  z = scalbn(z, n); /* subnormal output */
393  else
394  {
395  uint32_t hz;
396  GET_HIGH_WORD(hz, z);
397  SET_HIGH_WORD(z, hz + (n << 20));
398  }
399  return s * z;
400 }
double sqrt(double x)
Square root function.
Definition: sqrt.c:119
static const double cp_l
Definition: pow.c:87
static const double L6
Definition: pow.c:75
#define GET_HIGH_WORD(i, d)
Get the more significant 32 bit int from a double.
Definition: prim.h:167
double scalbn(double x, int32_t n)
Definition: scalbn.c:56
double pow(double x, double y)
Expontation function.
Definition: pow.c:138
static const double lg2_h
Definition: pow.c:82
static const double dp_h[]
Definition: pow.c:60
static const double ivln2_h
Definition: pow.c:89
static const double two53
Definition: pow.c:67
static const double P2
Definition: pow.c:77
static const double P1
Definition: pow.c:76
static const double huge
Definition: pow.c:68
static const double one
Definition: pow.c:67
#define EXTRACT_WORDS(ix0, ix1, d)
Get two 32 bit ints from a double.
Definition: prim.h:156
static const double ivln2_l
Definition: pow.c:90
static const double P3
Definition: pow.c:78
static const double ivln2
Definition: pow.c:88
static const double lg2
Definition: pow.c:81
static const double L3
Definition: pow.c:72
static const double zero
Definition: pow.c:66
static const double ovt
Definition: pow.c:84
static const double dp_l[]
Definition: pow.c:63
double fabs(double x)
Returns the absolute value of x.
Definition: fabs.c:51
static const double P4
Definition: pow.c:79
static const double L1
Definition: pow.c:70
static const double L5
Definition: pow.c:74
static const double cp_h
Definition: pow.c:86
static const double lg2_l
Definition: pow.c:83
static const double tiny
Definition: pow.c:68
static const double two
Definition: pow.c:67
#define SET_LOW_WORD(d, v)
Set the less significant 32 bits of a double from an int.
Definition: prim.h:209
static const double L4
Definition: pow.c:73
static const double L2
Definition: pow.c:71
static const double cp
Definition: pow.c:85
#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 bp[]
Definition: pow.c:57
static const double P5
Definition: pow.c:80