Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(555)

Side by Side Diff: src/math.js

Issue 305403002: fdlibm: reduce accuracy slightly in favor of performance. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | src/rempio2.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 "use strict"; 5 "use strict";
6 6
7 // This file relies on the fact that the following declarations have been made 7 // This file relies on the fact that the following declarations have been made
8 // in runtime.js: 8 // in runtime.js:
9 // var $Object = global.Object; 9 // var $Object = global.Object;
10 10
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 // software is freely granted, provided that this notice 181 // software is freely granted, provided that this notice
182 // is preserved. 182 // is preserved.
183 // ==================================================== 183 // ====================================================
184 184
185 var invpio2 = 6.36619772367581382433e-01; 185 var invpio2 = 6.36619772367581382433e-01;
186 var pio2_1 = 1.57079632673412561417e+00; 186 var pio2_1 = 1.57079632673412561417e+00;
187 var pio2_1t = 6.07710050650619224932e-11; 187 var pio2_1t = 6.07710050650619224932e-11;
188 var pio2_2 = 6.07710050630396597660e-11; 188 var pio2_2 = 6.07710050630396597660e-11;
189 var pio2_2t = 2.02226624879595063154e-21; 189 var pio2_2t = 2.02226624879595063154e-21;
190 190
191 // Table of values of multiples of pi/2 from pi/2 to 50*pi/2. This is
192 // used as a quick check to see if an argument is close to a multiple
193 // of pi/2 and needs extra bits for reduction. This array contains
194 // the high word the multiple of pi/2.
195
196 var npio2_hw = [
197 0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
198 0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
199 0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
200 0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
201 0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
202 0x404858EB, 0x404921FB
203 ];
204
205 macro REMPIO2(x) 191 macro REMPIO2(x)
206 var n, y0, y1; 192 var n, y;
207 var hx = %_DoubleHi(x); 193 var hx = %_DoubleHi(x);
208 var ix = hx & 0x7fffffff; 194 var ix = hx & 0x7fffffff;
209 195
210 if (ix < 0x4002d97c) { 196 if (ix < 0x4002d97c) {
211 // |x| ~< 3*pi/4, special case with n = +/- 1 197 // |x| ~< 3*pi/4, special case with n = +/- 1
212 if (hx > 0) { 198 if (hx > 0) {
213 var z = x - pio2_1; 199 y = x - pio2_1 - pio2_2 - pio2_2t;
Raymond Toy 2014/06/02 16:55:53 I don't think this is computing the same values as
214 if (ix != 0x3ff921fb) {
215 // 33+53 bit pi is good enough
216 y0 = z - pio2_1t;
217 y1 = (z - y0) - pio2_1t;
218 } else {
219 // near pi/2, use 33+33+53 bit pi
220 z -= pio2_2;
221 y0 = z - pio2_2t;
222 y1 = (z - y0) - pio2_2t;
223 }
224 n = 1; 200 n = 1;
225 } else { 201 } else {
226 // Negative x 202 y = x + pio2_1 + pio2_2 + pio2_2t;
227 var z = x + pio2_1;
228 if (ix != 0x3ff921fb) {
229 // 33+53 bit pi is good enough
230 y0 = z + pio2_1t;
231 y1 = (z - y0) + pio2_1t;
232 } else {
233 // near pi/2, use 33+33+53 bit pi
234 z += pio2_2;
235 y0 = z + pio2_2t;
236 y1 = (z - y0) + pio2_2t;
237 }
238 n = -1; 203 n = -1;
239 } 204 }
240 } else if (ix <= 0x413921fb) { 205 } else if (ix <= 0x413921fb) {
241 // |x| ~<= 2^19*(pi/2), medium size 206 // |x| ~<= 2^19*(pi/2), medium size
242 var t = MathAbs(x); 207 var t = MathAbs(x);
243 n = MathRound(t * invpio2); 208 n = MathRound(t * invpio2);
244 var fn = n; 209 var fn = n;
245 var r = t - fn * pio2_1; 210 var r = t - fn * pio2_1;
246 var w = fn * pio2_1t; 211 var w = fn * pio2_1t;
247 // First round good to 85 bit 212 // First round good to 85 bit
248 if (n < 32 && ix != npio2_hw[n - 1]) { 213 y = r - w;
249 // Quick check for cancellation 214 var i = (ix - (%_DoubleHi(y) & 0x7ff00000)) >> 20;
250 y0 = r - w; 215 if (i > 16) {
251 } else { 216 // 2nd iteration needed, good to 118
252 var j = ix >> 20; 217 t = r;
253 y0 = r - w; 218 w = fn * pio2_2;
254 var i = j - (( %_DoubleHi(y0) >> 20) & 0x7ff); 219 r = t - w;
255 if (i > 16) { 220 w = fn * pio2_2t - ((t - r) - w);
256 // 2nd iteration needed, good to 118 221 y = r - w;
257 t = r;
258 w = fn * pio2_2;
259 r = t - w;
260 w = fn * pio2_2t - ((t - r) - w);
261 y0 = r - w;
262 }
263 } 222 }
264 y1 = (r - y0) - w;
265 if (hx < 0) { 223 if (hx < 0) {
266 n = -n; 224 n = -n;
267 y0 = -y0; 225 y = -y;
268 y1 = -y1;
269 } 226 }
270 } else if (ix >= 0x7ff00000) { 227 } else if (ix >= 0x7ff00000) {
271 n = 0; 228 n = 0;
272 y0 = NAN; 229 y = NAN;
273 y1 = NAN;
274 } else { 230 } else {
275 // Need to do full Payne-Hanek reduction here! 231 // Need to do full Payne-Hanek reduction here!
276 var r = %RemPiO2(x); 232 var r = %RemPiO2(x);
277 n = r[0]; 233 n = r[0];
278 y0 = r[1]; 234 y = r[1];
279 y1 = r[2];
280 } 235 }
281 endmacro 236 endmacro
282 237
283 // Sine for [-pi/4, pi/4], pi/4 ~ 0.7854 238 // Sine for [-pi/4, pi/4], pi/4 ~ 0.7854
284 239
285 var S1 = -1.66666666666666324348e-01; 240 var S1 = -1.66666666666666324348e-01;
286 var S2 = 8.33333333332248946124e-03; 241 var S2 = 8.33333333332248946124e-03;
287 var S3 = -1.98412698298579493134e-04; 242 var S3 = -1.98412698298579493134e-04;
288 var S4 = 2.75573137070700676789e-06; 243 var S4 = 2.75573137070700676789e-06;
289 var S5 = -2.50507602534068634195e-08; 244 var S5 = -2.50507602534068634195e-08;
290 var S6 = 1.58969099521155010221e-10; 245 var S6 = 1.58969099521155010221e-10;
291 246
292 function KernelSin(x, y) { 247 function KernelSin(x) {
293 var z = x * x; 248 var z = x * x;
294 var v = z * x; 249 var v = z * x;
295 var r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6))); 250 var r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)));
296 return x - ((z * (0.5 * y - v * r) - y) - v * S1); 251 return v * (z * r + S1) + x;
297 } 252 }
298 253
299 // Cosine for [-pi/4, pi/4], pi/4 ~ 0.7854 254 // Cosine for [-pi/4, pi/4], pi/4 ~ 0.7854
300 255
301 var C1 = 4.16666666666666019037e-02; 256 var C1 = 4.16666666666666019037e-02;
302 var C2 = -1.38888888888741095749e-03; 257 var C2 = -1.38888888888741095749e-03;
303 var C3 = 2.48015872894767294178e-05; 258 var C3 = 2.48015872894767294178e-05;
304 var C4 = -2.75573143513906633035e-07; 259 var C4 = -2.75573143513906633035e-07;
305 var C5 = 2.08757232129817482790e-09; 260 var C5 = 2.08757232129817482790e-09;
306 var C6 = -1.13596475577881948265e-11; 261 var C6 = -1.13596475577881948265e-11;
307 262
308 function KernelCos(x, y) { 263 function KernelCos(x) {
309 var ix = %_DoubleHi(x) & 0x7fffffff; 264 var ix = %_DoubleHi(x) & 0x7fffffff;
310 var z = x * x; 265 var z = x * x;
311 var r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6))))); 266 var r = z * (C1 + z * (C2 + z * (C3 + z * (C4 + z * (C5 + z * C6)))));
312 if (ix < 0x3fd33333) { 267 if (ix < 0x3fd33333) {
313 return 1 - (0.5 * z - (z * r - x * y)); 268 return (r - 0.5) * z + 1;
314 } else { 269 } else {
315 var qx; 270 var qx;
316 if (ix > 0x3fe90000) { 271 if (ix > 0x3fe90000) {
317 qx = 0.28125; 272 qx = 0.28125;
318 } else { 273 } else {
319 qx = %_ConstructDouble(%_DoubleHi(0.25 * x), 0); 274 qx = %_ConstructDouble(%_DoubleHi(0.25 * x), 0);
320 } 275 }
321 var hz = 0.5 * z - qx; 276 return (1 - qx) - ((0.5 * z - qx) - (z * r));
322 var a = 1 - qx;
323 return a - (hz - (z * r - x * y));
324 } 277 }
325 } 278 }
326 279
327 // Tangent for [-pi/4, pi/4], pi/4 ~ 0.7854 280 // Tangent for [-pi/4, pi/4], pi/4 ~ 0.7854
328 281
329 var T0 = 3.33333333333334091986e-01; 282 var T0 = 3.33333333333334091986e-01;
330 var T1 = 1.33333333333201242699e-01; 283 var T1 = 1.33333333333201242699e-01;
331 var T2 = 5.39682539762260521377e-02; 284 var T2 = 5.39682539762260521377e-02;
332 var T3 = 2.18694882948595424599e-02; 285 var T3 = 2.18694882948595424599e-02;
333 var T4 = 8.86323982359930005737e-03; 286 var T4 = 8.86323982359930005737e-03;
334 var T5 = 3.59207910759131235356e-03; 287 var T5 = 3.59207910759131235356e-03;
335 var T6 = 1.45620945432529025516e-03; 288 var T6 = 1.45620945432529025516e-03;
336 var T7 = 5.88041240820264096874e-04; 289 var T7 = 5.88041240820264096874e-04;
337 var T8 = 2.46463134818469906812e-04; 290 var T8 = 2.46463134818469906812e-04;
338 var T9 = 7.81794442939557092300e-05; 291 var T9 = 7.81794442939557092300e-05;
339 var T10 = 7.14072491382608190305e-05; 292 var T10 = 7.14072491382608190305e-05;
340 var T11 = -1.85586374855275456654e-05; 293 var T11 = -1.85586374855275456654e-05;
341 var T12 = 2.59073051863633712884e-05; 294 var T12 = 2.59073051863633712884e-05;
342 295
343 function KernelTan(x, y, returnTan) { 296 function KernelTan(x, returnTan) {
344 var z; 297 var z;
345 var w; 298 var w;
346 var hx = %_DoubleHi(x); 299 var hx = %_DoubleHi(x);
347 var ix = hx & 0x7fffffff; 300 var ix = hx & 0x7fffffff;
348 301
349 if (ix < 0x3e300000) { 302 if (ix < 0x3e300000) {
350 // x < 2^-28 303 // x < 2^-28
351 // We don't try to generate inexact. 304 // We don't try to generate inexact.
352 if (((ix | %_DoubleLo(x)) | (returnTan + 1)) == 0) { 305 if (((ix | %_DoubleLo(x)) | (returnTan + 1)) == 0) {
353 return 1 / MathAbs(x); 306 return 1 / MathAbs(x);
354 } else { 307 } else {
355 if (returnTan == 1) { 308 if (returnTan == 1) {
356 return x; 309 return x;
357 } else { 310 } else {
358 // Compute -1/(x + y) carefully 311 // Compute -1/(x + y) carefully
359 var w = x + y; 312 var w = x;
360 var z = %_ConstructDouble( %_DoubleHi(w), 0); 313 var z = %_ConstructDouble( %_DoubleHi(w), 0);
361 var v = y - (z - x); 314 var v = x - z;
362 var a = -1 / w; 315 var a = -1 / w;
363 var t = %_ConstructDouble( %_DoubleHi(a), 0); 316 var t = %_ConstructDouble( %_DoubleHi(a), 0);
364 var s = 1 + t * z; 317 var s = 1 + t * z;
365 return t + a * (s + t * v); 318 return t + a * (s + t * v);
366 } 319 }
367 } 320 }
368 } 321 }
369 if (ix >= 0x3fe59429) { 322 if (ix >= 0x3fe59429) {
370 // |x| > .6744 323 // |x| > .6744
371 if (x < 0) { 324 if (x < 0) {
372 x = -x; 325 x = -x;
373 y = -y;
374 } 326 }
375 var pio4 = 7.85398163397448278999e-01; 327 var pio4 = 7.85398163397448278999e-01;
376 var pio4lo = 3.06161699786838301793e-17; 328 var pio4lo = 3.06161699786838301793e-17;
377 z = pio4 - x; 329 z = pio4 - x;
378 w = pio4lo - y; 330 w = pio4lo;
379 x = z + w; 331 x = z + w;
380 y = 0;
381 } 332 }
382 z = x * x; 333 z = x * x;
383 w = z * z; 334 w = z * z;
384 // 335 //
385 // Break x^5*(T[1]+x^2*T[2]+...) into 336 // Break x^5*(T[1]+x^2*T[2]+...) into
386 // x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + 337 // x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
387 // x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) 338 // x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
388 // 339 //
389 var r = T1 + w * (T3 + w * (T5 + w * (T7 + w * (T9 + w * T11)))); 340 var r = T1 + w * (T3 + w * (T5 + w * (T7 + w * (T9 + w * T11))));
390 var v = z * (T2 + w * (T4 + w * (T6 + w * (T8 + w * (T10 + w * T12))))); 341 var v = z * (T2 + w * (T4 + w * (T6 + w * (T8 + w * (T10 + w * T12)))));
391 var s = z * x; 342 var s = z * x;
392 r = y + z * (s * (r + v) + y); 343 r = z * (s * (r + v));
393 r = r + T0 * s; 344 r = r + T0 * s;
394 w = x + r; 345 w = x + r;
395 if (ix >= 0x3fe59428) { 346 if (ix >= 0x3fe59428) {
396 return (1 - ((hx >> 30) & 2)) * 347 return (1 - ((hx >> 30) & 2)) *
397 (returnTan - 2.0 * (x - (w * w / (w + returnTan) - r))); 348 (returnTan - 2.0 * (x - (w * w / (w + returnTan) - r)));
398 } 349 }
399 if (returnTan == 1) { 350 if (returnTan == 1) {
400 return w; 351 return w;
401 } else { 352 } else {
402 // Compute -1/(x+r) accurately 353 // Compute -1/(x+r) accurately
403 z = %_ConstructDouble( %_DoubleHi(w), 0); 354 z = %_ConstructDouble( %_DoubleHi(w), 0);
404 v = r - (z - x); // z+v = r+x 355 v = r - (z - x); // z+v = r+x
405 var a = -1 / w; 356 var a = -1 / w;
406 var t = %_ConstructDouble( %_DoubleHi(a), 0); 357 var t = %_ConstructDouble( %_DoubleHi(a), 0);
407 s = 1 + t * z; 358 s = 1 + t * z;
408 return t + a * (s + t * v); 359 return t + a * (s + t * v);
409 } 360 }
410 } 361 }
411 362
412 363
413 function MathSinSlow(x) { 364 function MathSinSlow(x) {
414 REMPIO2(x); 365 REMPIO2(x);
415 if (n & 2) { 366 if (n & 2) {
416 if (n & 1) { 367 if (n & 1) {
417 return -KernelCos(y0, y1); 368 return -KernelCos(y);
418 } else { 369 } else {
419 return -KernelSin(y0, y1); 370 return -KernelSin(y);
420 } 371 }
421 } else { 372 } else {
422 if (n & 1) { 373 if (n & 1) {
423 return KernelCos(y0, y1); 374 return KernelCos(y);
424 } else { 375 } else {
425 return KernelSin(y0, y1); 376 return KernelSin(y);
426 } 377 }
427 } 378 }
428 } 379 }
429 380
430 function MathCosSlow(x) { 381 function MathCosSlow(x) {
431 REMPIO2(x); 382 REMPIO2(x);
432 if (n & 2) { 383 if (n & 2) {
433 if (n & 1) { 384 if (n & 1) {
434 return KernelSin(y0, y1); 385 return KernelSin(y);
435 } else { 386 } else {
436 return -KernelCos(y0, y1); 387 return -KernelCos(y);
437 } 388 }
438 } else { 389 } else {
439 if (n & 1) { 390 if (n & 1) {
440 return -KernelSin(y0, y1); 391 return -KernelSin(y);
441 } else { 392 } else {
442 return KernelCos(y0, y1); 393 return KernelCos(y);
443 } 394 }
444 } 395 }
445 } 396 }
446 397
447 function MathTanSlow(x) { 398 function MathTanSlow(x) {
448 REMPIO2(x); 399 REMPIO2(x);
449 // flag is 1 if n is even and -1 if n is odd 400 // flag is 1 if n is even and -1 if n is odd
450 var flag = (n & 1) ? -1 : 1; 401 var flag = (n & 1) ? -1 : 1;
451 return KernelTan(y0, y1, flag) 402 return KernelTan(y, flag)
452 } 403 }
453 404
454 //ECMA 262 - 15.8.2.16 405 //ECMA 262 - 15.8.2.16
455 function MathSin(x) { 406 function MathSin(x) {
456 x = x * 1; // Convert to number and deal with -0. 407 x = x * 1; // Convert to number and deal with -0.
457 if (%_IsMinusZero(x)) return x; 408 if (%_IsMinusZero(x)) return x;
458 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { 409 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) {
459 // |x| < pi/4, approximately. No reduction needed. 410 // |x| < pi/4, approximately. No reduction needed.
460 var z = x * x; 411 var z = x * x;
461 var v = z * x; 412 var v = z * x;
462 var r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6))); 413 var r = S2 + z * (S3 + z * (S4 + z * (S5 + z * S6)));
463 return x + v * (S1 + z * r); 414 return x + v * (S1 + z * r);
464 } 415 }
465 return MathSinSlow(x); 416 return MathSinSlow(x);
466 } 417 }
467 418
468 //ECMA 262 - 15.8.2.7 419 //ECMA 262 - 15.8.2.7
469 function MathCos(x) { 420 function MathCos(x) {
470 x = x * 1; // Convert to number; 421 x = x * 1; // Convert to number;
471 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { 422 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) {
472 // |x| < pi/4, approximately. No reduction needed. 423 // |x| < pi/4, approximately. No reduction needed.
473 return KernelCos(x, 0); 424 return KernelCos(x);
474 } 425 }
475 return MathCosSlow(x); 426 return MathCosSlow(x);
476 } 427 }
477 428
478 //ECMA 262 - 15.8.2.18 429 //ECMA 262 - 15.8.2.18
479 function MathTan(x) { 430 function MathTan(x) {
480 x = x * 1; // Convert to number and deal with -0. 431 x = x * 1; // Convert to number and deal with -0.
481 if (%_IsMinusZero(x)) return x; 432 if (%_IsMinusZero(x)) return x;
482 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) { 433 if ((%_DoubleHi(x) & 0x7fffffff) <= 0x3fe921fb) {
483 // |x| < pi/4, approximately. No reduction needed. 434 // |x| < pi/4, approximately. No reduction needed.
484 return KernelTan(x, 0, 1); 435 return KernelTan(x, 1);
485 } 436 }
486 return MathTanSlow(x); 437 return MathTanSlow(x);
487 } 438 }
488 439
489 // ------------------------------------------------------------------- 440 // -------------------------------------------------------------------
490 441
491 function SetUpMath() { 442 function SetUpMath() {
492 %CheckIsBootstrapping(); 443 %CheckIsBootstrapping();
493 444
494 %SetPrototype($Math, $Object.prototype); 445 %SetPrototype($Math, $Object.prototype);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 %SetInlineBuiltinFlag(MathRandom); 490 %SetInlineBuiltinFlag(MathRandom);
540 %SetInlineBuiltinFlag(MathSin); 491 %SetInlineBuiltinFlag(MathSin);
541 %SetInlineBuiltinFlag(MathCos); 492 %SetInlineBuiltinFlag(MathCos);
542 %SetInlineBuiltinFlag(MathTan); 493 %SetInlineBuiltinFlag(MathTan);
543 %SetInlineBuiltinFlag(KernelSin); 494 %SetInlineBuiltinFlag(KernelSin);
544 %SetInlineBuiltinFlag(KernelCos); 495 %SetInlineBuiltinFlag(KernelCos);
545 %SetInlineBuiltinFlag(KernelTan); 496 %SetInlineBuiltinFlag(KernelTan);
546 } 497 }
547 498
548 SetUpMath(); 499 SetUpMath();
OLDNEW
« no previous file with comments | « no previous file | src/rempio2.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698