Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions src/java.base/share/classes/java/lang/Math.java
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,9 @@ public static long multiplyExact(long x, long y) {
* <p>
* If {@code y} is zero, an {@code ArithmeticException} is thrown
* (JLS {@jls 15.17.2}).
* <p>
* The built-in remainder operator "{@code %}" is a suitable counterpart
* both for this method and for the built-in division operator "{@code /}".
*
* @param x the dividend
* @param y the divisor
Expand Down Expand Up @@ -1039,6 +1042,9 @@ public static int divideExact(int x, int y) {
* <p>
* If {@code y} is zero, an {@code ArithmeticException} is thrown
* (JLS {@jls 15.17.2}).
* <p>
* The built-in remainder operator "{@code %}" is a suitable counterpart
* both for this method and for the built-in division operator "{@code /}".
*
* @param x the dividend
* @param y the divisor
Expand All @@ -1056,6 +1062,80 @@ public static long divideExact(long x, long y) {
throw new ArithmeticException("long overflow");
}

/**
* Returns the largest (closest to positive infinity)
* {@code int} value that is less than or equal to the algebraic quotient.
* This method is identical to {@link #floorDiv(int,int)} except that it
* throws an {@code ArithmeticException} when the dividend is
* {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is
* {@code -1} instead of ignoring the integer overflow and returning
* {@code Integer.MIN_VALUE}.
* <p>
* The floor modulus method {@link #floorMod(int,int)} is a suitable
* counterpart both for this method and for the {@link #floorDiv(int,int)}
* method.
* <p>
* For examples, see {@link #floorDiv(int, int)}.
*
* @param x the dividend
* @param y the divisor
* @return the largest (closest to positive infinity)
* {@code int} value that is less than or equal to the algebraic quotient.
* @throws ArithmeticException if the divisor {@code y} is zero, or the
* dividend {@code x} is {@code Integer.MIN_VALUE} and the divisor {@code y}
* is {@code -1}.
* @see #floorDiv(int, int)
* @since 18
*/
public static int floorDivExact(int x, int y) {
int r = x / y;
if ((x & y & r) >= 0) {
// if the signs are different and modulo not zero, round down
if ((x ^ y) < 0 && (r * y != x)) {
r--;
}
return r;
}
throw new ArithmeticException("integer overflow");
}

/**
* Returns the largest (closest to positive infinity)
* {@code long} value that is less than or equal to the algebraic quotient.
* This method is identical to {@link #floorDiv(long,long)} except that it
* throws an {@code ArithmeticException} when the dividend is
* {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is
* {@code -1} instead of ignoring the integer overflow and returning
* {@code Long.MIN_VALUE}.
* <p>
* The floor modulus method {@link #floorMod(long,long)} is a suitable
* counterpart both for this method and for the {@link #floorDiv(long,long)}
* method.
* <p>
* For examples, see {@link #floorDiv(int, int)}.
*
* @param x the dividend
* @param y the divisor
* @return the largest (closest to positive infinity)
* {@code long} value that is less than or equal to the algebraic quotient.
* @throws ArithmeticException if the divisor {@code y} is zero, or the
* dividend {@code x} is {@code Long.MIN_VALUE} and the divisor {@code y}
* is {@code -1}.
* @see #floorDiv(long,long)
* @since 18
*/
public static long floorDivExact(long x, long y) {
long r = x / y;
if ((x & y & r) >= 0) {
// if the signs are different and modulo not zero, round down
if ((x ^ y) < 0 && (r * y != x)) {
r--;
}
return r;
}
throw new ArithmeticException("long overflow");
}

/**
* Returns the argument incremented by one, throwing an exception if the
* result overflows an {@code int}.
Expand Down
66 changes: 66 additions & 0 deletions src/java.base/share/classes/java/lang/StrictMath.java
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,9 @@ public static long multiplyExact(long x, long y) {
* <p>
* If {@code y} is zero, an {@code ArithmeticException} is thrown
* (JLS {@jls 15.17.2}).
* <p>
* The built-in remainder operator "{@code %}" is a suitable counterpart
* both for this method and for the built-in division operator "{@code /}".
*
* @param x the dividend
* @param y the divisor
Expand All @@ -887,6 +890,9 @@ public static int divideExact(int x, int y) {
* <p>
* If {@code y} is zero, an {@code ArithmeticException} is thrown
* (JLS {@jls 15.17.2}).
* <p>
* The built-in remainder operator "{@code %}" is a suitable counterpart
* both for this method and for the built-in division operator "{@code /}".
*
* @param x the dividend
* @param y the divisor
Expand All @@ -901,6 +907,66 @@ public static long divideExact(long x, long y) {
return Math.divideExact(x, y);
}

/**
* Returns the largest (closest to positive infinity)
* {@code int} value that is less than or equal to the algebraic quotient.
* This method is identical to {@link #floorDiv(int,int)} except that it
* throws an {@code ArithmeticException} when the dividend is
* {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is
* {@code -1} instead of ignoring the integer overflow and returning
* {@code Integer.MIN_VALUE}.
* <p>
* The floor modulus method {@link #floorMod(int,int)} is a suitable
* counterpart both for this method and for the {@link #floorDiv(int,int)}
* method.
* <p>
* See {@link Math#floorDiv(int, int) Math.floorDiv} for examples and
* a comparison to the integer division {@code /} operator.
*
* @param x the dividend
* @param y the divisor
* @return the largest (closest to positive infinity)
* {@code int} value that is less than or equal to the algebraic quotient.
* @throws ArithmeticException if the divisor {@code y} is zero, or the
* dividend {@code x} is {@code Integer.MIN_VALUE} and the divisor {@code y}
* is {@code -1}.
* @see Math#floorDiv(int, int)
* @since 18
*/
public static int floorDivExact(int x, int y) {
return Math.floorDivExact(x, y);
}

/**
* Returns the largest (closest to positive infinity)
* {@code long} value that is less than or equal to the algebraic quotient.
* This method is identical to {@link #floorDiv(long,long)} except that it
* throws an {@code ArithmeticException} when the dividend is
* {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is
* {@code -1} instead of ignoring the integer overflow and returning
* {@code Long.MIN_VALUE}.
* <p>
* The floor modulus method {@link #floorMod(long,long)} is a suitable
* counterpart both for this method and for the {@link #floorDiv(long,long)}
* method.
* <p>
* For examples, see {@link Math#floorDiv(int, int) Math.floorDiv}.
*
* @param x the dividend
* @param y the divisor
* @return the largest (closest to positive infinity)
* {@code long} value that is less than or equal to the algebraic quotient.
* @throws ArithmeticException if the divisor {@code y} is zero, or the
* dividend {@code x} is {@code Long.MIN_VALUE} and the divisor {@code y}
* is {@code -1}.
* @see Math#floorDiv(int, int)
* @see Math#floorDiv(long,long)
* @since 18
*/
public static long floorDivExact(long x, long y) {
return Math.floorDivExact(x, y);
}

/**
* Returns the argument incremented by one,
* throwing an exception if the result overflows an {@code int}.
Expand Down
62 changes: 59 additions & 3 deletions test/jdk/java/lang/Math/ExactArithTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static void fail(String message) {

/**
* Test Math.addExact, multiplyExact, divideExact, subtractExact,
* incrementExact, decrementExact, negateExact methods with
* floorDivExact, incrementExact, decrementExact, negateExact methods with
* {@code int} arguments.
*/
static void testIntegerExact() {
Expand Down Expand Up @@ -166,6 +166,34 @@ static void testIntegerExact(int x, int y) {
}
}

exceptionExpected = false;
try {
// Test floorDivExact
int q = 0;
try {
q = Math.floorDiv(x, y);
} catch (ArithmeticException e) {
exceptionExpected = true;
}
if (!exceptionExpected && x == Integer.MIN_VALUE && y == -1) {
exceptionExpected = true;
}
int z = Math.floorDivExact(x, y);
if (exceptionExpected) {
fail("FAIL: int Math.floorDivExact(" + x + " / " + y + ")" +
"; expected ArithmeticException not thrown");
}
if (z != q) {
fail("FAIL: int Math.floorDivExact(" + x + " / " + y + ") = " +
z + "; expected: " + q);
}
} catch (ArithmeticException ex) {
if (!exceptionExpected) {
fail("FAIL: int Math.floorDivExact(" + x + " / " + y + ")" +
"; Unexpected exception: " + ex);
}
}

try {
// Test incrementExact
int inc = Math.incrementExact(x);
Expand Down Expand Up @@ -217,8 +245,8 @@ static void testIntegerExact(int x, int y) {

/**
* Test Math.addExact, multiplyExact, divideExact, subtractExact,
* incrementExact, decrementExact, negateExact, toIntExact methods
* with {@code long} arguments.
* floorDivExact, incrementExact, decrementExact, negateExact, toIntExact
* methods with {@code long} arguments.
*/
static void testLongExact() {
testLongExactTwice(0, 0);
Expand Down Expand Up @@ -324,6 +352,34 @@ static void testLongExact(long x, long y) {
}
}

boolean exceptionExpected = false;
try {
// Test floorDivExact
long q = 0;
try {
q = Math.floorDiv(x, y);
} catch (ArithmeticException e) {
exceptionExpected = true;
}
if (!exceptionExpected && x == Long.MIN_VALUE && y == -1) {
exceptionExpected = true;
}
long z = Math.floorDivExact(x, y);
if (exceptionExpected) {
fail("FAIL: long Math.floorDivExact(" + x + " / " + y + ")" +
"; expected ArithmeticException not thrown");
}
if (z != q) {
fail("FAIL: long Math.floorDivExact(" + x + " / " + y + ") = " +
z + "; expected: " + q);
}
} catch (ArithmeticException ex) {
if (!exceptionExpected) {
fail("FAIL: long Math.floorDivExact(" + x + " / " + y + ")" +
"; Unexpected exception: " + ex);
}
}

try {
// Test incrementExact
resultBig = xBig.add(BigInteger.ONE);
Expand Down