2 * IBM Accurate Mathematical Library
3 * written by International Business Machines Corp.
4 * Copyright (C) 2001-2013 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 /***************************************************************************/
40 #include <math_private.h>
47 double __slowexp(double);
49 /***************************************************************************/
50 /* An ultimate exp routine. Given an IEEE double machine number x */
51 /* it computes the correctly rounded (to nearest) value of e^x */
52 /***************************************************************************/
55 __ieee754_exp(double x
) {
56 double bexp
, t
, eps
, del
, base
, y
, al
, bet
, res
, rem
, cor
;
57 mynumber junk1
, junk2
, binexp
= {{0,0}};
64 SET_RESTORE_ROUND (FE_TONEAREST
);
67 m
= junk1
.i
[HIGH_HALF
];
70 if (n
> smallint
&& n
< bigint
) {
72 y
= x
*log2e
.x
+ three51
.x
;
73 bexp
= y
- three51
.x
; /* multiply the result by 2**bexp */
77 eps
= bexp
*ln_two2
.x
; /* x = bexp*ln(2) + t - eps */
78 t
= x
- bexp
*ln_two1
.x
;
81 base
= y
- three33
.x
; /* t rounded to a multiple of 2**-18 */
83 del
= (t
- base
) - eps
; /* x = bexp*ln(2) + base + del */
84 eps
= del
+ del
*del
*(p3
.x
*del
+ p2
.x
);
86 binexp
.i
[HIGH_HALF
] =(junk1
.i
[LOW_HALF
]+1023)<<20;
88 i
= ((junk2
.i
[LOW_HALF
]>>8)&0xfffffffe)+356;
89 j
= (junk2
.i
[LOW_HALF
]&511)<<1;
91 al
= coar
.x
[i
]*fine
.x
[j
];
92 bet
=(coar
.x
[i
]*fine
.x
[j
+1] + coar
.x
[i
+1]*fine
.x
[j
]) + 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
)) { retval
= res
*binexp
.x
; goto ret
; }
98 else { retval
= __slowexp(x
); goto ret
; } /*if error is over bound */
101 if (n
<= smallint
) { retval
= 1.0; goto ret
; }
104 if (n
> infint
) { retval
= x
+x
; goto ret
; } /* x is NaN */
105 if (n
< infint
) { retval
= (x
>0) ? (hhuge
*hhuge
) : (tiny
*tiny
); goto ret
; }
106 /* x is finite, cause either overflow or underflow */
107 if (junk1
.i
[LOW_HALF
] != 0) { retval
= x
+x
; goto ret
; } /* x is NaN */
108 retval
= (x
>0)?inf
.x
:zero
; /* |x| = inf; return either inf or 0 */
112 y
= x
*log2e
.x
+ three51
.x
;
113 bexp
= y
- three51
.x
;
115 eps
= bexp
*ln_two2
.x
;
116 t
= x
- bexp
*ln_two1
.x
;
118 base
= y
- three33
.x
;
120 del
= (t
- base
) - eps
;
121 eps
= del
+ del
*del
*(p3
.x
*del
+ p2
.x
);
122 i
= ((junk2
.i
[LOW_HALF
]>>8)&0xfffffffe)+356;
123 j
= (junk2
.i
[LOW_HALF
]&511)<<1;
124 al
= coar
.x
[i
]*fine
.x
[j
];
125 bet
=(coar
.x
[i
]*fine
.x
[j
+1] + coar
.x
[i
+1]*fine
.x
[j
]) + coar
.x
[i
+1]*fine
.x
[j
+1];
126 rem
=(bet
+ bet
*eps
)+al
*eps
;
128 cor
= (al
- res
) + rem
;
130 ex
=junk1
.i
[LOW_HALF
];
131 if (res
< 1.0) {res
+=res
; cor
+=cor
; ex
-=1;}
133 binexp
.i
[HIGH_HALF
] = (1023+ex
)<<20;
134 if (res
== (res
+cor
*err_0
)) { retval
= res
*binexp
.x
; goto ret
; }
135 else { retval
= __slowexp(x
); goto ret
; } /*if error is over bound */
138 binexp
.i
[HIGH_HALF
] = (1023-ex
)<<20;
141 eps
=1.0000000001+err_0
*binexp
.x
;
143 y
= ((1.0-t
)+res
)+cor
;
146 if (res
== (res
+ eps
*cor
))
147 { binexp
.i
[HIGH_HALF
] = 0x00100000;
148 retval
= (res
-1.0)*binexp
.x
;
151 else { retval
= __slowexp(x
); goto ret
; } /* if error is over bound */
154 binexp
.i
[HIGH_HALF
] =(junk1
.i
[LOW_HALF
]+767)<<20;
155 if (res
== (res
+cor
*err_0
)) { retval
= res
*binexp
.x
*t256
.x
; goto ret
; }
156 else { retval
= __slowexp(x
); goto ret
; }
161 #ifndef __ieee754_exp
162 strong_alias (__ieee754_exp
, __exp_finite
)
165 /************************************************************************/
166 /* Compute e^(x+xx)(Double-Length number) .The routine also receive */
167 /* bound of error of previous calculation .If after computing exp */
168 /* error bigger than allows routine return non positive number */
169 /*else return e^(x + xx) (always positive ) */
170 /************************************************************************/
174 __exp1(double x
, double xx
, double error
) {
175 double bexp
, t
, eps
, del
, base
, y
, al
, bet
, res
, rem
, cor
;
176 mynumber junk1
, junk2
, binexp
= {{0,0}};
183 m
= junk1
.i
[HIGH_HALF
];
184 n
= m
&hugeint
; /* no sign */
186 if (n
> smallint
&& n
< bigint
) {
187 y
= x
*log2e
.x
+ three51
.x
;
188 bexp
= y
- three51
.x
; /* multiply the result by 2**bexp */
192 eps
= bexp
*ln_two2
.x
; /* x = bexp*ln(2) + t - eps */
193 t
= x
- bexp
*ln_two1
.x
;
196 base
= y
- three33
.x
; /* t rounded to a multiple of 2**-18 */
198 del
= (t
- base
) + (xx
-eps
); /* x = bexp*ln(2) + base + del */
199 eps
= del
+ del
*del
*(p3
.x
*del
+ p2
.x
);
201 binexp
.i
[HIGH_HALF
] =(junk1
.i
[LOW_HALF
]+1023)<<20;
203 i
= ((junk2
.i
[LOW_HALF
]>>8)&0xfffffffe)+356;
204 j
= (junk2
.i
[LOW_HALF
]&511)<<1;
206 al
= coar
.x
[i
]*fine
.x
[j
];
207 bet
=(coar
.x
[i
]*fine
.x
[j
+1] + coar
.x
[i
+1]*fine
.x
[j
]) + coar
.x
[i
+1]*fine
.x
[j
+1];
209 rem
=(bet
+ bet
*eps
)+al
*eps
;
211 cor
= (al
- res
) + rem
;
212 if (res
== (res
+cor
*(1.0+error
+err_1
))) return res
*binexp
.x
;
216 if (n
<= smallint
) return 1.0; /* if x->0 e^x=1 */
219 if (n
> infint
) return(zero
/zero
); /* x is NaN, return invalid */
220 if (n
< infint
) return ( (x
>0) ? (hhuge
*hhuge
) : (tiny
*tiny
) );
221 /* x is finite, cause either overflow or underflow */
222 if (junk1
.i
[LOW_HALF
] != 0) return (zero
/zero
); /* x is NaN */
223 return ((x
>0)?inf
.x
:zero
); /* |x| = inf; return either inf or 0 */
226 y
= x
*log2e
.x
+ three51
.x
;
227 bexp
= y
- three51
.x
;
229 eps
= bexp
*ln_two2
.x
;
230 t
= x
- bexp
*ln_two1
.x
;
232 base
= y
- three33
.x
;
234 del
= (t
- base
) + (xx
-eps
);
235 eps
= del
+ del
*del
*(p3
.x
*del
+ p2
.x
);
236 i
= ((junk2
.i
[LOW_HALF
]>>8)&0xfffffffe)+356;
237 j
= (junk2
.i
[LOW_HALF
]&511)<<1;
238 al
= coar
.x
[i
]*fine
.x
[j
];
239 bet
=(coar
.x
[i
]*fine
.x
[j
+1] + coar
.x
[i
+1]*fine
.x
[j
]) + coar
.x
[i
+1]*fine
.x
[j
+1];
240 rem
=(bet
+ bet
*eps
)+al
*eps
;
242 cor
= (al
- res
) + rem
;
244 ex
=junk1
.i
[LOW_HALF
];
245 if (res
< 1.0) {res
+=res
; cor
+=cor
; ex
-=1;}
247 binexp
.i
[HIGH_HALF
] = (1023+ex
)<<20;
248 if (res
== (res
+cor
*(1.0+error
+err_1
))) return res
*binexp
.x
;
252 binexp
.i
[HIGH_HALF
] = (1023-ex
)<<20;
255 eps
=1.00000000001+(error
+err_1
)*binexp
.x
;
257 y
= ((1.0-t
)+res
)+cor
;
260 if (res
== (res
+ eps
*cor
))
261 {binexp
.i
[HIGH_HALF
] = 0x00100000; return (res
-1.0)*binexp
.x
;}
265 binexp
.i
[HIGH_HALF
] =(junk1
.i
[LOW_HALF
]+767)<<20;
266 if (res
== (res
+cor
*(1.0+error
+err_1
)))
267 return res
*binexp
.x
*t256
.x
;