2 * IBM Accurate Mathematical Library
3 * written by International Business Machines Corp.
4 * Copyright (C) 2001-2014 Free Software Foundation, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 /***************************************************************************/
20 /* MODULE_NAME: upow.c */
27 /* FILES NEEDED: dla.h endian.h mpa.h mydefs.h */
28 /* halfulp.c mpexp.c mplog.c slowexp.c slowpow.c mpa.c */
30 /* root.tbl uexp.tbl upow.tbl */
31 /* An ultimate power routine. Given two IEEE double machine numbers y,x */
32 /* it computes the correctly rounded (to nearest) value of x^y. */
33 /* Assumption: Machine arithmetic operations are performed in */
34 /* round to nearest mode of IEEE 754 standard. */
36 /***************************************************************************/
44 #include <math_private.h>
51 static const double huge
= 1.0e300
, tiny
= 1.0e-300;
53 double __exp1 (double x
, double xx
, double error
);
54 static double log1 (double x
, double *delta
, double *error
);
55 static double my_log2 (double x
, double *delta
, double *error
);
56 double __slowpow (double x
, double y
, double z
);
57 static double power1 (double x
, double y
);
58 static int checkint (double x
);
60 /* An ultimate power routine. Given two IEEE double machine numbers y, x it
61 computes the correctly rounded (to nearest) value of X^y. */
64 __ieee754_pow (double x
, double y
)
66 double z
, a
, aa
, error
, t
, a1
, a2
, y1
, y2
;
72 if (v
.i
[LOW_HALF
] == 0)
74 qx
= u
.i
[HIGH_HALF
] & 0x7fffffff;
76 if (((qx
== 0x7ff00000) && (u
.i
[LOW_HALF
] != 0)) || (qx
> 0x7ff00000))
88 if (((u
.i
[HIGH_HALF
] > 0 && u
.i
[HIGH_HALF
] < 0x7ff00000) || /* x>0 and not x->0 */
89 (u
.i
[HIGH_HALF
] == 0 && u
.i
[LOW_HALF
] != 0)) &&
90 /* 2^-1023< x<= 2^-1023 * 0x1.0000ffffffff */
91 (v
.i
[HIGH_HALF
] & 0x7fffffff) < 0x4ff00000)
92 { /* if y<-1 or y>1 */
96 SET_RESTORE_ROUND (FE_TONEAREST
);
98 /* Avoid internal underflow for tiny y. The exact value of y does
99 not matter if |y| <= 2**-64. */
100 if (ABS (y
) < 0x1p
-64)
101 y
= y
< 0 ? -0x1p
-64 : 0x1p
-64;
102 z
= log1 (x
, &aa
, &error
); /* x^y =e^(y log (X)) */
110 aa
= y2
* a1
+ y
* a2
;
113 error
= error
* ABS (y
);
114 t
= __exp1 (a1
, a2
, 1.9e16
* error
); /* return -10 or 0 if wasn't computed exactly */
115 retval
= (t
> 0) ? t
: power1 (x
, y
);
118 if (__isinf (retval
))
119 retval
= huge
* huge
;
120 else if (retval
== 0)
121 retval
= tiny
* tiny
;
127 if (((v
.i
[HIGH_HALF
] & 0x7fffffff) == 0x7ff00000 && v
.i
[LOW_HALF
] != 0)
128 || (v
.i
[HIGH_HALF
] & 0x7fffffff) > 0x7ff00000) /* NaN */
130 if (ABS (y
) > 1.0e20
)
131 return (y
> 0) ? 0 : 1.0 / 0.0;
134 return y
< 0 ? 1.0 / x
: x
;
136 return y
< 0 ? 1.0 / 0.0 : 0.0; /* return 0 */
139 qx
= u
.i
[HIGH_HALF
] & 0x7fffffff; /* no sign */
140 qy
= v
.i
[HIGH_HALF
] & 0x7fffffff; /* no sign */
142 if (qx
>= 0x7ff00000 && (qx
> 0x7ff00000 || u
.i
[LOW_HALF
] != 0)) /* NaN */
144 if (qy
>= 0x7ff00000 && (qy
> 0x7ff00000 || v
.i
[LOW_HALF
] != 0)) /* NaN */
145 return x
== 1.0 ? 1.0 : y
;
148 if (u
.i
[HIGH_HALF
] < 0)
153 if (qy
== 0x7ff00000)
158 return v
.i
[HIGH_HALF
] < 0 ? INF
.x
: 0.0;
160 return v
.i
[HIGH_HALF
] < 0 ? 0.0 : INF
.x
;
162 else if (qx
== 0x7ff00000)
163 return y
< 0 ? 0.0 : INF
.x
;
164 return (x
- x
) / (x
- x
); /* y not integer and x<0 */
166 else if (qx
== 0x7ff00000)
169 return y
< 0 ? nZERO
.x
: nINF
.x
;
171 return y
< 0 ? 0.0 : INF
.x
;
173 /* if y even or odd */
175 return __ieee754_pow (-x
, y
);
180 SET_RESTORE_ROUND (FE_TONEAREST
);
181 retval
= -__ieee754_pow (-x
, y
);
183 if (__isinf (retval
))
184 retval
= -huge
* huge
;
185 else if (retval
== 0)
186 retval
= -tiny
* tiny
;
192 if (qx
== 0x7ff00000) /* x= 2^-0x3ff */
193 return y
> 0 ? x
: 0;
195 if (qy
> 0x45f00000 && qy
< 0x7ff00000)
200 return (x
> 1.0) ? huge
* huge
: tiny
* tiny
;
202 return (x
< 1.0) ? huge
* huge
: tiny
* tiny
;
208 return (x
> 1.0) ? INF
.x
: 0;
210 return (x
< 1.0) ? INF
.x
: 0;
211 return 0; /* unreachable, to make the compiler happy */
214 #ifndef __ieee754_pow
215 strong_alias (__ieee754_pow
, __pow_finite
)
218 /* Compute x^y using more accurate but more slow log routine. */
221 power1 (double x
, double y
)
223 double z
, a
, aa
, error
, t
, a1
, a2
, y1
, y2
;
224 z
= my_log2 (x
, &aa
, &error
);
232 aa
= ((y1
* a1
- a
) + y1
* a2
+ y2
* a1
) + y2
* a2
+ aa
* y
;
235 error
= error
* ABS (y
);
236 t
= __exp1 (a1
, a2
, 1.9e16
* error
);
237 return (t
>= 0) ? t
: __slowpow (x
, y
, z
);
240 /* Compute log(x) (x is left argument). The result is the returned double + the
241 parameter DELTA. The result is bounded by ERROR. */
244 log1 (double x
, double *delta
, double *error
)
247 double uu
, vv
, eps
, nx
, e
, e1
, e2
, t
, t1
, t2
, res
, add
= 0;
250 mynumber
/**/ two52
= {{0x43300000, 0x00000000}}; /* 2**52 */
253 mynumber
/**/ two52
= {{0x00000000, 0x43300000}}; /* 2**52 */
261 if (m
< 0x00100000) /* 1<x<2^-1007 */
269 if ((m
& 0x000fffff) < 0x0006a09e)
271 u
.i
[HIGH_HALF
] = (m
& 0x000fffff) | 0x3ff00000;
272 two52
.i
[LOW_HALF
] = (m
>> 20);
276 u
.i
[HIGH_HALF
] = (m
& 0x000fffff) | 0x3fe00000;
277 two52
.i
[LOW_HALF
] = (m
>> 20) + 1;
282 i
= (v
.i
[LOW_HALF
] & 0x000003ff) << 2;
283 if (two52
.i
[LOW_HALF
] == 1023) /* nx = 0 */
285 if (i
> 1192 && i
< 1208) /* |x-1| < 1.5*2**-10 */
288 t1
= (t
+ 5.0e6
) - 5.0e6
;
290 e1
= t
- 0.5 * t1
* t1
;
291 e2
= (t
* t
* t
* (r3
+ t
* (r4
+ t
* (r5
+ t
* (r6
+ t
293 - 0.5 * t2
* (t
+ t1
));
295 *error
= 1.0e-21 * ABS (t
);
296 *delta
= (e1
- res
) + e2
;
298 } /* |x-1| < 1.5*2**-10 */
301 v
.x
= u
.x
* (ui
.x
[i
] + ui
.x
[i
+ 1]) + bigv
.x
;
303 j
= v
.i
[LOW_HALF
] & 0x0007ffff;
307 e2
= eps
* (ui
.x
[i
+ 1] + vj
.x
[j
] * (ui
.x
[i
] + ui
.x
[i
+ 1]));
309 e2
= ((e1
- e
) + e2
);
310 t
= ui
.x
[i
+ 2] + vj
.x
[j
+ 1];
312 t2
= ((((t
- t1
) + e
) + (ui
.x
[i
+ 3] + vj
.x
[j
+ 2])) + e2
+ e
* e
313 * (p2
+ e
* (p3
+ e
* p4
)));
316 *delta
= (t1
- res
) + t2
;
323 nx
= (two52
.x
- two52e
.x
) + add
;
325 e2
= eps
* ui
.x
[i
+ 1];
328 t
= nx
* ln2a
.x
+ ui
.x
[i
+ 2];
330 t2
= ((((t
- t1
) + e
) + nx
* ln2b
.x
+ ui
.x
[i
+ 3] + e2
) + e
* e
331 * (q2
+ e
* (q3
+ e
* (q4
+ e
* (q5
+ e
* q6
)))));
334 *delta
= (t1
- res
) + t2
;
339 /* Slower but more accurate routine of log. The returned result is double +
340 DELTA. The result is bounded by ERROR. */
343 my_log2 (double x
, double *delta
, double *error
)
346 double uu
, vv
, eps
, nx
, e
, e1
, e2
, t
, t1
, t2
, res
, add
= 0;
347 double ou1
, ou2
, lu1
, lu2
, ov
, lv1
, lv2
, a
, a1
, a2
;
348 double y
, yy
, z
, zz
, j1
, j2
, j7
, j8
;
350 double j3
, j4
, j5
, j6
;
354 mynumber
/**/ two52
= {{0x43300000, 0x00000000}}; /* 2**52 */
357 mynumber
/**/ two52
= {{0x00000000, 0x43300000}}; /* 2**52 */
374 if ((m
& 0x000fffff) < 0x0006a09e)
376 u
.i
[HIGH_HALF
] = (m
& 0x000fffff) | 0x3ff00000;
377 two52
.i
[LOW_HALF
] = (m
>> 20);
381 u
.i
[HIGH_HALF
] = (m
& 0x000fffff) | 0x3fe00000;
382 two52
.i
[LOW_HALF
] = (m
>> 20) + 1;
387 i
= (v
.i
[LOW_HALF
] & 0x000003ff) << 2;
388 /*------------------------------------- |x-1| < 2**-11------------------------------- */
389 if ((two52
.i
[LOW_HALF
] == 1023) && (i
== 1200))
392 EMULV (t
, s3
, y
, yy
, j1
, j2
, j3
, j4
, j5
);
393 ADD2 (-0.5, 0, y
, yy
, z
, zz
, j1
, j2
);
394 MUL2 (t
, 0, z
, zz
, y
, yy
, j1
, j2
, j3
, j4
, j5
, j6
, j7
, j8
);
395 MUL2 (t
, 0, y
, yy
, z
, zz
, j1
, j2
, j3
, j4
, j5
, j6
, j7
, j8
);
398 e2
= ((((t
- e1
) + z
) + zz
) + t
* t
* t
399 * (ss3
+ t
* (s4
+ t
* (s5
+ t
* (s6
+ t
* (s7
+ t
* s8
))))));
401 *error
= 1.0e-25 * ABS (t
);
402 *delta
= (e1
- res
) + e2
;
405 /*----------------------------- |x-1| > 2**-11 -------------------------- */
407 { /*Computing log(x) according to log table */
408 nx
= (two52
.x
- two52e
.x
) + add
;
413 v
.x
= u
.x
* (ou1
+ ou2
) + bigv
.x
;
415 j
= v
.i
[LOW_HALF
] & 0x0007ffff;
421 a
= (ou1
+ ou2
) * (1.0 + ov
);
422 a1
= (a
+ 1.0e10
) - 1.0e10
;
423 a2
= a
* (1.0 - a1
* uu
* vv
);
428 t
= nx
* ln2a
.x
+ lu1
+ lv1
;
430 t2
= ((((t
- t1
) + e
) + (lu2
+ lv2
+ nx
* ln2b
.x
+ e2
)) + e
* e
431 * (p2
+ e
* (p3
+ e
* p4
)));
434 *delta
= (t1
- res
) + t2
;
439 /* This function receives a double x and checks if it is an integer. If not,
440 it returns 0, else it returns 1 if even or -1 if odd. */
452 m
= u
.i
[HIGH_HALF
] & 0x7fffffff; /* no sign */
454 return 0; /* x is +/-inf or NaN */
456 return 1; /* |x| >= 2**53 */
458 return 0; /* |x| < 2, can not be 0 or 1 */
460 k
= (m
>> 20) - 1023; /* 1 <= k <= 52 */
462 return (n
& 1) ? -1 : 1; /* odd or even */
466 return 0; /* if not integer */
467 return (n
<< (k
- 21)) ? -1 : 1;
470 return 0; /*if not integer */
472 return (m
& 1) ? -1 : 1;
475 return (m
<< (k
+ 11)) ? -1 : 1;