Title: [165795] trunk
Revision
165795
Author
[email protected]
Date
2014-03-17 20:21:22 -0700 (Mon, 17 Mar 2014)

Log Message

Implement Math.hypot
https://bugs.webkit.org/show_bug.cgi?id=129486

Patch by Tibor Meszaros <[email protected]> on 2014-03-17
Reviewed by Darin Adler.

Source/_javascript_Core:

* runtime/MathObject.cpp:
(JSC::MathObject::finishCreation):
(JSC::mathProtoFuncHypot):

LayoutTests:

* js/Object-getOwnPropertyNames-expected.txt:
* js/math-expected.txt:
* js/script-tests/Object-getOwnPropertyNames.js:
* js/script-tests/math.js:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (165794 => 165795)


--- trunk/LayoutTests/ChangeLog	2014-03-18 03:17:44 UTC (rev 165794)
+++ trunk/LayoutTests/ChangeLog	2014-03-18 03:21:22 UTC (rev 165795)
@@ -1,3 +1,15 @@
+2014-03-17  Tibor Meszaros  <[email protected]>
+
+        Implement Math.hypot
+        https://bugs.webkit.org/show_bug.cgi?id=129486
+
+        Reviewed by Darin Adler.
+
+        * js/Object-getOwnPropertyNames-expected.txt:
+        * js/math-expected.txt:
+        * js/script-tests/Object-getOwnPropertyNames.js:
+        * js/script-tests/math.js:
+
 2014-03-17  Jer Noble  <[email protected]>
 
         Layout Test mathml/wbr-in-mroot-crash.html crashes

Modified: trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt (165794 => 165795)


--- trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt	2014-03-18 03:17:44 UTC (rev 165794)
+++ trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt	2014-03-18 03:21:22 UTC (rev 165795)
@@ -58,7 +58,7 @@
 PASS getSortedOwnPropertyNames(RegExp.prototype) is ['compile', 'constructor', 'exec', 'global', 'ignoreCase', 'lastIndex', 'multiline', 'source', 'test', 'toString']
 PASS getSortedOwnPropertyNames(Error) is ['length', 'name', 'prototype']
 PASS getSortedOwnPropertyNames(Error.prototype) is ['constructor', 'message', 'name', 'toString']
-PASS getSortedOwnPropertyNames(Math) is ['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','cos','cosh','exp','expm1','floor','fround','imul','log','log10','log1p','log2','max','min','pow','random','round','sin','sinh','sqrt','tan','tanh','trunc']
+PASS getSortedOwnPropertyNames(Math) is ['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sin','sinh','sqrt','tan','tanh','trunc']
 PASS getSortedOwnPropertyNames(JSON) is ['parse', 'stringify']
 PASS globalPropertyNames.indexOf('NaN') != -1 is true
 PASS globalPropertyNames.indexOf('Infinity') != -1 is true

Modified: trunk/LayoutTests/js/math-expected.txt (165794 => 165795)


--- trunk/LayoutTests/js/math-expected.txt	2014-03-18 03:17:44 UTC (rev 165794)
+++ trunk/LayoutTests/js/math-expected.txt	2014-03-18 03:21:22 UTC (rev 165795)
@@ -83,6 +83,29 @@
 PASS Math.floor(-Number.MAX_VALUE) is -Number.MAX_VALUE
 PASS Math.floor(Infinity) is Infinity
 PASS Math.floor(-Infinity) is -Infinity
+PASS Math.hypot.length is 2
+PASS Math.hypot(NaN) is NaN
+PASS Math.hypot() is 0
+PASS Math.hypot(-0) is 0
+PASS Math.hypot(0) is 0
+PASS Math.hypot(-Infinity) is Infinity
+PASS Math.hypot(Infinity) is Infinity
+PASS Math.hypot(-3) is 3
+PASS Math.hypot(3, 4) is 5
+PASS Math.hypot(1, NaN, Infinity) is Infinity
+PASS Math.hypot(3, 4, 5) is 7.0710678118654755
+PASS Math.hypot(3, 4, '5') is 7.0710678118654755
+PASS Math.hypot(-3, -4) is 5
+PASS Math.hypot(3, -Infinity) is Infinity
+PASS Math.hypot(3, NaN) is NaN
+PASS Math.hypot(NaN, 3) is NaN
+PASS Math.hypot(0, NaN) is NaN
+PASS Math.hypot(NaN, 0) is NaN
+PASS Math.hypot(NaN, {valueOf:function(){throw "err"}}) threw exception err.
+PASS Math.hypot(NaN, NaN, {valueOf:function(){throw "err"}}) threw exception err.
+PASS Math.hypot({valueOf:function(){throw "error1"}}, {valueOf:function(){sideEffect = 1}}) threw exception error1.
+PASS sideEffect is 0
+PASS Math.hypot(3, 4, 'foo') is NaN
 PASS Math.log(NaN) is NaN
 PASS Math.log(0) is -Infinity
 PASS Math.log(-0) is -Infinity

Modified: trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js (165794 => 165795)


--- trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js	2014-03-18 03:17:44 UTC (rev 165794)
+++ trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js	2014-03-18 03:21:22 UTC (rev 165795)
@@ -66,7 +66,7 @@
     "RegExp.prototype": "['compile', 'constructor', 'exec', 'global', 'ignoreCase', 'lastIndex', 'multiline', 'source', 'test', 'toString']",
     "Error": "['length', 'name', 'prototype']",
     "Error.prototype": "['constructor', 'message', 'name', 'toString']",
-    "Math": "['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','cos','cosh','exp','expm1','floor','fround','imul','log','log10','log1p','log2','max','min','pow','random','round','sin','sinh','sqrt','tan','tanh','trunc']",
+    "Math": "['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sin','sinh','sqrt','tan','tanh','trunc']",
     "JSON": "['parse', 'stringify']"
 };
 

Modified: trunk/LayoutTests/js/script-tests/math.js (165794 => 165795)


--- trunk/LayoutTests/js/script-tests/math.js	2014-03-18 03:17:44 UTC (rev 165794)
+++ trunk/LayoutTests/js/script-tests/math.js	2014-03-18 03:21:22 UTC (rev 165795)
@@ -124,6 +124,31 @@
 shouldBe("Math.floor(Infinity)", "Infinity");
 shouldBe("Math.floor(-Infinity)", "-Infinity");
 
+shouldBe("Math.hypot.length","2");
+shouldBe("Math.hypot(NaN)", "NaN");
+shouldBe("Math.hypot()", "0");
+shouldBe("Math.hypot(-0)", "0");
+shouldBe("Math.hypot(0)", "0");
+shouldBe("Math.hypot(-Infinity)", "Infinity");
+shouldBe("Math.hypot(Infinity)", "Infinity");
+shouldBe("Math.hypot(-3)", "3");
+shouldBe("Math.hypot(3, 4)", "5");
+shouldBe("Math.hypot(1, NaN, Infinity)", "Infinity");
+shouldBe("Math.hypot(3, 4, 5)", "7.0710678118654755");
+shouldBe("Math.hypot(3, 4, '5')", "7.0710678118654755");
+shouldBe("Math.hypot(-3, -4)", "5");
+shouldBe("Math.hypot(3, -Infinity)", "Infinity");
+shouldBe("Math.hypot(3, NaN)", "NaN");
+shouldBe("Math.hypot(NaN, 3)", "NaN");
+shouldBe("Math.hypot(0, NaN)", "NaN");
+shouldBe("Math.hypot(NaN, 0)", "NaN");
+shouldThrow("Math.hypot(NaN, {valueOf:function(){throw \"err\"}})","'err'");
+shouldThrow("Math.hypot(NaN, NaN, {valueOf:function(){throw \"err\"}})","'err'");
+sideEffect = 0;
+shouldThrow("Math.hypot({valueOf:function(){throw \"error1\"}}, {valueOf:function(){sideEffect = 1}})", "'error1'");
+shouldBe('sideEffect', '0');
+shouldBe("Math.hypot(3, 4, 'foo')", "NaN");
+
 shouldBe("Math.log(NaN)", "NaN");
 shouldBe("Math.log(0)", "-Infinity");
 shouldBe("Math.log(-0)", "-Infinity");

Modified: trunk/Source/_javascript_Core/ChangeLog (165794 => 165795)


--- trunk/Source/_javascript_Core/ChangeLog	2014-03-18 03:17:44 UTC (rev 165794)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-03-18 03:21:22 UTC (rev 165795)
@@ -1,3 +1,14 @@
+2014-03-17  Tibor Meszaros  <[email protected]>
+
+        Implement Math.hypot
+        https://bugs.webkit.org/show_bug.cgi?id=129486
+
+        Reviewed by Darin Adler.
+
+        * runtime/MathObject.cpp:
+        (JSC::MathObject::finishCreation):
+        (JSC::mathProtoFuncHypot):
+
 2014-03-17  Zsolt Borbely  <[email protected]>
 
         Fix the !ENABLE(PROMISES) build

Modified: trunk/Source/_javascript_Core/runtime/MathObject.cpp (165794 => 165795)


--- trunk/Source/_javascript_Core/runtime/MathObject.cpp	2014-03-18 03:17:44 UTC (rev 165794)
+++ trunk/Source/_javascript_Core/runtime/MathObject.cpp	2014-03-18 03:21:22 UTC (rev 165795)
@@ -29,6 +29,7 @@
 #include <wtf/MathExtras.h>
 #include <wtf/RandomNumber.h>
 #include <wtf/RandomNumberSeed.h>
+#include <wtf/Vector.h>
 
 namespace JSC {
 
@@ -50,6 +51,7 @@
 static EncodedJSValue JSC_HOST_CALL mathProtoFuncExpm1(ExecState*);
 static EncodedJSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState*);
 static EncodedJSValue JSC_HOST_CALL mathProtoFuncFround(ExecState*);
+static EncodedJSValue JSC_HOST_CALL mathProtoFuncHypot(ExecState*);
 static EncodedJSValue JSC_HOST_CALL mathProtoFuncLog(ExecState*);
 static EncodedJSValue JSC_HOST_CALL mathProtoFuncLog1p(ExecState*);
 static EncodedJSValue JSC_HOST_CALL mathProtoFuncLog10(ExecState*);
@@ -108,6 +110,7 @@
     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "expm1"), 1, mathProtoFuncExpm1, NoIntrinsic, DontEnum | Function);
     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "floor"), 1, mathProtoFuncFloor, FloorIntrinsic, DontEnum | Function);
     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "fround"), 1, mathProtoFuncFround, NoIntrinsic, DontEnum | Function);
+    putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "hypot"), 2, mathProtoFuncHypot, NoIntrinsic, DontEnum | Function);
     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "log"), 1, mathProtoFuncLog, LogIntrinsic, DontEnum | Function);
     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "log10"), 1, mathProtoFuncLog10, NoIntrinsic, DontEnum | Function);
     putDirectNativeFunctionWithoutTransition(vm, globalObject, Identifier(&vm, "log1p"), 1, mathProtoFuncLog1p, NoIntrinsic, DontEnum | Function);
@@ -175,6 +178,35 @@
     return JSValue::encode(jsNumber(floor(exec->argument(0).toNumber(exec))));
 }
 
+EncodedJSValue JSC_HOST_CALL mathProtoFuncHypot(ExecState* exec)
+{
+    unsigned argsCount = exec->argumentCount();
+    double max = 0;
+    Vector<double, 8> args;
+    args.reserveInitialCapacity(argsCount);
+    for (unsigned i = 0; i < argsCount; ++i) {
+        args.uncheckedAppend(exec->uncheckedArgument(i).toNumber(exec));
+        if (exec->hadException())
+            return JSValue::encode(jsNull());
+        if (std::isinf(args[i]))
+            return JSValue::encode(jsDoubleNumber(+std::numeric_limits<double>::infinity()));
+        max = std::max(fabs(args[i]), max);
+    }
+    if (!max)
+        max = 1;
+    // Kahan summation algorithm significantly reduces the numerical error in the total obtained.
+    double sum = 0;
+    double compensation = 0;
+    for (double argument : args) {
+        double scaledArgument = argument / max;
+        double summand = scaledArgument * scaledArgument - compensation;
+        double preliminary = sum + summand;
+        compensation = (preliminary - sum) - summand;
+        sum = preliminary;
+    }
+    return JSValue::encode(jsDoubleNumber(sqrt(sum) * max));
+}
+
 EncodedJSValue JSC_HOST_CALL mathProtoFuncLog(ExecState* exec)
 {
     return JSValue::encode(jsDoubleNumber(log(exec->argument(0).toNumber(exec))));
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to