Fix Math.expm1 implementation Bug: #9331 Change-Id: I65639c4462155a07333d35d91f2e69f66c62489a Bug-Link: https://github.com/gwtproject/gwt/issues/9331
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 15bc14c..7d307e5 100644 --- a/user/super/com/google/gwt/emul/java/lang/Math.java +++ b/user/super/com/google/gwt/emul/java/lang/Math.java
@@ -136,16 +136,7 @@ } public static double expm1(double d) { - if (d == 0.0 || Double.isNaN(d)) { - return d; // "a zero with same sign as argument", arg is zero, so... - } else if (!Double.isInfinite(d)) { - if (d < 0.0d) { - return -1.0d; - } else { - return Double.POSITIVE_INFINITY; - } - } - return exp(d) + 1.0d; + return d == 0 ? d : exp(d) - 1; } public static double floor(double x) {
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 ed3ac23..7259c1b 100644 --- a/user/test/com/google/gwt/emultest/java/lang/MathTest.java +++ b/user/test/com/google/gwt/emultest/java/lang/MathTest.java
@@ -42,6 +42,14 @@ assertFalse(isNegativeZero(x)); } + private static void assertNaN(double x) { + assertTrue(Double.isNaN(x)); + } + + private static void assertEquals(double expected, double actual) { + assertEquals(expected, actual, 0.); + } + private static boolean isNegativeZero(double x) { return Double.doubleToLongBits(-0.0) == Double.doubleToLongBits(x); } @@ -71,7 +79,7 @@ v = Math.abs(Double.POSITIVE_INFINITY); assertEquals(Double.POSITIVE_INFINITY, v); v = Math.abs(Double.NaN); - assertTrue(Double.isNaN(v)); + assertNaN(v); } public void testAddExact() { @@ -156,11 +164,11 @@ v = Math.cos(Math.PI * 1.5); assertEquals(0.0, v, 1e-7); v = Math.cos(Double.NaN); - assertTrue(Double.isNaN(v)); + assertNaN(v); v = Math.cos(Double.NEGATIVE_INFINITY); - assertTrue(Double.isNaN(v)); + assertNaN(v); v = Math.cos(Double.POSITIVE_INFINITY); - assertTrue(Double.isNaN(v)); + assertNaN(v); } public void testCosh() { @@ -171,7 +179,7 @@ v = Math.cosh(-1.0); assertEquals(1.5430806348, v, 1e-7); v = Math.cosh(Double.NaN); - assertTrue(Double.isNaN(v)); + assertNaN(v); v = Math.cosh(Double.NEGATIVE_INFINITY); assertEquals(Double.POSITIVE_INFINITY, v); v = Math.cosh(Double.POSITIVE_INFINITY); @@ -204,6 +212,16 @@ } } + public void testExpm1() { + assertNegativeZero(Math.expm1(-0.)); + assertPositiveZero(Math.expm1(0.)); + assertNaN(Math.expm1(Double.NaN)); + assertEquals(Double.POSITIVE_INFINITY, Math.expm1(Double.POSITIVE_INFINITY)); + assertEquals(-1., Math.expm1(Double.NEGATIVE_INFINITY)); + assertEquals(-0.632, Math.expm1(-1), 0.001); + assertEquals(1.718, Math.expm1(1), 0.001); + } + public void testFloor() { double v = Math.floor(0.5); assertEquals(0, v, 0); @@ -320,12 +338,12 @@ assertEquals(1d, Math.max(1d, -1d)); assertEquals(-1d, Math.max(-1d, -2d)); assertEquals(-1d, Math.max(-2d, -1d)); - assertTrue(Double.isNaN(Math.max(Double.NaN, 1d))); - assertTrue(Double.isNaN(Math.max(1d, Double.NaN))); - assertTrue(Double.isNaN(Math.max(Double.NaN, Double.POSITIVE_INFINITY))); - assertTrue(Double.isNaN(Math.max(Double.POSITIVE_INFINITY, Double.NaN))); - assertTrue(Double.isNaN(Math.max(Double.NaN, Double.NEGATIVE_INFINITY))); - assertTrue(Double.isNaN(Math.max(Double.NEGATIVE_INFINITY, Double.NaN))); + assertNaN(Math.max(Double.NaN, 1d)); + assertNaN(Math.max(1d, Double.NaN)); + assertNaN(Math.max(Double.NaN, Double.POSITIVE_INFINITY)); + assertNaN(Math.max(Double.POSITIVE_INFINITY, Double.NaN)); + assertNaN(Math.max(Double.NaN, Double.NEGATIVE_INFINITY)); + assertNaN(Math.max(Double.NEGATIVE_INFINITY, Double.NaN)); assertEquals(2f, Math.max(1f, 2f)); assertEquals(2f, Math.max(2f, 1f)); @@ -352,12 +370,12 @@ assertEquals(-1d, Math.min(1d, -1d)); assertEquals(-2d, Math.min(-1d, -2d)); assertEquals(-2d, Math.min(-2d, -1d)); - assertTrue(Double.isNaN(Math.min(Double.NaN, 1d))); - assertTrue(Double.isNaN(Math.min(1d, Double.NaN))); - assertTrue(Double.isNaN(Math.min(Double.NaN, Double.POSITIVE_INFINITY))); - assertTrue(Double.isNaN(Math.min(Double.POSITIVE_INFINITY, Double.NaN))); - assertTrue(Double.isNaN(Math.min(Double.NaN, Double.NEGATIVE_INFINITY))); - assertTrue(Double.isNaN(Math.min(Double.NEGATIVE_INFINITY, Double.NaN))); + assertNaN(Math.min(Double.NaN, 1d)); + assertNaN(Math.min(1d, Double.NaN)); + assertNaN(Math.min(Double.NaN, Double.POSITIVE_INFINITY)); + assertNaN(Math.min(Double.POSITIVE_INFINITY, Double.NaN)); + assertNaN(Math.min(Double.NaN, Double.NEGATIVE_INFINITY)); + assertNaN(Math.min(Double.NEGATIVE_INFINITY, Double.NaN)); assertEquals(1f, Math.min(1f, 2f)); assertEquals(1f, Math.min(2f, 1f)); @@ -519,7 +537,7 @@ } public void testSignum() { - assertTrue(Double.isNaN(Math.signum(Double.NaN))); + assertNaN(Math.signum(Double.NaN)); assertTrue(isNegativeZero(Math.signum(-0.))); assertEquals(0., Math.signum(0.), 0); assertEquals(-1, Math.signum(-2), 0); @@ -542,11 +560,11 @@ v = Math.sin(Math.PI * 1.5); assertEquals(-1.0, v, 1e-7); v = Math.sin(Double.NaN); - assertTrue(Double.isNaN(v)); + assertNaN(v); v = Math.sin(Double.NEGATIVE_INFINITY); - assertTrue(Double.isNaN(v)); + assertNaN(v); v = Math.sin(Double.POSITIVE_INFINITY); - assertTrue(Double.isNaN(v)); + assertNaN(v); } public void testSinh() { @@ -557,7 +575,7 @@ v = Math.sinh(-1.0); assertEquals(-1.175201193, v, 1e-7); v = Math.sinh(Double.NaN); - assertTrue(Double.isNaN(v)); + assertNaN(v); v = Math.sinh(Double.NEGATIVE_INFINITY); assertEquals(Double.NEGATIVE_INFINITY, v); v = Math.sinh(Double.POSITIVE_INFINITY); @@ -572,11 +590,11 @@ v = Math.tan(-0.0); assertEquals(-0.0, v, 1e-7); v = Math.tan(Double.NaN); - assertTrue(Double.isNaN(v)); + assertNaN(v); v = Math.tan(Double.NEGATIVE_INFINITY); - assertTrue(Double.isNaN(v)); + assertNaN(v); v = Math.tan(Double.POSITIVE_INFINITY); - assertTrue(Double.isNaN(v)); + assertNaN(v); } public void testTanh() { @@ -587,7 +605,7 @@ v = Math.tanh(-1.0); assertEquals(-0.761594155, v, 1e-7); v = Math.tanh(Double.NaN); - assertTrue(Double.isNaN(v)); + assertNaN(v); v = Math.tanh(Double.NEGATIVE_INFINITY); assertEquals(-1.0, v, 1e-7); v = Math.tanh(Double.POSITIVE_INFINITY);