| Index: src/runtime.cc
|
| ===================================================================
|
| --- src/runtime.cc (revision 2195)
|
| +++ src/runtime.cc (working copy)
|
| @@ -4161,16 +4161,62 @@
|
| }
|
|
|
|
|
| +// Helper function to compute x^y, where y is known to be an
|
| +// integer. Uses binary decomposition to limit the number of
|
| +// multiplications; see the discussion in "Hacker's Delight" by Henry
|
| +// S. Warren, Jr., figure 11-6, page 213.
|
| +static double powi(double x, int y) {
|
| + ASSERT(y != kMinInt);
|
| + unsigned n = (y < 0) ? -y : y;
|
| + double m = x;
|
| + double p = 1;
|
| + while (true) {
|
| + if ((n & 1) != 0) p *= m;
|
| + n >>= 1;
|
| + if (n == 0) {
|
| + if (y < 0) {
|
| + // Unfortunately, we have to be careful when p has reached
|
| + // infinity in the computation, because sometimes the higher
|
| + // internal precision in the pow() implementation would have
|
| + // given us a finite p. This happens very rarely.
|
| + double result = 1.0 / p;
|
| + return (result == 0 && isinf(p)) ? pow(x, y) : result;
|
| + } else {
|
| + return p;
|
| + }
|
| + }
|
| + m *= m;
|
| + }
|
| +}
|
| +
|
| +
|
| static Object* Runtime_Math_pow(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 2);
|
|
|
| CONVERT_DOUBLE_CHECKED(x, args[0]);
|
| +
|
| + // If the second argument is a smi, it is much faster to call the
|
| + // custom powi() function than the generic pow().
|
| + if (args[1]->IsSmi()) {
|
| + int y = Smi::cast(args[1])->value();
|
| + return Heap::AllocateHeapNumber(powi(x, y));
|
| + }
|
| +
|
| CONVERT_DOUBLE_CHECKED(y, args[1]);
|
| - if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
|
| - return Heap::nan_value();
|
| + if (y == 0.5) {
|
| + // It's not uncommon to use Math.pow(x, 0.5) to compute the square
|
| + // root of a number. To speed up such computations, we explictly
|
| + // check for this case and use the sqrt() function which is faster
|
| + // than pow().
|
| + return Heap::AllocateHeapNumber(sqrt(x));
|
| + } else if (y == -0.5) {
|
| + // Optimized using Math.pow(x, -0.5) == 1 / Math.pow(x, 0.5).
|
| + return Heap::AllocateHeapNumber(1.0 / sqrt(x));
|
| } else if (y == 0) {
|
| return Smi::FromInt(1);
|
| + } else if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
|
| + return Heap::nan_value();
|
| } else {
|
| return Heap::AllocateHeapNumber(pow(x, y));
|
| }
|
|
|