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