Fix handling of -0 in Math.copySign Change-Id: I3cbae4d357763a96400c0e3ada7646b151728ba9
diff --git a/user/super/com/google/gwt/emul/java/lang/Math.java b/user/super/com/google/gwt/emul/java/lang/Math.java index 82463fa..15bc14c 100644 --- a/user/super/com/google/gwt/emul/java/lang/Math.java +++ b/user/super/com/google/gwt/emul/java/lang/Math.java
@@ -102,11 +102,11 @@ } public static double copySign(double magnitude, double sign) { - if (sign < 0) { - return (magnitude < 0) ? magnitude : -magnitude; - } else { - return (magnitude > 0) ? magnitude : -magnitude; - } + return isNegative(sign) ? -Math.abs(magnitude) : Math.abs(magnitude); + } + + private static boolean isNegative(double d) { + return d < 0 || 1 / d < 0; } public static float copySign(float magnitude, float sign) {
diff --git a/user/test/com/google/gwt/emultest/java/lang/MathTest.java b/user/test/com/google/gwt/emultest/java/lang/MathTest.java index c47d4ff..ed3ac23 100644 --- a/user/test/com/google/gwt/emultest/java/lang/MathTest.java +++ b/user/test/com/google/gwt/emultest/java/lang/MathTest.java
@@ -33,6 +33,15 @@ private static final Integer[] ALL_INTEGER_CANDIDATES = getAllIntegerCandidates(); private static final Long[] ALL_LONG_CANDIDATES = getAllLongCandidates(); + private static void assertNegativeZero(double x) { + assertTrue(isNegativeZero(x)); + } + + private static void assertPositiveZero(double x) { + assertEquals(0.0, x); + assertFalse(isNegativeZero(x)); + } + private static boolean isNegativeZero(double x) { return Double.doubleToLongBits(-0.0) == Double.doubleToLongBits(x); } @@ -54,10 +63,9 @@ v = Math.abs(1.0); assertEquals(1.0, v); v = Math.abs(negativeZero); - assertEquals(0.0, v); - assertFalse(isNegativeZero(v)); + assertPositiveZero(v); v = Math.abs(0.0); - assertEquals(0.0, v); + assertPositiveZero(v); v = Math.abs(Double.NEGATIVE_INFINITY); assertEquals(Double.POSITIVE_INFINITY, v); v = Math.abs(Double.POSITIVE_INFINITY); @@ -101,6 +109,41 @@ assertEquals(10.0, v, 1e-7); } + public void testCopySign() { + double negativeZero = makeNegativeZero(); + + assertEquals(3.0, Math.copySign(3.0, 2.0)); + assertEquals(3.0, Math.copySign(-3.0, 2.0)); + assertEquals(-3.0, Math.copySign(3.0, -2.0)); + assertEquals(-3.0, Math.copySign(-3.0, -2.0)); + + assertEquals(2.0, Math.copySign(2.0, 0.0)); + assertEquals(2.0, Math.copySign(-2.0, 0.0)); + assertEquals(-2.0, Math.copySign(2.0, negativeZero)); + assertEquals(-2.0, Math.copySign(-2.0, negativeZero)); + assertEquals(-2.0, Math.copySign(-2.0, Double.NEGATIVE_INFINITY)); + assertEquals(2.0, Math.copySign(-2.0, Double.POSITIVE_INFINITY)); + assertEquals(2.0, Math.copySign(-2.0, Double.NaN)); + + assertPositiveZero(Math.copySign(0.0, 4.0)); + assertPositiveZero(Math.copySign(negativeZero, 4.0)); + assertNegativeZero(Math.copySign(0.0, -4.0)); + assertNegativeZero(Math.copySign(negativeZero, -4.0)); + + assertPositiveZero(Math.copySign(0.0, 0.0)); + assertPositiveZero(Math.copySign(negativeZero, 0.0)); + assertNegativeZero(Math.copySign(0.0, negativeZero)); + assertNegativeZero(Math.copySign(negativeZero, negativeZero)); + + assertEquals(Double.POSITIVE_INFINITY, Math.copySign(Double.POSITIVE_INFINITY, 1)); + assertEquals(Double.NEGATIVE_INFINITY, Math.copySign(Double.POSITIVE_INFINITY, -1)); + assertEquals(Double.POSITIVE_INFINITY, Math.copySign(Double.NEGATIVE_INFINITY, 1)); + assertEquals(Double.NEGATIVE_INFINITY, Math.copySign(Double.NEGATIVE_INFINITY, -1)); + + assertEquals(Double.NaN, Math.copySign(Double.NaN, 1), 0); + assertEquals(Double.NaN, Math.copySign(Double.NaN, -1), 0); + } + public void testCos() { double v = Math.cos(0.0); assertEquals(1.0, v, 1e-7);