Commit 264fa75e authored by bmeurer's avatar bmeurer Committed by Commit bot

[math] Fix Math.hypot to properly call ToNumber on all arguments.

The spec requires all Math functions to first call ToNumber on all
arguments before doing any other observable operation.  So early
return in case of Infinity is not valid.

Drive-by-fix: Remove the use of %_Arguments / %_ArgumentsLength and
use (strict) arguments instead of allocating a temporary InternalArray
explicitly.

R=yangguo@chromium.org

Review URL: https://codereview.chromium.org/1669773002

Cr-Commit-Position: refs/heads/master@{#33717}
parent db74cccf
...@@ -164,17 +164,14 @@ function MathHypot(x, y) { // Function length is 2. ...@@ -164,17 +164,14 @@ function MathHypot(x, y) { // Function length is 2.
// We may want to introduce fast paths for two arguments and when // We may want to introduce fast paths for two arguments and when
// normalization to avoid overflow is not necessary. For now, we // normalization to avoid overflow is not necessary. For now, we
// simply assume the general case. // simply assume the general case.
var length = %_ArgumentsLength(); var length = arguments.length;
var args = new InternalArray(length);
var max = 0; var max = 0;
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
var n = %_Arguments(i); var n = MathAbs(arguments[i]);
n = TO_NUMBER(n);
if (n === INFINITY || n === -INFINITY) return INFINITY;
n = MathAbs(n);
if (n > max) max = n; if (n > max) max = n;
args[i] = n; arguments[i] = n;
} }
if (max === INFINITY) return INFINITY;
// Kahan summation to avoid rounding errors. // Kahan summation to avoid rounding errors.
// Normalize the numbers to the largest one to avoid overflow. // Normalize the numbers to the largest one to avoid overflow.
...@@ -182,7 +179,7 @@ function MathHypot(x, y) { // Function length is 2. ...@@ -182,7 +179,7 @@ function MathHypot(x, y) { // Function length is 2.
var sum = 0; var sum = 0;
var compensation = 0; var compensation = 0;
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
var n = args[i] / max; var n = arguments[i] / max;
var summand = n * n - compensation; var summand = n * n - compensation;
var preliminary = sum + summand; var preliminary = sum + summand;
compensation = (preliminary - sum) - summand; compensation = (preliminary - sum) - summand;
......
...@@ -56,6 +56,13 @@ x = ""; ...@@ -56,6 +56,13 @@ x = "";
assertEquals(1, Math.pow(v, w)); assertEquals(1, Math.pow(v, w));
assertEquals("hestfisk", x, "pow"); assertEquals("hestfisk", x, "pow");
x = "";
var a = {valueOf: function() { x += "hest"; return 1/0; }};
var b = {valueOf: function() { x += "fisk"; return 1}};
assertEquals(1/0, Math.hypot(a, b));
assertEquals("hestfisk", x, "hypot");
var year = { valueOf: function() { x += 1; return 2007; } }; var year = { valueOf: function() { x += 1; return 2007; } };
var month = { valueOf: function() { x += 2; return 2; } }; var month = { valueOf: function() { x += 2; return 2; } };
var date = { valueOf: function() { x += 3; return 4; } }; var date = { valueOf: function() { x += 3; return 4; } };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment