OLD | NEW |
1 // The following is adapted from fdlibm (http://www.netlib.org/fdlibm), | 1 // The following is adapted from fdlibm (http://www.netlib.org/fdlibm), |
2 // | 2 // |
3 // ==================================================== | 3 // ==================================================== |
4 // Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved. | 4 // Copyright (C) 1993-2004 by Sun Microsystems, Inc. All rights reserved. |
5 // | 5 // |
6 // Developed at SunSoft, a Sun Microsystems, Inc. business. | 6 // Developed at SunSoft, a Sun Microsystems, Inc. business. |
7 // Permission to use, copy, modify, and distribute this | 7 // Permission to use, copy, modify, and distribute this |
8 // software is freely granted, provided that this notice | 8 // software is freely granted, provided that this notice |
9 // is preserved. | 9 // is preserved. |
10 // ==================================================== | 10 // ==================================================== |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 // | x | | 134 // | x | |
135 // | 135 // |
136 // 3. ieee_sin(X+Y) = ieee_sin(X) + sin'(X')*Y | 136 // 3. ieee_sin(X+Y) = ieee_sin(X) + sin'(X')*Y |
137 // ~ ieee_sin(X) + (1-X*X/2)*Y | 137 // ~ ieee_sin(X) + (1-X*X/2)*Y |
138 // For better accuracy, let | 138 // For better accuracy, let |
139 // 3 2 2 2 2 | 139 // 3 2 2 2 2 |
140 // r = X *(S2+X *(S3+X *(S4+X *(S5+X *S6)))) | 140 // r = X *(S2+X *(S3+X *(S4+X *(S5+X *S6)))) |
141 // then 3 2 | 141 // then 3 2 |
142 // sin(x) = X + (S1*X + (X *(r-Y/2)+Y)) | 142 // sin(x) = X + (S1*X + (X *(r-Y/2)+Y)) |
143 // | 143 // |
144 macro KSIN(x) | 144 const S1 = -1.66666666666666324348e-01; |
145 kMath[7+x] | 145 const S2 = 8.33333333332248946124e-03; |
146 endmacro | 146 const S3 = -1.98412698298579493134e-04; |
| 147 const S4 = 2.75573137070700676789e-06; |
| 148 const S5 = -2.50507602534068634195e-08; |
| 149 const S6 = 1.58969099521155010221e-10; |
147 | 150 |
148 macro RETURN_KERNELSIN(X, Y, SIGN) | 151 macro RETURN_KERNELSIN(X, Y, SIGN) |
149 var z = X * X; | 152 var z = X * X; |
150 var v = z * X; | 153 var v = z * X; |
151 var r = KSIN(1) + z * (KSIN(2) + z * (KSIN(3) + | 154 var r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6))); |
152 z * (KSIN(4) + z * KSIN(5)))); | 155 return (X - ((z * (0.5 * Y - v * r) - Y) - v * S1)) SIGN; |
153 return (X - ((z * (0.5 * Y - v * r) - Y) - v * KSIN(0))) SIGN; | |
154 endmacro | 156 endmacro |
155 | 157 |
156 // __kernel_cos(X, Y) | 158 // __kernel_cos(X, Y) |
157 // kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 | 159 // kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 |
158 // Input X is assumed to be bounded by ~pi/4 in magnitude. | 160 // Input X is assumed to be bounded by ~pi/4 in magnitude. |
159 // Input Y is the tail of X so that x = X + Y. | 161 // Input Y is the tail of X so that x = X + Y. |
160 // | 162 // |
161 // Algorithm | 163 // Algorithm |
162 // 1. Since ieee_cos(-x) = ieee_cos(x), we need only to consider positive x. | 164 // 1. Since ieee_cos(-x) = ieee_cos(x), we need only to consider positive x. |
163 // 2. ieee_cos(x) is approximated by a polynomial of degree 14 on | 165 // 2. ieee_cos(x) is approximated by a polynomial of degree 14 on |
(...skipping 14 matching lines...) Expand all Loading... |
178 // a correction term is necessary in ieee_cos(x) and hence | 180 // a correction term is necessary in ieee_cos(x) and hence |
179 // cos(X+Y) = 1 - (X*X/2 - (r - X*Y)) | 181 // cos(X+Y) = 1 - (X*X/2 - (r - X*Y)) |
180 // For better accuracy when x > 0.3, let qx = |x|/4 with | 182 // For better accuracy when x > 0.3, let qx = |x|/4 with |
181 // the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. | 183 // the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. |
182 // Then | 184 // Then |
183 // cos(X+Y) = (1-qx) - ((X*X/2-qx) - (r-X*Y)). | 185 // cos(X+Y) = (1-qx) - ((X*X/2-qx) - (r-X*Y)). |
184 // Note that 1-qx and (X*X/2-qx) is EXACT here, and the | 186 // Note that 1-qx and (X*X/2-qx) is EXACT here, and the |
185 // magnitude of the latter is at least a quarter of X*X/2, | 187 // magnitude of the latter is at least a quarter of X*X/2, |
186 // thus, reducing the rounding error in the subtraction. | 188 // thus, reducing the rounding error in the subtraction. |
187 // | 189 // |
188 macro KCOS(x) | 190 const C1 = 4.16666666666666019037e-02; |
189 kMath[13+x] | 191 const C2 = -1.38888888888741095749e-03; |
190 endmacro | 192 const C3 = 2.48015872894767294178e-05; |
| 193 const C4 = -2.75573143513906633035e-07; |
| 194 const C5 = 2.08757232129817482790e-09; |
| 195 const C6 = -1.13596475577881948265e-11; |
191 | 196 |
192 macro RETURN_KERNELCOS(X, Y, SIGN) | 197 macro RETURN_KERNELCOS(X, Y, SIGN) |
193 var ix = %_DoubleHi(X) & 0x7fffffff; | 198 var ix = %_DoubleHi(X) & 0x7fffffff; |
194 var z = X * X; | 199 var z = X * X; |
195 var r = z * (KCOS(0) + z * (KCOS(1) + z * (KCOS(2)+ | 200 var r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6))))); |
196 z * (KCOS(3) + z * (KCOS(4) + z * KCOS(5)))))); | |
197 if (ix < 0x3fd33333) { // |x| ~< 0.3 | 201 if (ix < 0x3fd33333) { // |x| ~< 0.3 |
198 return (1 - (0.5 * z - (z * r - X * Y))) SIGN; | 202 return (1 - (0.5 * z - (z * r - X * Y))) SIGN; |
199 } else { | 203 } else { |
200 var qx; | 204 var qx; |
201 if (ix > 0x3fe90000) { // |x| > 0.78125 | 205 if (ix > 0x3fe90000) { // |x| > 0.78125 |
202 qx = 0.28125; | 206 qx = 0.28125; |
203 } else { | 207 } else { |
204 qx = %_ConstructDouble(%_DoubleHi(0.25 * X), 0); | 208 qx = %_ConstructDouble(%_DoubleHi(0.25 * X), 0); |
205 } | 209 } |
206 var hz = 0.5 * z - qx; | 210 var hz = 0.5 * z - qx; |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 var sign = (n & 2) - 1; | 333 var sign = (n & 2) - 1; |
330 RETURN_KERNELSIN(y0, y1, * sign); | 334 RETURN_KERNELSIN(y0, y1, * sign); |
331 } else { | 335 } else { |
332 var sign = 1 - (n & 2); | 336 var sign = 1 - (n & 2); |
333 RETURN_KERNELCOS(y0, y1, * sign); | 337 RETURN_KERNELCOS(y0, y1, * sign); |
334 } | 338 } |
335 } | 339 } |
336 | 340 |
337 // ECMA 262 - 15.8.2.16 | 341 // ECMA 262 - 15.8.2.16 |
338 function MathSin(x) { | 342 function MathSin(x) { |
339 x = x * 1; // Convert to number. | 343 x = +x; // Convert to number. |
340 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { | 344 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { |
341 // |x| < pi/4, approximately. No reduction needed. | 345 // |x| < pi/4, approximately. No reduction needed. |
342 RETURN_KERNELSIN(x, 0, /* empty */); | 346 RETURN_KERNELSIN(x, 0, /* empty */); |
343 } | 347 } |
344 return MathSinSlow(x); | 348 return +MathSinSlow(x); |
345 } | 349 } |
346 | 350 |
347 // ECMA 262 - 15.8.2.7 | 351 // ECMA 262 - 15.8.2.7 |
348 function MathCos(x) { | 352 function MathCos(x) { |
349 x = x * 1; // Convert to number. | 353 x = +x; // Convert to number. |
350 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { | 354 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { |
351 // |x| < pi/4, approximately. No reduction needed. | 355 // |x| < pi/4, approximately. No reduction needed. |
352 RETURN_KERNELCOS(x, 0, /* empty */); | 356 RETURN_KERNELCOS(x, 0, /* empty */); |
353 } | 357 } |
354 return MathCosSlow(x); | 358 return +MathCosSlow(x); |
355 } | 359 } |
356 | 360 |
357 // ECMA 262 - 15.8.2.18 | 361 // ECMA 262 - 15.8.2.18 |
358 function MathTan(x) { | 362 function MathTan(x) { |
359 x = x * 1; // Convert to number. | 363 x = x * 1; // Convert to number. |
360 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { | 364 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { |
361 // |x| < pi/4, approximately. No reduction needed. | 365 // |x| < pi/4, approximately. No reduction needed. |
362 return KernelTan(x, 0, 1); | 366 return KernelTan(x, 0, 1); |
363 } | 367 } |
364 REMPIO2(x); | 368 REMPIO2(x); |
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
990 z_l = CP_L * p_h + p_l * CP + dp_l; | 994 z_l = CP_L * p_h + p_l * CP + dp_l; |
991 | 995 |
992 // log2(ax) = (ss + ...) * 2 / (3 * log(2)) = n + dp_h + z_h + z_l | 996 // log2(ax) = (ss + ...) * 2 / (3 * log(2)) = n + dp_h + z_h + z_l |
993 var t = n; | 997 var t = n; |
994 var t1 = %_ConstructDouble(%_DoubleHi(((z_h + z_l) + dp_h) + t), 0); | 998 var t1 = %_ConstructDouble(%_DoubleHi(((z_h + z_l) + dp_h) + t), 0); |
995 var t2 = z_l - (((t1 - t) - dp_h) - z_h); | 999 var t2 = z_l - (((t1 - t) - dp_h) - z_h); |
996 | 1000 |
997 // t1 + t2 = log2(ax), sum up because we do not care about extra precision. | 1001 // t1 + t2 = log2(ax), sum up because we do not care about extra precision. |
998 return t1 + t2; | 1002 return t1 + t2; |
999 } | 1003 } |
OLD | NEW |