2 * IBM Accurate Mathematical Library
3 * Copyright (c) International Business Machines Corp., 2001
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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"
42 double __slowexp(double);
44 /***************************************************************************/
45 /* An ultimate exp routine. Given an IEEE double machine number x */
46 /* it computes the correctly rounded (to nearest) value of e^x */
47 /***************************************************************************/
48 double __ieee754_exp(double x) {
49 double bexp, t, eps, del, base, y, al, bet, res, rem, cor;
50 mynumber junk1, junk2, binexp = {{0,0}};
57 m = junk1.i[HIGH_HALF];
60 if (n > smallint && n < bigint) {
62 y = x*log2e.x + three51.x;
63 bexp = y - three51.x; /* multiply the result by 2**bexp */
67 eps = bexp*ln_two2.x; /* x = bexp*ln(2) + t - eps */
68 t = x - bexp*ln_two1.x;
71 base = y - three33.x; /* t rounded to a multiple of 2**-18 */
73 del = (t - base) - eps; /* x = bexp*ln(2) + base + del */
74 eps = del + del*del*(p3.x*del + p2.x);
76 binexp.i[HIGH_HALF] =(junk1.i[LOW_HALF]+1023)<<20;
78 i = ((junk2.i[LOW_HALF]>>8)&0xfffffffe)+356;
79 j = (junk2.i[LOW_HALF]&511)<<1;
81 al = coar.x[i]*fine.x[j];
82 bet =(coar.x[i]*fine.x[j+1] + coar.x[i+1]*fine.x[j]) + coar.x[i+1]*fine.x[j+1];
84 rem=(bet + bet*eps)+al*eps;
86 cor = (al - res) + rem;
87 if (res == (res+cor*err_0)) return res*binexp.x;
88 else return __slowexp(x); /*if error is over bound */
91 if (n <= smallint) return 1.0;
94 if (n > infint) return(zero/zero); /* x is NaN, return invalid */
95 if (n < infint) return ( (x>0) ? (hhuge*hhuge) : (tiny*tiny) );
96 /* x is finite, cause either overflow or underflow */
97 if (junk1.i[LOW_HALF] != 0) return (zero/zero); /* x is NaN */
98 return ((x>0)?inf.x:zero ); /* |x| = inf; return either inf or 0 */
101 y = x*log2e.x + three51.x;
102 bexp = y - three51.x;
104 eps = bexp*ln_two2.x;
105 t = x - bexp*ln_two1.x;
107 base = y - three33.x;
109 del = (t - base) - eps;
110 eps = del + del*del*(p3.x*del + p2.x);
111 i = ((junk2.i[LOW_HALF]>>8)&0xfffffffe)+356;
112 j = (junk2.i[LOW_HALF]&511)<<1;
113 al = coar.x[i]*fine.x[j];
114 bet =(coar.x[i]*fine.x[j+1] + coar.x[i+1]*fine.x[j]) + coar.x[i+1]*fine.x[j+1];
115 rem=(bet + bet*eps)+al*eps;
117 cor = (al - res) + rem;
119 ex=junk1.i[LOW_HALF];
120 if (res < 1.0) {res+=res; cor+=cor; ex-=1;}
122 binexp.i[HIGH_HALF] = (1023+ex)<<20;
123 if (res == (res+cor*err_0)) return res*binexp.x;
124 else return __slowexp(x); /*if error is over bound */
127 binexp.i[HIGH_HALF] = (1023-ex)<<20;
130 eps=1.0000000001+err_0*binexp.x;
132 y = ((1.0-t)+res)+cor;
135 if (res == (res + eps*cor))
136 { binexp.i[HIGH_HALF] = 0x00100000;
137 return (res-1.0)*binexp.x;
139 else return __slowexp(x); /* if error is over bound */
142 binexp.i[HIGH_HALF] =(junk1.i[LOW_HALF]+767)<<20;
143 if (res == (res+cor*err_0)) return res*binexp.x*t256.x;
144 else return __slowexp(x);
148 /************************************************************************/
149 /* Compute e^(x+xx)(Double-Length number) .The routine also receive */
150 /* bound of error of previous calculation .If after computing exp */
151 /* error bigger than allows routine return non positive number */
152 /*else return e^(x + xx) (always positive ) */
153 /************************************************************************/
155 double __exp1(double x, double xx, double error) {
156 double bexp, t, eps, del, base, y, al, bet, res, rem, cor;
157 mynumber junk1, junk2, binexp = {{0,0}};
164 m = junk1.i[HIGH_HALF];
165 n = m&hugeint; /* no sign */
167 if (n > smallint && n < bigint) {
168 y = x*log2e.x + three51.x;
169 bexp = y - three51.x; /* multiply the result by 2**bexp */
173 eps = bexp*ln_two2.x; /* x = bexp*ln(2) + t - eps */
174 t = x - bexp*ln_two1.x;
177 base = y - three33.x; /* t rounded to a multiple of 2**-18 */
179 del = (t - base) + (xx-eps); /* x = bexp*ln(2) + base + del */
180 eps = del + del*del*(p3.x*del + p2.x);
182 binexp.i[HIGH_HALF] =(junk1.i[LOW_HALF]+1023)<<20;
184 i = ((junk2.i[LOW_HALF]>>8)&0xfffffffe)+356;
185 j = (junk2.i[LOW_HALF]&511)<<1;
187 al = coar.x[i]*fine.x[j];
188 bet =(coar.x[i]*fine.x[j+1] + coar.x[i+1]*fine.x[j]) + coar.x[i+1]*fine.x[j+1];
190 rem=(bet + bet*eps)+al*eps;
192 cor = (al - res) + rem;
193 if (res == (res+cor*(1.0+error+err_1))) return res*binexp.x;
197 if (n <= smallint) return 1.0; /* if x->0 e^x=1 */
200 if (n > infint) return(zero/zero); /* x is NaN, return invalid */
201 if (n < infint) return ( (x>0) ? (hhuge*hhuge) : (tiny*tiny) );
202 /* x is finite, cause either overflow or underflow */
203 if (junk1.i[LOW_HALF] != 0) return (zero/zero); /* x is NaN */
204 return ((x>0)?inf.x:zero ); /* |x| = inf; return either inf or 0 */
207 y = x*log2e.x + three51.x;
208 bexp = y - three51.x;
210 eps = bexp*ln_two2.x;
211 t = x - bexp*ln_two1.x;
213 base = y - three33.x;
215 del = (t - base) + (xx-eps);
216 eps = del + del*del*(p3.x*del + p2.x);
217 i = ((junk2.i[LOW_HALF]>>8)&0xfffffffe)+356;
218 j = (junk2.i[LOW_HALF]&511)<<1;
219 al = coar.x[i]*fine.x[j];
220 bet =(coar.x[i]*fine.x[j+1] + coar.x[i+1]*fine.x[j]) + coar.x[i+1]*fine.x[j+1];
221 rem=(bet + bet*eps)+al*eps;
223 cor = (al - res) + rem;
225 ex=junk1.i[LOW_HALF];
226 if (res < 1.0) {res+=res; cor+=cor; ex-=1;}
228 binexp.i[HIGH_HALF] = (1023+ex)<<20;
229 if (res == (res+cor*(1.0+error+err_1))) return res*binexp.x;
233 binexp.i[HIGH_HALF] = (1023-ex)<<20;
236 eps=1.00000000001+(error+err_1)*binexp.x;
238 y = ((1.0-t)+res)+cor;
241 if (res == (res + eps*cor))
242 {binexp.i[HIGH_HALF] = 0x00100000; return (res-1.0)*binexp.x;}
246 binexp.i[HIGH_HALF] =(junk1.i[LOW_HALF]+767)<<20;
247 if (res == (res+cor*(1.0+error+err_1)))
248 return res*binexp.x*t256.x;