• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/builtins/builtins-utils.h"
6 #include "src/builtins/builtins.h"
7 #include "src/counters.h"
8 #include "src/objects-inl.h"
9 
10 namespace v8 {
11 namespace internal {
12 
13 // -----------------------------------------------------------------------------
14 // ES6 section 20.2.2 Function Properties of the Math Object
15 
16 // ES6 section 20.2.2.18 Math.hypot ( value1, value2, ...values )
BUILTIN(MathHypot)17 BUILTIN(MathHypot) {
18   HandleScope scope(isolate);
19   int const length = args.length() - 1;
20   if (length == 0) return Smi::kZero;
21   DCHECK_LT(0, length);
22   double max = 0;
23   bool one_arg_is_nan = false;
24   std::vector<double> abs_values;
25   abs_values.reserve(length);
26   for (int i = 0; i < length; i++) {
27     Handle<Object> x = args.at(i + 1);
28     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x,
29                                        Object::ToNumber(isolate, x));
30     double abs_value = std::abs(x->Number());
31 
32     if (std::isnan(abs_value)) {
33       one_arg_is_nan = true;
34     } else {
35       abs_values.push_back(abs_value);
36       if (max < abs_value) {
37         max = abs_value;
38       }
39     }
40   }
41 
42   if (max == V8_INFINITY) {
43     return *isolate->factory()->NewNumber(V8_INFINITY);
44   }
45 
46   if (one_arg_is_nan) {
47     return ReadOnlyRoots(isolate).nan_value();
48   }
49 
50   if (max == 0) {
51     return Smi::kZero;
52   }
53   DCHECK_GT(max, 0);
54 
55   // Kahan summation to avoid rounding errors.
56   // Normalize the numbers to the largest one to avoid overflow.
57   double sum = 0;
58   double compensation = 0;
59   for (int i = 0; i < length; i++) {
60     double n = abs_values[i] / max;
61     double summand = n * n - compensation;
62     double preliminary = sum + summand;
63     compensation = (preliminary - sum) - summand;
64     sum = preliminary;
65   }
66 
67   return *isolate->factory()->NewNumber(std::sqrt(sum) * max);
68 }
69 
70 }  // namespace internal
71 }  // namespace v8
72