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)17BUILTIN(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