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