Skip to content

Commit

Permalink
Refactor newly added Math.floorDiv, floorMod, multiplyExact methods.
Browse files Browse the repository at this point in the history
Change-Id: Ie5cffa85ec296b7f44776149a0d2c0ab4a77fb33
  • Loading branch information
korzha committed May 25, 2016
1 parent 0ba67f4 commit 93c726a
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 30 deletions.
4 changes: 2 additions & 2 deletions user/super/com/google/gwt/emul/java/lang/Double.java
Expand Up @@ -202,11 +202,11 @@ public static int hashCode(double d) {
}

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) {
Expand Down
56 changes: 28 additions & 28 deletions user/super/com/google/gwt/emul/java/lang/Math.java
Expand Up @@ -69,10 +69,9 @@ public static double asin(double x) {
}

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) {
Expand Down Expand Up @@ -142,30 +141,24 @@ public static double floor(double x) {

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) {
Expand Down Expand Up @@ -227,15 +220,20 @@ public static long min(long x, long y) {
}

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

Expand Down Expand Up @@ -280,11 +278,9 @@ private static native int unsafeCastToInt(double d) /*-{
}-*/;

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) {
Expand Down Expand Up @@ -362,6 +358,10 @@ public static double toRadians(double x) {
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");
Expand Down
4 changes: 4 additions & 0 deletions user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
Expand Up @@ -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);
}-*/;
Expand Down
16 changes: 16 additions & 0 deletions user/test/com/google/gwt/emultest/java/lang/MathTest.java
Expand Up @@ -247,6 +247,10 @@ public void testFloorDiv() {
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));
Expand All @@ -264,6 +268,10 @@ public void testFloorDivLongs() {
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));
Expand All @@ -281,6 +289,10 @@ public void testFloorMod() {
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);
Expand All @@ -295,6 +307,10 @@ public void testFloorModLongs() {
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);
Expand Down

0 comments on commit 93c726a

Please sign in to comment.