Refactor newly added Math.floorDiv, floorMod, multiplyExact methods.

Change-Id: Ie5cffa85ec296b7f44776149a0d2c0ab4a77fb33
diff --git a/user/super/com/google/gwt/emul/java/lang/Double.java b/user/super/com/google/gwt/emul/java/lang/Double.java
index 27f1534..2b4c11c 100644
--- a/user/super/com/google/gwt/emul/java/lang/Double.java
+++ b/user/super/com/google/gwt/emul/java/lang/Double.java
@@ -202,11 +202,11 @@
   }
 
   public static boolean isFinite(double x) {
-    return NEGATIVE_INFINITY < x && x < POSITIVE_INFINITY;
+    return JsUtils.isFinite(x);
   }
 
   public static boolean isInfinite(double x) {
-    return x == POSITIVE_INFINITY || x == NEGATIVE_INFINITY;
+    return !isNaN(x) && !isFinite(x);
   }
 
   public static boolean isNaN(double x) {
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 bd30a66..06b6f27 100644
--- a/user/super/com/google/gwt/emul/java/lang/Math.java
+++ b/user/super/com/google/gwt/emul/java/lang/Math.java
@@ -69,10 +69,9 @@
   }
 
   public static int addExact(int x, int y) {
-    int r = x + y;
-    // "Hacker's Delight" 2-12 Overflow if both arguments have the opposite sign of the result
-    throwOverflowIf(((x ^ r) & (y ^ r)) < 0);
-    return r;
+    double r = (double) x + (double) y;
+    throwOverflowIf(!isSafeIntegerRange(r));
+    return (int) r;
   }
 
   public static long addExact(long x, long y) {
@@ -142,30 +141,24 @@
 
   public static int floorDiv(int dividend, int divisor) {
     throwDivByZeroIf(divisor == 0);
-    int r = dividend / divisor;
-    // if the signs are different and modulo not zero, round down
-    if ((dividend ^ divisor) < 0 && (r * divisor != dividend)) {
-      r--;
-    }
-    return r;
+    // round down division if the signs are different and modulo not zero
+    return ((dividend ^ divisor) >= 0 ? dividend / divisor : ((dividend + 1) / divisor) - 1);
   }
 
   public static long floorDiv(long dividend, long divisor) {
     throwDivByZeroIf(divisor == 0);
-    long r = dividend / divisor;
-    // if the signs are different and modulo not zero, round down
-    if ((dividend ^ divisor) < 0 && (r * divisor != dividend)) {
-      r--;
-    }
-    return r;
+    // round down division if the signs are different and modulo not zero
+    return ((dividend ^ divisor) >= 0 ? dividend / divisor : ((dividend + 1) / divisor) - 1);
   }
 
   public static int floorMod(int dividend, int divisor) {
-    return dividend - floorDiv(dividend, divisor) * divisor;
+    throwDivByZeroIf(divisor == 0);
+    return ((dividend % divisor) + divisor) % divisor;
   }
 
   public static long floorMod(long dividend, long divisor) {
-    return dividend - floorDiv(dividend, divisor) * divisor;
+    throwDivByZeroIf(divisor == 0);
+    return ((dividend % divisor) + divisor) % divisor;
   }
 
   public static double hypot(double x, double y) {
@@ -227,15 +220,20 @@
   }
 
   public static int multiplyExact(int x, int y) {
-    long r = (long) x * (long) y;
-    int ir = (int) r;
-    throwOverflowIf(ir != r);
-    return ir;
+    double r = (double) x * (double) y;
+    throwOverflowIf(!isSafeIntegerRange(r));
+    return (int) r;
   }
 
   public static long multiplyExact(long x, long y) {
+    if (y == -1) {
+      return negateExact(x);
+    }
+    if (y == 0) {
+      return 0;
+    }
     long r = x * y;
-    throwOverflowIf((x == Long.MIN_VALUE && y == -1) || (y != 0 && (r / y != x)));
+    throwOverflowIf(r / y != x);
     return r;
   }
 
@@ -280,11 +278,9 @@
   }-*/;
 
   public static int subtractExact(int x, int y) {
-    int r = x - y;
-    // "Hacker's Delight" Overflow if the arguments have different signs and
-    // the sign of the result is different than the sign of x
-    throwOverflowIf(((x ^ y) & (x ^ r)) < 0);
-    return r;
+    double r = (double) x - (double) y;
+    throwOverflowIf(!isSafeIntegerRange(r));
+    return (int) r;
   }
 
   public static long subtractExact(long x, long y) {
@@ -362,6 +358,10 @@
     return x * PI_OVER_180;
   }
 
+  private static boolean isSafeIntegerRange(double value) {
+    return Integer.MIN_VALUE <= value && value <= Integer.MAX_VALUE;
+  }
+
   private static void throwDivByZeroIf(boolean condition) {
     if (condition) {
       throw new ArithmeticException("div by zero");
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
index b0ff418..09bd266 100644
--- a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
+++ b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
@@ -20,6 +20,10 @@
  */
 public class JsUtils {
 
+  public static native boolean isFinite(double d) /*-{
+    return isFinite(d);
+  }-*/;
+
   public static native boolean isNaN(double d) /*-{
     return isNaN(d);
   }-*/;
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 7259c1b..48c9a75 100644
--- a/user/test/com/google/gwt/emultest/java/lang/MathTest.java
+++ b/user/test/com/google/gwt/emultest/java/lang/MathTest.java
@@ -247,6 +247,10 @@
     assertEquals(-2, Math.floorDiv(4, -3));
     assertEquals(-2, Math.floorDiv(-4, 3));
     assertEquals(1, Math.floorDiv(-4, -3));
+    assertEquals(1, Math.floorDiv(Integer.MIN_VALUE, Integer.MIN_VALUE));
+    assertEquals(1, Math.floorDiv(Integer.MAX_VALUE, Integer.MAX_VALUE));
+    assertEquals(Integer.MIN_VALUE, Math.floorDiv(Integer.MIN_VALUE, 1));
+    assertEquals(Integer.MAX_VALUE, Math.floorDiv(Integer.MAX_VALUE, 1));
 
     // special case
     assertEquals(Integer.MIN_VALUE, Math.floorDiv(Integer.MIN_VALUE, -1));
@@ -264,6 +268,10 @@
     assertEquals(-2L, Math.floorDiv(4L, -3L));
     assertEquals(-2L, Math.floorDiv(-4L, 3L));
     assertEquals(1L, Math.floorDiv(-4L, -3L));
+    assertEquals(1L, Math.floorDiv(Long.MIN_VALUE, Long.MIN_VALUE));
+    assertEquals(1L, Math.floorDiv(Long.MAX_VALUE, Long.MAX_VALUE));
+    assertEquals(Long.MIN_VALUE, Math.floorDiv(Long.MIN_VALUE, 1L));
+    assertEquals(Long.MAX_VALUE, Math.floorDiv(Long.MAX_VALUE, 1L));
 
     // special case
     assertEquals(Long.MIN_VALUE, Math.floorDiv(Long.MIN_VALUE, -1));
@@ -281,6 +289,10 @@
     assertEquals(-2, Math.floorMod(4, -3));
     assertEquals(2, Math.floorMod(-4, 3));
     assertEquals(-1, Math.floorMod(-4, -3));
+    assertEquals(0, Math.floorMod(Integer.MIN_VALUE, Integer.MIN_VALUE));
+    assertEquals(0, Math.floorMod(Integer.MAX_VALUE, Integer.MAX_VALUE));
+    assertEquals(0, Math.floorMod(Integer.MIN_VALUE, 1));
+    assertEquals(0, Math.floorMod(Integer.MAX_VALUE, 1));
 
     try {
       Math.floorMod(1, 0);
@@ -295,6 +307,10 @@
     assertEquals(-2L, Math.floorMod(4L, -3L));
     assertEquals(2L, Math.floorMod(-4L, 3L));
     assertEquals(-1L, Math.floorMod(-4L, -3L));
+    assertEquals(0L, Math.floorMod(Long.MIN_VALUE, Long.MIN_VALUE));
+    assertEquals(0L, Math.floorMod(Long.MAX_VALUE, Long.MAX_VALUE));
+    assertEquals(0L, Math.floorMod(Long.MIN_VALUE, 1L));
+    assertEquals(0L, Math.floorMod(Long.MAX_VALUE, 1L));
 
     try {
       Math.floorMod(1L, 0L);