diff --git a/jdk/src/share/classes/java/lang/Math.java b/jdk/src/share/classes/java/lang/Math.java index b8cef07b131..23bc934688d 100644 --- a/jdk/src/share/classes/java/lang/Math.java +++ b/jdk/src/share/classes/java/lang/Math.java @@ -825,7 +825,7 @@ public final class Math { public static int multiplyExact(int x, int y) { long r = (long)x * (long)y; if ((int)r != r) { - throw new ArithmeticException("long overflow"); + throw new ArithmeticException("integer overflow"); } return (int)r; } @@ -856,6 +856,108 @@ public final class Math { return r; } + /** + * Returns the argument incremented by one, throwing an exception if the + * result overflows an {@code int}. + * + * @param a the value to increment + * @return the result + * @throws ArithmeticException if the result overflows an int + * @since 1.8 + */ + public static int incrementExact(int a) { + if (a == Integer.MAX_VALUE) { + throw new ArithmeticException("integer overflow"); + } + + return a + 1; + } + + /** + * Returns the argument incremented by one, throwing an exception if the + * result overflows a {@code long}. + * + * @param a the value to increment + * @return the result + * @throws ArithmeticException if the result overflows a long + * @since 1.8 + */ + public static long incrementExact(long a) { + if (a == Long.MAX_VALUE) { + throw new ArithmeticException("long overflow"); + } + + return a + 1L; + } + + /** + * Returns the argument decremented by one, throwing an exception if the + * result overflows an {@code int}. + * + * @param a the value to decrement + * @return the result + * @throws ArithmeticException if the result overflows an int + * @since 1.8 + */ + public static int decrementExact(int a) { + if (a == Integer.MIN_VALUE) { + throw new ArithmeticException("integer overflow"); + } + + return a - 1; + } + + /** + * Returns the argument decremented by one, throwing an exception if the + * result overflows a {@code long}. + * + * @param a the value to decrement + * @return the result + * @throws ArithmeticException if the result overflows a long + * @since 1.8 + */ + public static long decrementExact(long a) { + if (a == Long.MIN_VALUE) { + throw new ArithmeticException("long overflow"); + } + + return a - 1L; + } + + /** + * Returns the negation of the argument, throwing an exception if the + * result overflows an {@code int}. + * + * @param a the value to negate + * @return the result + * @throws ArithmeticException if the result overflows an int + * @since 1.8 + */ + public static int negateExact(int a) { + if (a == Integer.MIN_VALUE) { + throw new ArithmeticException("integer overflow"); + } + + return -a; + } + + /** + * Returns the negation of the argument, throwing an exception if the + * result overflows a {@code long}. + * + * @param a the value to negate + * @return the result + * @throws ArithmeticException if the result overflows a long + * @since 1.8 + */ + public static long negateExact(long a) { + if (a == Long.MIN_VALUE) { + throw new ArithmeticException("long overflow"); + } + + return -a; + } + /** * Returns the value of the {@code long} argument; * throwing an exception if the value overflows an {@code int}. diff --git a/jdk/test/java/lang/Math/ExactArithTests.java b/jdk/test/java/lang/Math/ExactArithTests.java index 86d7da3e8f1..670c8e35180 100644 --- a/jdk/test/java/lang/Math/ExactArithTests.java +++ b/jdk/test/java/lang/Math/ExactArithTests.java @@ -132,7 +132,56 @@ public class ExactArithTests { fail("FAIL: int Math.multiplyExact(" + x + " * " + y + ")" + "; Unexpected exception: " + ex); } } + try { + // Test incrementExact + int inc = Math.incrementExact(x); + long inc2 = (long) x + 1L; + if ((int) inc2 != inc2) { + fail("FAIL: int Math.incrementExact(" + x + ") = " + inc + "; expected Arithmetic exception"); + } else if (inc != inc2) { + fail("FAIL: long Math.incrementExact(" + x + ") = " + inc + "; expected: " + inc2); + } + } catch (ArithmeticException ex) { + long inc2 = (long) x + 1L; + if ((int) inc2 == inc2) { + fail("FAIL: int Math.incrementExact(" + x + ")" + "; Unexpected exception: " + ex); + } + } + + try { + // Test decrementExact + int dec = Math.decrementExact(x); + long dec2 = (long) x - 1L; + if ((int) dec2 != dec2) { + fail("FAIL: int Math.decrementExact(" + x + ") = " + dec + "; expected Arithmetic exception"); + } else if (dec != dec2) { + fail("FAIL: long Math.decrementExact(" + x + ") = " + dec + "; expected: " + dec2); + } + } catch (ArithmeticException ex) { + long dec2 = (long) x - 1L; + if ((int) dec2 == dec2) { + fail("FAIL: int Math.decrementExact(" + x + ")" + "; Unexpected exception: " + ex); + + } + } + + try { + // Test negateExact + int neg = Math.negateExact(x); + long neg2 = -((long)x) ; + if ((int) neg2 != neg2) { + fail("FAIL: int Math.negateExact(" + x + ") = " + neg + "; expected Arithmetic exception"); + } else if (neg != neg2) { + fail("FAIL: long Math.negateExact(" + x + ") = " + neg + "; expected: " + neg2); + } + } catch (ArithmeticException ex) { + long neg2 = (long) x - 1L; + if ((int) neg2 == neg2) { + fail("FAIL: int Math.negateExact(" + x + ")" + "; Unexpected exception: " + ex); + + } + } } /** @@ -224,6 +273,39 @@ public class ExactArithTests { } } + try { + // Test incrementExact + resultBig = xBig.add(BigInteger.ONE); + long inc = Math.incrementExact(x); + checkResult("long Math.incrementExact", x, 1L, inc, resultBig); + } catch (ArithmeticException ex) { + if (inLongRange(resultBig)) { + fail("FAIL: long Math.incrementExact(" + x + "); Unexpected exception: " + ex); + } + } + + try { + // Test decrementExact + resultBig = xBig.subtract(BigInteger.ONE); + long dec = Math.decrementExact(x); + checkResult("long Math.decrementExact", x, 1L, dec, resultBig); + } catch (ArithmeticException ex) { + if (inLongRange(resultBig)) { + fail("FAIL: long Math.decrementExact(" + x + "); Unexpected exception: " + ex); + } + } + + try { + // Test negateExact + resultBig = xBig.negate(); + long dec = Math.negateExact(x); + checkResult("long Math.negateExact", x, 0L, dec, resultBig); + } catch (ArithmeticException ex) { + if (inLongRange(resultBig)) { + fail("FAIL: long Math.negateExact(" + x + "); Unexpected exception: " + ex); + } + } + try { // Test toIntExact int value = Math.toIntExact(x);