Fixes Math.rint.

Also fixes the NaN handling in Assert.java that I discovered
during testing.

Authors: Goktug Gokdogan, Andrei Korzhevskii
Bug: #9156
Bug-Link: https://github.com/gwtproject/gwt/issues/9156
Change-Id: I2effe1c5ace329b2f708c53a1f83a295da4f5709
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 f996964..cb01dc1 100644
--- a/user/super/com/google/gwt/emul/java/lang/Math.java
+++ b/user/super/com/google/gwt/emul/java/lang/Math.java
@@ -269,15 +269,12 @@
     return NativeMath.random();
   }
 
-  public static double rint(double d) {
-    if (Double.isNaN(d)) {
-      return d;
-    } else if (Double.isInfinite(d)) {
-      return d;
-    } else if (d == 0.0d) {
-      return d;
+  public static double rint(double x) {
+    double mod2 = x % 2;
+    if ((mod2 == -1.5) || (mod2 == 0.5)) {
+      return NativeMath.floor(x);
     } else {
-      return round(d);
+      return NativeMath.round(x);
     }
   }
 
diff --git a/user/super/com/google/gwt/junit/translatable/junit/framework/Assert.java b/user/super/com/google/gwt/junit/translatable/junit/framework/Assert.java
index 94957ca..1d56fa3 100644
--- a/user/super/com/google/gwt/junit/translatable/junit/framework/Assert.java
+++ b/user/super/com/google/gwt/junit/translatable/junit/framework/Assert.java
@@ -84,7 +84,8 @@
   @DoNotInline
   public static void assertEquals(String str, double obj1, double obj2,
       double delta) {
-    if (obj1 == obj2) {
+    // Handles special cases like NaN
+    if (Double.compare(obj1, obj2) == 0) {
       return;
     } else if (Math.abs(obj1 - obj2) <= delta) {
       return;
@@ -96,7 +97,8 @@
   @DoNotInline
   public static void assertEquals(String str, float obj1, float obj2,
       float delta) {
-    if (obj1 == obj2) {
+        // Handles special cases like NaN
+    if (Float.compare(obj1, obj2) == 0) {
       return;
     } else if (Math.abs(obj1 - obj2) <= delta) {
       return;
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 9b8bb5d..7f63a27 100644
--- a/user/test/com/google/gwt/emultest/java/lang/MathTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/MathTest.java
@@ -16,6 +16,8 @@
 
 package com.google.gwt.emultest.java.lang;
 
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
 import com.google.gwt.junit.client.GWTTestCase;
 
 import java.math.BigInteger;
@@ -159,6 +161,25 @@
     }
   }
 
+  public void testFloor() {
+    double v = Math.floor(0.5);
+    assertEquals(0, v, 0);
+    v = Math.floor(Double.POSITIVE_INFINITY);
+    assertEquals(Double.POSITIVE_INFINITY, v, 0);
+    v = Math.floor(Double.NEGATIVE_INFINITY);
+    assertEquals(Double.NEGATIVE_INFINITY, v, 0);
+    v = Math.floor(Double.NaN);
+    assertEquals(Double.NaN, v, 0);
+  }
+
+  @DoNotRunWith(Platform.HtmlUnitBug)
+  public void testFloor_DoubleMaxValue() {
+    double v = Math.floor(Double.MAX_VALUE);
+    assertEquals(Double.MAX_VALUE, v, 0);
+    v = Math.floor(-Double.MAX_VALUE);
+    assertEquals(-Double.MAX_VALUE, v, 0);
+  }
+
   public void testFloorDiv() {
     assertEquals(0, Math.floorDiv(0, 1));
     assertEquals(1, Math.floorDiv(4, 3));
@@ -377,6 +398,83 @@
     }
   }
 
+  public void testRound() {
+    long v = Math.round(0.5);
+    assertEquals(1L, v);
+    v = Math.round(Double.POSITIVE_INFINITY);
+    assertEquals(Long.MAX_VALUE, v, 0);
+    v = Math.round(Double.NEGATIVE_INFINITY);
+    assertEquals(Long.MIN_VALUE, v, 0);
+    v = Math.round(Double.NaN);
+    assertEquals(0, v, 0);
+  }
+
+  @DoNotRunWith(Platform.HtmlUnitBug)
+  public void testRound_DoubleMaxValue() {
+    long v = Math.round(Double.MAX_VALUE);
+    assertEquals(Double.MAX_VALUE, v, 0);
+    v = Math.round(-Double.MAX_VALUE);
+    assertEquals(-Double.MAX_VALUE, v, 0);
+  }
+
+  public void testRint() {
+    final double twoTo52 = 1L << 52;
+    // format: value to be round and expected value
+    final double[] testValues = {
+        0, 0,
+        0.5, 0,
+        0.75, 1,
+        1.5, 2,
+        1.75, 2,
+        -0, -0,
+        -0.5, -0,
+        -1.25, -1,
+        -1.5, -2,
+        -2.5, -2,
+        twoTo52, twoTo52,
+        twoTo52 - 0.25, twoTo52,
+        twoTo52 + 0.25, twoTo52,
+        twoTo52 + 0.5, twoTo52,
+        twoTo52 - 0.5, twoTo52,
+        twoTo52 + 0.75, twoTo52 + 1,
+        twoTo52 - 0.75, twoTo52 - 1,
+        -twoTo52, -twoTo52,
+        -twoTo52 + 0.25, -twoTo52,
+        -twoTo52 - 0.25, -twoTo52,
+        -twoTo52 + 0.5, -twoTo52,
+        -twoTo52 - 0.5, -twoTo52,
+        -twoTo52 + 0.75, -twoTo52 + 1,
+        -twoTo52 - 0.75, -twoTo52 - 1,
+        Double.MIN_VALUE, 0,
+        Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY,
+        Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY,
+        Double.NaN, Double.NaN,
+    };
+    for (int i = 0; i < testValues.length;) {
+      double v = testValues[i++];
+      double expected = testValues[i++];
+      double actual = Math.rint(v);
+      assertEquals("value: " + v + ", expected: " + expected + ", actual: " + actual,
+          expected, actual, 0);
+    }
+  }
+
+  @DoNotRunWith(Platform.HtmlUnitBug)
+  public void testRint_DoubleMaxValue() {
+    // format: value to be round and expected value
+    final double[] testValues = {
+        Double.MAX_VALUE, Double.MAX_VALUE,
+        -Double.MAX_VALUE, -Double.MAX_VALUE,
+    };
+    for (int i = 0; i < testValues.length;) {
+      double v = testValues[i++];
+      double expected = testValues[i++];
+      double actual = Math.rint(v);
+      assertEquals("value: " + v + ", expected: " + expected + ", actual: " + actual,
+          expected, actual, 0);
+    }
+  }
+
   public void testSin() {
     double v = Math.sin(0.0);
     assertEquals(0.0, v, 1e-7);