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);