Commit a5f94a48 authored by whesse@chromium.org's avatar whesse@chromium.org

Fix Math.pow(-0, 0.5) and Math.pow(-0, -0.5). These are not equal to sqrt(-0)...

Fix Math.pow(-0, 0.5) and Math.pow(-0, -0.5).  These are not equal to sqrt(-0) and 1/sqrt(-0).  Add tests for these cases.  Fixes V8 issue 1088.
BUG=1088
TEST=test/mjsunit/math-pow.js

Review URL: http://codereview.chromium.org/6368050

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6573 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 81526353
......@@ -4698,12 +4698,15 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
runtime.entry_label(),
AVOID_NANS_AND_INFINITIES);
// Convert -0 into +0 by adding +0.
__ vmov(d2, 0.0);
__ vadd(d0, d2, d0);
// Load 1.0 into d2.
__ vmov(d2, 1.0);
// Calculate the reciprocal of the square root. 1/sqrt(x) = sqrt(1/x).
__ vdiv(d0, d2, d0);
// Calculate the reciprocal of the square root.
__ vsqrt(d0, d0);
__ vdiv(d0, d2, d0);
__ b(&allocate_return);
......@@ -4717,6 +4720,9 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
scratch1, scratch2, heap_number_map, s0,
runtime.entry_label(),
AVOID_NANS_AND_INFINITIES);
// Convert -0 into +0 by adding +0.
__ vmov(d2, 0.0);
__ vadd(d0, d2, d0);
__ vsqrt(d0, d0);
__ bind(&allocate_return);
......
......@@ -838,8 +838,8 @@ double power_double_double(double x, double y) {
return power_double_int(x, y_int); // Returns 1.0 for exponent 0.
}
if (!isinf(x)) {
if (y == 0.5) return sqrt(x);
if (y == -0.5) return 1.0 / sqrt(x);
if (y == 0.5) return sqrt(x + 0.0); // -0 must be converted to +0.
if (y == -0.5) return 1.0 / sqrt(x + 0.0);
}
if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
return OS::nan_value();
......
......@@ -3499,10 +3499,12 @@ void MathPowStub::Generate(MacroAssembler* masm) {
__ j(not_equal, &not_minus_half);
// Calculates reciprocal of square root.
// Note that 1/sqrt(x) = sqrt(1/x))
__ divsd(xmm3, xmm0);
__ movsd(xmm1, xmm3);
// sqrtsd returns -0 when input is -0. ECMA spec requires +0.
__ xorpd(xmm1, xmm1);
__ addsd(xmm1, xmm0);
__ sqrtsd(xmm1, xmm1);
__ divsd(xmm3, xmm1);
__ movsd(xmm1, xmm3);
__ jmp(&allocate_return);
// Test for 0.5.
......@@ -3514,7 +3516,9 @@ void MathPowStub::Generate(MacroAssembler* masm) {
__ ucomisd(xmm2, xmm1);
__ j(not_equal, &call_runtime);
// Calculates square root.
__ movsd(xmm1, xmm0);
// sqrtsd returns -0 when input is -0. ECMA spec requires +0.
__ xorpd(xmm1, xmm1);
__ addsd(xmm1, xmm0);
__ sqrtsd(xmm1, xmm1);
__ bind(&allocate_return);
......
......@@ -7951,10 +7951,12 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
__ j(not_equal, &not_minus_half);
// Calculates reciprocal of square root.
// Note that 1/sqrt(x) = sqrt(1/x))
__ divsd(xmm3, xmm0);
__ movsd(xmm1, xmm3);
// sqrtsd returns -0 when input is -0. ECMA spec requires +0.
__ xorpd(xmm1, xmm1);
__ addsd(xmm1, xmm0);
__ sqrtsd(xmm1, xmm1);
__ divsd(xmm3, xmm1);
__ movsd(xmm1, xmm3);
__ jmp(&allocate_return);
// Test for 0.5.
......@@ -7966,7 +7968,9 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
__ ucomisd(xmm2, xmm1);
call_runtime.Branch(not_equal);
// Calculates square root.
__ movsd(xmm1, xmm0);
// sqrtsd returns -0 when input is -0. ECMA spec requires +0.
__ xorpd(xmm1, xmm1);
__ addsd(xmm1, xmm0);
__ sqrtsd(xmm1, xmm1);
JumpTarget done;
......
......@@ -2397,6 +2397,8 @@ void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) {
__ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity));
__ ucomisd(xmm_scratch, input_reg);
DeoptimizeIf(equal, instr->environment());
__ xorpd(xmm_scratch, xmm_scratch);
__ addsd(input_reg, xmm_scratch); // Convert -0 to +0.
__ sqrtsd(input_reg, input_reg);
}
......
......@@ -6969,10 +6969,12 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
__ j(not_equal, &not_minus_half);
// Calculates reciprocal of square root.
// Note that 1/sqrt(x) = sqrt(1/x))
__ divsd(xmm3, xmm0);
__ movsd(xmm1, xmm3);
// sqrtsd returns -0 when input is -0. ECMA spec requires +0.
__ xorpd(xmm1, xmm1);
__ addsd(xmm1, xmm0);
__ sqrtsd(xmm1, xmm1);
__ divsd(xmm3, xmm1);
__ movsd(xmm1, xmm3);
__ jmp(&allocate_return);
// Test for 0.5.
......@@ -6985,7 +6987,9 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
call_runtime.Branch(not_equal);
// Calculates square root.
__ movsd(xmm1, xmm0);
// sqrtsd returns -0 when input is -0. ECMA spec requires +0.
__ xorpd(xmm1, xmm1);
__ addsd(xmm1, xmm0);
__ sqrtsd(xmm1, xmm1);
JumpTarget done;
......
......@@ -58,10 +58,11 @@ assertEquals(Infinity, Math.pow(-1.1, Infinity));
assertEquals(Infinity, Math.pow(2, Infinity));
assertEquals(Infinity, Math.pow(-2, Infinity));
assertEquals(+0, Math.pow(1.1, -Infinity));
assertEquals(+0, Math.pow(-1.1, -Infinity));
assertEquals(+0, Math.pow(2, -Infinity));
assertEquals(+0, Math.pow(-2, -Infinity));
// Because +0 == -0, we need to compare 1/{+,-}0 to {+,-}Infinity
assertEquals(+Infinity, 1/Math.pow(1.1, -Infinity));
assertEquals(+Infinity, 1/Math.pow(-1.1, -Infinity));
assertEquals(+Infinity, 1/Math.pow(2, -Infinity));
assertEquals(+Infinity, 1/Math.pow(-2, -Infinity));
assertEquals(NaN, Math.pow(1, Infinity));
assertEquals(NaN, Math.pow(1, -Infinity));
......@@ -81,8 +82,8 @@ assertEquals(Infinity, Math.pow(-0.999, -Infinity));
assertEquals(Infinity, Math.pow(Infinity, 0.1));
assertEquals(Infinity, Math.pow(Infinity, 2));
assertEquals(+0, Math.pow(Infinity, -0.1));
assertEquals(+0, Math.pow(Infinity, -2));
assertEquals(+Infinity, 1/Math.pow(Infinity, -0.1));
assertEquals(+Infinity, 1/Math.pow(Infinity, -2));
assertEquals(-Infinity, Math.pow(-Infinity, 3));
assertEquals(-Infinity, Math.pow(-Infinity, 13));
......@@ -90,23 +91,23 @@ assertEquals(-Infinity, Math.pow(-Infinity, 13));
assertEquals(Infinity, Math.pow(-Infinity, 3.1));
assertEquals(Infinity, Math.pow(-Infinity, 2));
assertEquals(-0, Math.pow(-Infinity, -3));
assertEquals(-0, Math.pow(-Infinity, -13));
assertEquals(-Infinity, 1/Math.pow(-Infinity, -3));
assertEquals(-Infinity, 1/Math.pow(-Infinity, -13));
assertEquals(+0, Math.pow(-Infinity, -3.1));
assertEquals(+0, Math.pow(-Infinity, -2));
assertEquals(+Infinity, 1/Math.pow(-Infinity, -3.1));
assertEquals(+Infinity, 1/Math.pow(-Infinity, -2));
assertEquals(+0, Math.pow(+0, 1.1));
assertEquals(+0, Math.pow(+0, 2));
assertEquals(+Infinity, 1/Math.pow(+0, 1.1));
assertEquals(+Infinity, 1/Math.pow(+0, 2));
assertEquals(Infinity, Math.pow(+0, -1.1));
assertEquals(Infinity, Math.pow(+0, -2));
assertEquals(-0, Math.pow(-0, 3));
assertEquals(-0, Math.pow(-0, 13));
assertEquals(-Infinity, 1/Math.pow(-0, 3));
assertEquals(-Infinity, 1/Math.pow(-0, 13));
assertEquals(+0, Math.pow(-0, 3.1));
assertEquals(+0, Math.pow(-0, 2));
assertEquals(+Infinity, 1/Math.pow(-0, 3.1));
assertEquals(+Infinity, 1/Math.pow(-0, 2));
assertEquals(-Infinity, Math.pow(-0, -3));
assertEquals(-Infinity, Math.pow(-0, -13));
......@@ -123,6 +124,18 @@ assertEquals(NaN, Math.pow(-2, -1.1));
assertEquals(NaN, Math.pow(-1000, 1.1));
assertEquals(NaN, Math.pow(-1000, -1.1));
assertEquals(+Infinity, 1/Math.pow(-0, 0.5));
assertEquals(+Infinity, 1/Math.pow(-0, 0.6));
assertEquals(-Infinity, 1/Math.pow(-0, 1));
assertEquals(-Infinity, 1/Math.pow(-0, 10000000001));
assertEquals(+Infinity, Math.pow(-0, -0.5));
assertEquals(+Infinity, Math.pow(-0, -0.6));
assertEquals(-Infinity, Math.pow(-0, -1));
assertEquals(-Infinity, Math.pow(-0, -10000000001));
// Tests from Sputnik S8.5_A13_T1.
assertTrue((1*((Math.pow(2,53))-1)*(Math.pow(2,-1074))) === 4.4501477170144023e-308);
assertTrue((1*(Math.pow(2,52))*(Math.pow(2,-1074))) === 2.2250738585072014e-308);
......
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