OLD | NEW |
1 /* origin: FreeBSD /usr/src/lib/msun/src/e_pow.c */ | 1 /* origin: FreeBSD /usr/src/lib/msun/src/e_pow.c */ |
2 /* | 2 /* |
3 * ==================================================== | 3 * ==================================================== |
4 * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. | 4 * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. |
5 * | 5 * |
6 * Permission to use, copy, modify, and distribute this | 6 * Permission to use, copy, modify, and distribute this |
7 * software is freely granted, provided that this notice | 7 * software is freely granted, provided that this notice |
8 * is preserved. | 8 * is preserved. |
9 * ==================================================== | 9 * ==================================================== |
10 */ | 10 */ |
(...skipping 13 matching lines...) Expand all Loading... |
24 * 2. 1 ** (anything) is 1 | 24 * 2. 1 ** (anything) is 1 |
25 * 3. (anything except 1) ** NAN is NAN | 25 * 3. (anything except 1) ** NAN is NAN |
26 * 4. NAN ** (anything except 0) is NAN | 26 * 4. NAN ** (anything except 0) is NAN |
27 * 5. +-(|x| > 1) ** +INF is +INF | 27 * 5. +-(|x| > 1) ** +INF is +INF |
28 * 6. +-(|x| > 1) ** -INF is +0 | 28 * 6. +-(|x| > 1) ** -INF is +0 |
29 * 7. +-(|x| < 1) ** +INF is +0 | 29 * 7. +-(|x| < 1) ** +INF is +0 |
30 * 8. +-(|x| < 1) ** -INF is +INF | 30 * 8. +-(|x| < 1) ** -INF is +INF |
31 * 9. -1 ** +-INF is 1 | 31 * 9. -1 ** +-INF is 1 |
32 * 10. +0 ** (+anything except 0, NAN) is +0 | 32 * 10. +0 ** (+anything except 0, NAN) is +0 |
33 * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 | 33 * 11. -0 ** (+anything except 0, NAN, odd integer) is +0 |
34 * 12. +0 ** (-anything except 0, NAN) is +INF, raise divbyze
ro | 34 * 12. +0 ** (-anything except 0, NAN) is +INF, raise |
35 * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF, raise divbyze
ro | 35 * divbyzero |
| 36 * 13. -0 ** (-anything except 0, NAN, odd integer) is +INF, raise |
| 37 * divbyzero |
36 * 14. -0 ** (+odd integer) is -0 | 38 * 14. -0 ** (+odd integer) is -0 |
37 * 15. -0 ** (-odd integer) is -INF, raise divbyzero | 39 * 15. -0 ** (-odd integer) is -INF, raise divbyzero |
38 * 16. +INF ** (+anything except 0,NAN) is +INF | 40 * 16. +INF ** (+anything except 0,NAN) is +INF |
39 * 17. +INF ** (-anything except 0,NAN) is +0 | 41 * 17. +INF ** (-anything except 0,NAN) is +0 |
40 * 18. -INF ** (+odd integer) is -INF | 42 * 18. -INF ** (+odd integer) is -INF |
41 * 19. -INF ** (anything) = -0 ** (-anything), (anything except odd integer
) | 43 * 19. -INF ** (anything) = -0 ** (-anything), (anything except odd |
| 44 * integer) |
42 * 20. (anything) ** 1 is (anything) | 45 * 20. (anything) ** 1 is (anything) |
43 * 21. (anything) ** -1 is 1/(anything) | 46 * 21. (anything) ** -1 is 1/(anything) |
44 * 22. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) | 47 * 22. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) |
45 * 23. (-anything except 0 and inf) ** (non-integer) is NAN | 48 * 23. (-anything except 0 and inf) ** (non-integer) is NAN |
46 * | 49 * |
47 * Accuracy: | 50 * Accuracy: |
48 * pow(x,y) returns x**y nearly rounded. In particular | 51 * pow(x,y) returns x**y nearly rounded. In particular |
49 * pow(integer,integer) | 52 * pow(integer,integer) |
50 * always returns the correct integer provided it is | 53 * always returns the correct integer provided it is |
51 * representable. | 54 * representable. |
52 * | 55 * |
53 * Constants : | 56 * Constants : |
54 * The hexadecimal values are the intended ones for the following | 57 * The hexadecimal values are the intended ones for the following |
55 * constants. The decimal values may be used, provided that the | 58 * constants. The decimal values may be used, provided that the |
56 * compiler will convert from decimal to binary accurately enough | 59 * compiler will convert from decimal to binary accurately enough |
57 * to produce the hexadecimal values shown. | 60 * to produce the hexadecimal values shown. |
58 */ | 61 */ |
59 | 62 |
60 #include "libm.h" | 63 #include "libm.h" |
61 | 64 |
62 static const double | 65 static const double bp[] = |
63 bp[] = {1.0, 1.5,}, | 66 { |
64 dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ | 67 1.0, 1.5, |
65 dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ | 68 }, |
66 two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ | 69 dp_h[] = |
67 huge = 1.0e300, | 70 { |
68 tiny = 1.0e-300, | 71 0.0, 5.84962487220764160156e-01, |
69 /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ | 72 }, /* 0x3FE2B803, 0x40000000 */ |
70 L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ | 73 dp_l[] = |
71 L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ | 74 { |
72 L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ | 75 0.0, 1.35003920212974897128e-08, |
73 L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ | 76 }, /* 0x3E4CFDEB, 0x43CFD006 */ |
74 L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ | 77 two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ |
75 L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ | 78 huge = 1.0e300, |
76 P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ | 79 tiny = 1.0e-300, |
77 P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ | 80 /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ |
78 P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ | 81 L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ |
79 P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ | 82 L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ |
80 P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ | 83 L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ |
81 lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ | 84 L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ |
82 lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ | 85 L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ |
83 lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ | 86 L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ |
84 ovt = 8.0085662595372944372e-017, /* -(1024-log2(ovfl+.5ulp)) */ | 87 P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ |
85 cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ | 88 P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ |
86 cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ | 89 P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ |
87 cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ | 90 P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ |
88 ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ | 91 P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ |
89 ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ | 92 lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ |
90 ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ | 93 lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ |
91 | 94 lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ |
92 double pow(double x, double y) | 95 ovt = 8.0085662595372944372e-017, /* -(1024-log2(ovfl+.5ulp)) */ |
93 { | 96 cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ |
94 » double z,ax,z_h,z_l,p_h,p_l; | 97 cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ |
95 » double y1,t1,t2,r,s,t,u,v,w; | 98 cp_l = |
96 » int32_t i,j,k,yisint,n; | 99 -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ |
97 » int32_t hx,hy,ix,iy; | 100 ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ |
98 » uint32_t lx,ly; | 101 ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ |
99 | 102 ivln2_l = |
100 » EXTRACT_WORDS(hx, lx, x); | 103 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ |
101 » EXTRACT_WORDS(hy, ly, y); | 104 |
102 » ix = hx & 0x7fffffff; | 105 double pow(double x, double y) { |
103 » iy = hy & 0x7fffffff; | 106 double z, ax, z_h, z_l, p_h, p_l; |
104 | 107 double y1, t1, t2, r, s, t, u, v, w; |
105 » /* x**0 = 1, even if x is NaN */ | 108 int32_t i, j, k, yisint, n; |
106 » if ((iy|ly) == 0) | 109 int32_t hx, hy, ix, iy; |
107 » » return 1.0; | 110 uint32_t lx, ly; |
108 » /* 1**y = 1, even if y is NaN */ | 111 |
109 » if (hx == 0x3ff00000 && lx == 0) | 112 EXTRACT_WORDS(hx, lx, x); |
110 » » return 1.0; | 113 EXTRACT_WORDS(hy, ly, y); |
111 » /* NaN if either arg is NaN */ | 114 ix = hx & 0x7fffffff; |
112 » if (ix > 0x7ff00000 || (ix == 0x7ff00000 && lx != 0) || | 115 iy = hy & 0x7fffffff; |
113 » iy > 0x7ff00000 || (iy == 0x7ff00000 && ly != 0)) | 116 |
114 » » return x + y; | 117 /* x**0 = 1, even if x is NaN */ |
115 | 118 if ((iy | ly) == 0) |
116 » /* determine if y is an odd int when x < 0 | 119 return 1.0; |
117 » * yisint = 0 ... y is not an integer | 120 /* 1**y = 1, even if y is NaN */ |
118 » * yisint = 1 ... y is an odd int | 121 if (hx == 0x3ff00000 && lx == 0) |
119 » * yisint = 2 ... y is an even int | 122 return 1.0; |
120 » */ | 123 /* NaN if either arg is NaN */ |
121 » yisint = 0; | 124 if (ix > 0x7ff00000 || (ix == 0x7ff00000 && lx != 0) || iy > 0x7ff00000 || |
122 » if (hx < 0) { | 125 (iy == 0x7ff00000 && ly != 0)) |
123 » » if (iy >= 0x43400000) | 126 return x + y; |
124 » » » yisint = 2; /* even integer y */ | 127 |
125 » » else if (iy >= 0x3ff00000) { | 128 /* determine if y is an odd int when x < 0 |
126 » » » k = (iy>>20) - 0x3ff; /* exponent */ | 129 * yisint = 0 ... y is not an integer |
127 » » » if (k > 20) { | 130 * yisint = 1 ... y is an odd int |
128 » » » » j = ly>>(52-k); | 131 * yisint = 2 ... y is an even int |
129 » » » » if ((j<<(52-k)) == ly) | 132 */ |
130 » » » » » yisint = 2 - (j&1); | 133 yisint = 0; |
131 » » » } else if (ly == 0) { | 134 if (hx < 0) { |
132 » » » » j = iy>>(20-k); | 135 if (iy >= 0x43400000) |
133 » » » » if ((j<<(20-k)) == iy) | 136 yisint = 2; /* even integer y */ |
134 » » » » » yisint = 2 - (j&1); | 137 else if (iy >= 0x3ff00000) { |
135 » » » } | 138 k = (iy >> 20) - 0x3ff; /* exponent */ |
136 » » } | 139 if (k > 20) { |
137 » } | 140 j = ly >> (52 - k); |
138 | 141 if ((j << (52 - k)) == ly) |
139 » /* special value of y */ | 142 yisint = 2 - (j & 1); |
140 » if (ly == 0) { | 143 } else if (ly == 0) { |
141 » » if (iy == 0x7ff00000) { /* y is +-inf */ | 144 j = iy >> (20 - k); |
142 » » » if (((ix-0x3ff00000)|lx) == 0) /* (-1)**+-inf is 1 */ | 145 if ((j << (20 - k)) == iy) |
143 » » » » return 1.0; | 146 yisint = 2 - (j & 1); |
144 » » » else if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */ | 147 } |
145 » » » » return hy >= 0 ? y : 0.0; | 148 } |
146 » » » else /* (|x|<1)**+-inf = 0,inf */ | 149 } |
147 » » » » return hy >= 0 ? 0.0 : -y; | 150 |
148 » » } | 151 /* special value of y */ |
149 » » if (iy == 0x3ff00000) { /* y is +-1 */ | 152 if (ly == 0) { |
150 » » » if (hy >= 0) | 153 if (iy == 0x7ff00000) { /* y is +-inf */ |
151 » » » » return x; | 154 if (((ix - 0x3ff00000) | lx) == 0) /* (-1)**+-inf is 1 */ |
152 » » » y = 1/x; | 155 return 1.0; |
153 #if FLT_EVAL_METHOD!=0 | 156 else if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */ |
154 » » » { | 157 return hy >= 0 ? y : 0.0; |
155 » » » » union {double f; uint64_t i;} u = {y}; | 158 else /* (|x|<1)**+-inf = 0,inf */ |
156 » » » » uint64_t i = u.i & -1ULL/2; | 159 return hy >= 0 ? 0.0 : -y; |
157 » » » » if (i>>52 == 0 && (i&(i-1))) | 160 } |
158 » » » » » FORCE_EVAL((float)y); | 161 if (iy == 0x3ff00000) { /* y is +-1 */ |
159 » » » } | 162 if (hy >= 0) |
| 163 return x; |
| 164 y = 1 / x; |
| 165 #if FLT_EVAL_METHOD != 0 |
| 166 { |
| 167 union { |
| 168 double f; |
| 169 uint64_t i; |
| 170 } u = {y}; |
| 171 uint64_t i = u.i & -1ULL / 2; |
| 172 if (i >> 52 == 0 && (i & (i - 1))) |
| 173 FORCE_EVAL((float)y); |
| 174 } |
160 #endif | 175 #endif |
161 » » » return y; | 176 return y; |
162 » » } | 177 } |
163 » » if (hy == 0x40000000) /* y is 2 */ | 178 if (hy == 0x40000000) /* y is 2 */ |
164 » » » return x*x; | 179 return x * x; |
165 » » if (hy == 0x3fe00000) { /* y is 0.5 */ | 180 if (hy == 0x3fe00000) { /* y is 0.5 */ |
166 » » » if (hx >= 0) /* x >= +0 */ | 181 if (hx >= 0) /* x >= +0 */ |
167 » » » » return sqrt(x); | 182 return sqrt(x); |
168 » » } | 183 } |
169 » } | 184 } |
170 | 185 |
171 » ax = fabs(x); | 186 ax = fabs(x); |
172 » /* special value of x */ | 187 /* special value of x */ |
173 » if (lx == 0) { | 188 if (lx == 0) { |
174 » » if (ix == 0x7ff00000 || ix == 0 || ix == 0x3ff00000) { /* x is +
-0,+-inf,+-1 */ | 189 if (ix == 0x7ff00000 || ix == 0 || |
175 » » » z = ax; | 190 ix == 0x3ff00000) { /* x is +-0,+-inf,+-1 */ |
176 » » » if (hy < 0) /* z = (1/|x|) */ | 191 z = ax; |
177 » » » » z = 1.0/z; | 192 if (hy < 0) /* z = (1/|x|) */ |
178 » » » if (hx < 0) { | 193 z = 1.0 / z; |
179 » » » » if (((ix-0x3ff00000)|yisint) == 0) { | 194 if (hx < 0) { |
180 » » » » » z = (z-z)/(z-z); /* (-1)**non-int is NaN
*/ | 195 if (((ix - 0x3ff00000) | yisint) == 0) { |
181 » » » » } else if (yisint == 1) | 196 z = (z - z) / (z - z); /* (-1)**non-int is NaN */ |
182 » » » » » z = -z; /* (x<0)**odd = -(|x|**
odd) */ | 197 } else if (yisint == 1) |
183 » » » } | 198 z = -z; /* (x<0)**odd = -(|x|**odd) */ |
184 » » » return z; | 199 } |
185 » » } | 200 return z; |
186 » } | 201 } |
187 | 202 } |
188 » s = 1.0; /* sign of result */ | 203 |
189 » if (hx < 0) { | 204 s = 1.0; /* sign of result */ |
190 » » if (yisint == 0) /* (x<0)**(non-int) is NaN */ | 205 if (hx < 0) { |
191 » » » return (x-x)/(x-x); | 206 if (yisint == 0) /* (x<0)**(non-int) is NaN */ |
192 » » if (yisint == 1) /* (x<0)**(odd int) */ | 207 return (x - x) / (x - x); |
193 » » » s = -1.0; | 208 if (yisint == 1) /* (x<0)**(odd int) */ |
194 » } | 209 s = -1.0; |
195 | 210 } |
196 » /* |y| is huge */ | 211 |
197 » if (iy > 0x41e00000) { /* if |y| > 2**31 */ | 212 /* |y| is huge */ |
198 » » if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */ | 213 if (iy > 0x41e00000) { /* if |y| > 2**31 */ |
199 » » » if (ix <= 0x3fefffff) | 214 if (iy > 0x43f00000) { /* if |y| > 2**64, must o/uflow */ |
200 » » » » return hy < 0 ? huge*huge : tiny*tiny; | 215 if (ix <= 0x3fefffff) |
201 » » » if (ix >= 0x3ff00000) | 216 return hy < 0 ? huge * huge : tiny * tiny; |
202 » » » » return hy > 0 ? huge*huge : tiny*tiny; | 217 if (ix >= 0x3ff00000) |
203 » » } | 218 return hy > 0 ? huge * huge : tiny * tiny; |
204 » » /* over/underflow if x is not close to one */ | 219 } |
205 » » if (ix < 0x3fefffff) | 220 /* over/underflow if x is not close to one */ |
206 » » » return hy < 0 ? s*huge*huge : s*tiny*tiny; | 221 if (ix < 0x3fefffff) |
207 » » if (ix > 0x3ff00000) | 222 return hy < 0 ? s * huge * huge : s * tiny * tiny; |
208 » » » return hy > 0 ? s*huge*huge : s*tiny*tiny; | 223 if (ix > 0x3ff00000) |
209 » » /* now |1-x| is tiny <= 2**-20, suffice to compute | 224 return hy > 0 ? s * huge * huge : s * tiny * tiny; |
210 » » log(x) by x-x^2/2+x^3/3-x^4/4 */ | 225 /* now |1-x| is tiny <= 2**-20, suffice to compute |
211 » » t = ax - 1.0; /* t has 20 trailing zeros */ | 226 log(x) by x-x^2/2+x^3/3-x^4/4 */ |
212 » » w = (t*t)*(0.5 - t*(0.3333333333333333333333-t*0.25)); | 227 t = ax - 1.0; /* t has 20 trailing zeros */ |
213 » » u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ | 228 w = (t * t) * (0.5 - t * (0.3333333333333333333333 - t * 0.25)); |
214 » » v = t*ivln2_l - w*ivln2; | 229 u = ivln2_h * t; /* ivln2_h has 21 sig. bits */ |
215 » » t1 = u + v; | 230 v = t * ivln2_l - w * ivln2; |
216 » » SET_LOW_WORD(t1, 0); | 231 t1 = u + v; |
217 » » t2 = v - (t1-u); | 232 SET_LOW_WORD(t1, 0); |
218 » } else { | 233 t2 = v - (t1 - u); |
219 » » double ss,s2,s_h,s_l,t_h,t_l; | 234 } else { |
220 » » n = 0; | 235 double ss, s2, s_h, s_l, t_h, t_l; |
221 » » /* take care subnormal number */ | 236 n = 0; |
222 » » if (ix < 0x00100000) { | 237 /* take care subnormal number */ |
223 » » » ax *= two53; | 238 if (ix < 0x00100000) { |
224 » » » n -= 53; | 239 ax *= two53; |
225 » » » GET_HIGH_WORD(ix,ax); | 240 n -= 53; |
226 » » } | 241 GET_HIGH_WORD(ix, ax); |
227 » » n += ((ix)>>20) - 0x3ff; | 242 } |
228 » » j = ix & 0x000fffff; | 243 n += ((ix) >> 20) - 0x3ff; |
229 » » /* determine interval */ | 244 j = ix & 0x000fffff; |
230 » » ix = j | 0x3ff00000; /* normalize ix */ | 245 /* determine interval */ |
231 » » if (j <= 0x3988E) /* |x|<sqrt(3/2) */ | 246 ix = j | 0x3ff00000; /* normalize ix */ |
232 » » » k = 0; | 247 if (j <= 0x3988E) /* |x|<sqrt(3/2) */ |
233 » » else if (j < 0xBB67A) /* |x|<sqrt(3) */ | 248 k = 0; |
234 » » » k = 1; | 249 else if (j < 0xBB67A) /* |x|<sqrt(3) */ |
235 » » else { | 250 k = 1; |
236 » » » k = 0; | 251 else { |
237 » » » n += 1; | 252 k = 0; |
238 » » » ix -= 0x00100000; | 253 n += 1; |
239 » » } | 254 ix -= 0x00100000; |
240 » » SET_HIGH_WORD(ax, ix); | 255 } |
241 | 256 SET_HIGH_WORD(ax, ix); |
242 » » /* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */ | 257 |
243 » » u = ax - bp[k]; /* bp[0]=1.0, bp[1]=1.5 */ | 258 /* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */ |
244 » » v = 1.0/(ax+bp[k]); | 259 u = ax - bp[k]; /* bp[0]=1.0, bp[1]=1.5 */ |
245 » » ss = u*v; | 260 v = 1.0 / (ax + bp[k]); |
246 » » s_h = ss; | 261 ss = u * v; |
247 » » SET_LOW_WORD(s_h, 0); | 262 s_h = ss; |
248 » » /* t_h=ax+bp[k] High */ | 263 SET_LOW_WORD(s_h, 0); |
249 » » t_h = 0.0; | 264 /* t_h=ax+bp[k] High */ |
250 » » SET_HIGH_WORD(t_h, ((ix>>1)|0x20000000) + 0x00080000 + (k<<18)); | 265 t_h = 0.0; |
251 » » t_l = ax - (t_h-bp[k]); | 266 SET_HIGH_WORD(t_h, ((ix >> 1) | 0x20000000) + 0x00080000 + (k << 18)); |
252 » » s_l = v*((u-s_h*t_h)-s_h*t_l); | 267 t_l = ax - (t_h - bp[k]); |
253 » » /* compute log(ax) */ | 268 s_l = v * ((u - s_h * t_h) - s_h * t_l); |
254 » » s2 = ss*ss; | 269 /* compute log(ax) */ |
255 » » r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); | 270 s2 = ss * ss; |
256 » » r += s_l*(s_h+ss); | 271 r = s2 * s2 * |
257 » » s2 = s_h*s_h; | 272 (L1 + s2 * (L2 + s2 * (L3 + s2 * (L4 + s2 * (L5 + s2 * L6))))); |
258 » » t_h = 3.0 + s2 + r; | 273 r += s_l * (s_h + ss); |
259 » » SET_LOW_WORD(t_h, 0); | 274 s2 = s_h * s_h; |
260 » » t_l = r - ((t_h-3.0)-s2); | 275 t_h = 3.0 + s2 + r; |
261 » » /* u+v = ss*(1+...) */ | 276 SET_LOW_WORD(t_h, 0); |
262 » » u = s_h*t_h; | 277 t_l = r - ((t_h - 3.0) - s2); |
263 » » v = s_l*t_h + t_l*ss; | 278 /* u+v = ss*(1+...) */ |
264 » » /* 2/(3log2)*(ss+...) */ | 279 u = s_h * t_h; |
265 » » p_h = u + v; | 280 v = s_l * t_h + t_l * ss; |
266 » » SET_LOW_WORD(p_h, 0); | 281 /* 2/(3log2)*(ss+...) */ |
267 » » p_l = v - (p_h-u); | 282 p_h = u + v; |
268 » » z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ | 283 SET_LOW_WORD(p_h, 0); |
269 » » z_l = cp_l*p_h+p_l*cp + dp_l[k]; | 284 p_l = v - (p_h - u); |
270 » » /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ | 285 z_h = cp_h * p_h; /* cp_h+cp_l = 2/(3*log2) */ |
271 » » t = (double)n; | 286 z_l = cp_l * p_h + p_l * cp + dp_l[k]; |
272 » » t1 = ((z_h + z_l) + dp_h[k]) + t; | 287 /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */ |
273 » » SET_LOW_WORD(t1, 0); | 288 t = (double)n; |
274 » » t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); | 289 t1 = ((z_h + z_l) + dp_h[k]) + t; |
275 » } | 290 SET_LOW_WORD(t1, 0); |
276 | 291 t2 = z_l - (((t1 - t) - dp_h[k]) - z_h); |
277 » /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ | 292 } |
278 » y1 = y; | 293 |
279 » SET_LOW_WORD(y1, 0); | 294 /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ |
280 » p_l = (y-y1)*t1 + y*t2; | 295 y1 = y; |
281 » p_h = y1*t1; | 296 SET_LOW_WORD(y1, 0); |
282 » z = p_l + p_h; | 297 p_l = (y - y1) * t1 + y * t2; |
283 » EXTRACT_WORDS(j, i, z); | 298 p_h = y1 * t1; |
284 » if (j >= 0x40900000) { /* z >= 1024 */ | 299 z = p_l + p_h; |
285 » » if (((j-0x40900000)|i) != 0) /* if z > 1024 */ | 300 EXTRACT_WORDS(j, i, z); |
286 » » » return s*huge*huge; /* overflow */ | 301 if (j >= 0x40900000) { /* z >= 1024 */ |
287 » » if (p_l + ovt > z - p_h) | 302 if (((j - 0x40900000) | i) != 0) /* if z > 1024 */ |
288 » » » return s*huge*huge; /* overflow */ | 303 return s * huge * huge; /* overflow */ |
289 » } else if ((j&0x7fffffff) >= 0x4090cc00) { /* z <= -1075 */ // FIXME:
instead of abs(j) use unsigned j | 304 if (p_l + ovt > z - p_h) |
290 » » if (((j-0xc090cc00)|i) != 0) /* z < -1075 */ | 305 return s * huge * huge; /* overflow */ |
291 » » » return s*tiny*tiny; /* underflow */ | 306 } else if ((j & 0x7fffffff) >= 0x4090cc00) { |
292 » » if (p_l <= z - p_h) | 307 /* z <= -1075 */ // FIXME: instead of abs(j) use unsigned j |
293 » » » return s*tiny*tiny; /* underflow */ | 308 if (((j - 0xc090cc00) | i) != 0) /* z < -1075 */ |
294 » } | 309 return s * tiny * tiny; /* underflow */ |
295 » /* | 310 if (p_l <= z - p_h) |
296 » * compute 2**(p_h+p_l) | 311 return s * tiny * tiny; /* underflow */ |
297 » */ | 312 } |
298 » i = j & 0x7fffffff; | 313 /* |
299 » k = (i>>20) - 0x3ff; | 314 * compute 2**(p_h+p_l) |
300 » n = 0; | 315 */ |
301 » if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ | 316 i = j & 0x7fffffff; |
302 » » n = j + (0x00100000>>(k+1)); | 317 k = (i >> 20) - 0x3ff; |
303 » » k = ((n&0x7fffffff)>>20) - 0x3ff; /* new k for n */ | 318 n = 0; |
304 » » t = 0.0; | 319 if (i > 0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ |
305 » » SET_HIGH_WORD(t, n & ~(0x000fffff>>k)); | 320 n = j + (0x00100000 >> (k + 1)); |
306 » » n = ((n&0x000fffff)|0x00100000)>>(20-k); | 321 k = ((n & 0x7fffffff) >> 20) - 0x3ff; /* new k for n */ |
307 » » if (j < 0) | 322 t = 0.0; |
308 » » » n = -n; | 323 SET_HIGH_WORD(t, n & ~(0x000fffff >> k)); |
309 » » p_h -= t; | 324 n = ((n & 0x000fffff) | 0x00100000) >> (20 - k); |
310 » } | 325 if (j < 0) |
311 » t = p_l + p_h; | 326 n = -n; |
312 » SET_LOW_WORD(t, 0); | 327 p_h -= t; |
313 » u = t*lg2_h; | 328 } |
314 » v = (p_l-(t-p_h))*lg2 + t*lg2_l; | 329 t = p_l + p_h; |
315 » z = u + v; | 330 SET_LOW_WORD(t, 0); |
316 » w = v - (z-u); | 331 u = t * lg2_h; |
317 » t = z*z; | 332 v = (p_l - (t - p_h)) * lg2 + t * lg2_l; |
318 » t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); | 333 z = u + v; |
319 » r = (z*t1)/(t1-2.0) - (w + z*w); | 334 w = v - (z - u); |
320 » z = 1.0 - (r-z); | 335 t = z * z; |
321 » GET_HIGH_WORD(j, z); | 336 t1 = z - t * (P1 + t * (P2 + t * (P3 + t * (P4 + t * P5)))); |
322 » j += n<<20; | 337 r = (z * t1) / (t1 - 2.0) - (w + z * w); |
323 » if ((j>>20) <= 0) /* subnormal output */ | 338 z = 1.0 - (r - z); |
324 » » z = scalbn(z,n); | 339 GET_HIGH_WORD(j, z); |
325 » else | 340 j += n << 20; |
326 » » SET_HIGH_WORD(z, j); | 341 if ((j >> 20) <= 0) /* subnormal output */ |
327 » return s*z; | 342 z = scalbn(z, n); |
| 343 else |
| 344 SET_HIGH_WORD(z, j); |
| 345 return s * z; |
328 } | 346 } |
OLD | NEW |