2 * IBM Accurate Mathematical Library
3 * written by International Business Machines Corp.
4 * Copyright (C) 2001-2016 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:uexp.c */
25 /* FILES NEEDED:dla.h endian.h mpa.h mydefs.h uexp.h */
26 /* mpa.c mpexp.x slowexp.c */
28 /* An ultimate exp routine. Given an IEEE double machine number x */
29 /* it computes the correctly rounded (to nearest) value of e^x */
30 /* Assumption: Machine arithmetic operations are performed in */
31 /* round to nearest mode of IEEE 754 standard. */
33 /***************************************************************************/
41 #include <math_private.h>
49 double __slowexp (double);
51 /* An ultimate exp routine. Given an IEEE double machine number x it computes
52 the correctly rounded (to nearest) value of e^x. */
55 __ieee754_exp (double x
)
57 double bexp
, t
, eps
, del
, base
, y
, al
, bet
, res
, rem
, cor
;
58 mynumber junk1
, junk2
, binexp
= {{0, 0}};
63 SET_RESTORE_ROUND (FE_TONEAREST
);
66 m
= junk1
.i
[HIGH_HALF
];
69 if (n
> smallint
&& n
< bigint
)
71 y
= x
* log2e
.x
+ three51
.x
;
72 bexp
= y
- three51
.x
; /* multiply the result by 2**bexp */
76 eps
= bexp
* ln_two2
.x
; /* x = bexp*ln(2) + t - eps */
77 t
= x
- bexp
* ln_two1
.x
;
80 base
= y
- three33
.x
; /* t rounded to a multiple of 2**-18 */
82 del
= (t
- base
) - eps
; /* x = bexp*ln(2) + base + del */
83 eps
= del
+ del
* del
* (p3
.x
* del
+ p2
.x
);
85 binexp
.i
[HIGH_HALF
] = (junk1
.i
[LOW_HALF
] + 1023) << 20;
87 i
= ((junk2
.i
[LOW_HALF
] >> 8) & 0xfffffffe) + 356;
88 j
= (junk2
.i
[LOW_HALF
] & 511) << 1;
90 al
= coar
.x
[i
] * fine
.x
[j
];
91 bet
= ((coar
.x
[i
] * fine
.x
[j
+ 1] + coar
.x
[i
+ 1] * fine
.x
[j
])
92 + coar
.x
[i
+ 1] * fine
.x
[j
+ 1]);
94 rem
= (bet
+ bet
* eps
) + al
* eps
;
96 cor
= (al
- res
) + rem
;
97 if (res
== (res
+ cor
* err_0
))
99 retval
= res
* binexp
.x
;
104 retval
= __slowexp (x
);
106 } /*if error is over bound */
129 /* x is finite, cause either overflow or underflow */
130 if (junk1
.i
[LOW_HALF
] != 0)
135 retval
= (x
> 0) ? inf
.x
: zero
; /* |x| = inf; return either inf or 0 */
139 y
= x
* log2e
.x
+ three51
.x
;
140 bexp
= y
- three51
.x
;
142 eps
= bexp
* ln_two2
.x
;
143 t
= x
- bexp
* ln_two1
.x
;
145 base
= y
- three33
.x
;
147 del
= (t
- base
) - eps
;
148 eps
= del
+ del
* del
* (p3
.x
* del
+ p2
.x
);
149 i
= ((junk2
.i
[LOW_HALF
] >> 8) & 0xfffffffe) + 356;
150 j
= (junk2
.i
[LOW_HALF
] & 511) << 1;
151 al
= coar
.x
[i
] * fine
.x
[j
];
152 bet
= ((coar
.x
[i
] * fine
.x
[j
+ 1] + coar
.x
[i
+ 1] * fine
.x
[j
])
153 + coar
.x
[i
+ 1] * fine
.x
[j
+ 1]);
154 rem
= (bet
+ bet
* eps
) + al
* eps
;
156 cor
= (al
- res
) + rem
;
159 ex
= junk1
.i
[LOW_HALF
];
168 binexp
.i
[HIGH_HALF
] = (1023 + ex
) << 20;
169 if (res
== (res
+ cor
* err_0
))
171 retval
= res
* binexp
.x
;
176 retval
= __slowexp (x
);
177 goto check_uflow_ret
;
178 } /*if error is over bound */
181 binexp
.i
[HIGH_HALF
] = (1023 - ex
) << 20;
184 eps
= 1.0000000001 + err_0
* binexp
.x
;
186 y
= ((1.0 - t
) + res
) + cor
;
189 if (res
== (res
+ eps
* cor
))
191 binexp
.i
[HIGH_HALF
] = 0x00100000;
192 retval
= (res
- 1.0) * binexp
.x
;
193 goto check_uflow_ret
;
197 retval
= __slowexp (x
);
198 goto check_uflow_ret
;
199 } /* if error is over bound */
201 if (retval
< DBL_MIN
)
203 double force_underflow
= tiny
* tiny
;
204 math_force_eval (force_underflow
);
212 binexp
.i
[HIGH_HALF
] = (junk1
.i
[LOW_HALF
] + 767) << 20;
213 if (res
== (res
+ cor
* err_0
))
214 retval
= res
* binexp
.x
* t256
.x
;
216 retval
= __slowexp (x
);
227 return hhuge
* hhuge
;
232 #ifndef __ieee754_exp
233 strong_alias (__ieee754_exp
, __exp_finite
)
236 /* Compute e^(x+xx). The routine also receives bound of error of previous
237 calculation. If after computing exp the error exceeds the allowed bounds,
238 the routine returns a non-positive number. Otherwise it returns the
239 computed result, which is always positive. */
242 __exp1 (double x
, double xx
, double error
)
244 double bexp
, t
, eps
, del
, base
, y
, al
, bet
, res
, rem
, cor
;
245 mynumber junk1
, junk2
, binexp
= {{0, 0}};
249 m
= junk1
.i
[HIGH_HALF
];
250 n
= m
& hugeint
; /* no sign */
252 if (n
> smallint
&& n
< bigint
)
254 y
= x
* log2e
.x
+ three51
.x
;
255 bexp
= y
- three51
.x
; /* multiply the result by 2**bexp */
259 eps
= bexp
* ln_two2
.x
; /* x = bexp*ln(2) + t - eps */
260 t
= x
- bexp
* ln_two1
.x
;
263 base
= y
- three33
.x
; /* t rounded to a multiple of 2**-18 */
265 del
= (t
- base
) + (xx
- eps
); /* x = bexp*ln(2) + base + del */
266 eps
= del
+ del
* del
* (p3
.x
* del
+ p2
.x
);
268 binexp
.i
[HIGH_HALF
] = (junk1
.i
[LOW_HALF
] + 1023) << 20;
270 i
= ((junk2
.i
[LOW_HALF
] >> 8) & 0xfffffffe) + 356;
271 j
= (junk2
.i
[LOW_HALF
] & 511) << 1;
273 al
= coar
.x
[i
] * fine
.x
[j
];
274 bet
= ((coar
.x
[i
] * fine
.x
[j
+ 1] + coar
.x
[i
+ 1] * fine
.x
[j
])
275 + coar
.x
[i
+ 1] * fine
.x
[j
+ 1]);
277 rem
= (bet
+ bet
* eps
) + al
* eps
;
279 cor
= (al
- res
) + rem
;
280 if (res
== (res
+ cor
* (1.0 + error
+ err_1
)))
281 return res
* binexp
.x
;
287 return 1.0; /* if x->0 e^x=1 */
292 return (zero
/ zero
); /* x is NaN, return invalid */
294 return ((x
> 0) ? (hhuge
* hhuge
) : (tiny
* tiny
));
295 /* x is finite, cause either overflow or underflow */
296 if (junk1
.i
[LOW_HALF
] != 0)
297 return (zero
/ zero
); /* x is NaN */
298 return ((x
> 0) ? inf
.x
: zero
); /* |x| = inf; return either inf or 0 */
301 y
= x
* log2e
.x
+ three51
.x
;
302 bexp
= y
- three51
.x
;
304 eps
= bexp
* ln_two2
.x
;
305 t
= x
- bexp
* ln_two1
.x
;
307 base
= y
- three33
.x
;
309 del
= (t
- base
) + (xx
- eps
);
310 eps
= del
+ del
* del
* (p3
.x
* del
+ p2
.x
);
311 i
= ((junk2
.i
[LOW_HALF
] >> 8) & 0xfffffffe) + 356;
312 j
= (junk2
.i
[LOW_HALF
] & 511) << 1;
313 al
= coar
.x
[i
] * fine
.x
[j
];
314 bet
= ((coar
.x
[i
] * fine
.x
[j
+ 1] + coar
.x
[i
+ 1] * fine
.x
[j
])
315 + coar
.x
[i
+ 1] * fine
.x
[j
+ 1]);
316 rem
= (bet
+ bet
* eps
) + al
* eps
;
318 cor
= (al
- res
) + rem
;
321 ex
= junk1
.i
[LOW_HALF
];
330 binexp
.i
[HIGH_HALF
] = (1023 + ex
) << 20;
331 if (res
== (res
+ cor
* (1.0 + error
+ err_1
)))
332 return res
* binexp
.x
;
337 binexp
.i
[HIGH_HALF
] = (1023 - ex
) << 20;
340 eps
= 1.00000000001 + (error
+ err_1
) * binexp
.x
;
342 y
= ((1.0 - t
) + res
) + cor
;
345 if (res
== (res
+ eps
* cor
))
347 binexp
.i
[HIGH_HALF
] = 0x00100000;
348 return (res
- 1.0) * binexp
.x
;
355 binexp
.i
[HIGH_HALF
] = (junk1
.i
[LOW_HALF
] + 767) << 20;
356 if (res
== (res
+ cor
* (1.0 + error
+ err_1
)))
357 return res
* binexp
.x
* t256
.x
;